【问题标题】:How do I use a nunjucks file as an entry point with webpack?如何使用 nunjucks 文件作为 webpack 的入口点?
【发布时间】:2019-02-05 17:05:49
【问题描述】:

我在ejs 上看到过这篇帖子。但是如何使用 webpack 实现相同的功能?

我尝试将 nunjucks-loader 与 html-webpack-plugin 结合使用,但出现以下错误:[nunjucks-loader] non-web targets are not supported

这是我的代码:

这是配置:

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  //template: './client/index.html',
  filename: 'index.html',
  inject: 'body',
  template: 'nunjucks-html-loader!./client/templates/index.njk',
});

module: {
    loaders: [
      {
        test: /\.html$/,
        use: ['html-loader']
      }, 
      {
        test: /\.|njk|nunjucks$/,
        use: ['nunjucks-loader']
      }]
  };

【问题讨论】:

    标签: webpack nunjucks html-webpack-plugin


    【解决方案1】:

    这可能很长,但请多多包涵:

    问题在于 nunjucks-loader 将其作为 JavaScript 文件 (According to the first paragraph) 传递。

    改为使用nunjucks-html-loader

    使用 npm 或 yarn 安装它: 首先,我们安装 nunjucks-html-loader:

    npm i nunjucks-html-loader -D
    

    yarn add nunjucks-html-loader -D
    

    我还建议安装(这是可选的)webpack-glob-folder-entries(更多信息)

    npm i webpack-glob-folder-entries -D
    

    yarn add webpack-glob-folder-entries -D
    

    那么,如果我们认为我们有以下文件夹结构:

    - client/
         -templates/
              -index.njk   
              -layout.njk
              -_partials/
    - webpack.config.js
    

    在 index.njk 中我们有这样的东西:

    <!-- index.nunjucks -->
    {% extends "layout.njk" %}
    {% block content %}
       <h1> Here comes my content that is injected to layout.njk!</h1>
    {% endblock %}
    

    我们可以只配置 webpack,设置如下:

    //#1: Define the HTML Webpack Plugin:
    const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
        filename: 'index.html',
        inject: 'body',
    
    // Here is part of the magic, we get the index.njk but we tell
    // webpack to pass it through the nunjucks-html-loader
        template: 'nunjucks-html-loader!./client/templates/index.njk',
      });
    
    // Optional, but highly recommended. Create a returnEntries:
    // Webpack doesn't support glob paths. For the nunjucks-html-loader
    // we need each path to be specified for it to work (YES, even subdirectories!)
    
    function returnEntries(globPath){
      let entries = glob_entries(globPath, true);
      let folderList = new Array();
      for (let folder in entries){
         folderList.push(path.join(__dirname, entries[folder]));
      }
      return folderList;
    }
    
    module.exports = {
    // You should not have this the same. This is from my site. Go down to see the important part:
        entry: './client/index.js',
        output: {
          filename: production ? '[name]-[hash].js' : 'bundle.js',
          path: __dirname + '/dist',
          publicPath: 'dist/' //Important!!! : https://github.com/webpack/webpack/issues/1426
        },
       // #2  We load the HTMLWebpackPluginConfig
        plugins: [
          HtmlWebpackPluginConfig,
          extractTextPlugin
        ],
    
        resolve: {
          extensions: ['.Webpack.js', '.web.js', '.ts', '.js', '.tsx']
        },
    
    // HERE is the important part
        module: {
          loaders: [
            {
              // HTML LOADER
              // Super important: We need to test for the html 
              // as well as the nunjucks files
              test: /\.html$|njk|nunjucks/,
              use: ['html-loader',{
                loader: 'nunjucks-html-loader',
                options : {
                   // Other super important. This will be the base
                   // directory in which webpack is going to find 
                   // the layout and any other file index.njk is calling.
                   searchPaths: [...returnEntries('./client/templates/**/')]
                   // Use the one below if you want to use a single path.
                   // searchPaths: ['./client/templates'],
                }
              }]
            }
            ]
        }
    }
    

    然后运行webpack,你就可以开始了?。

    注意:

    searchPaths: ['./client/templates'],
    

    很重要。这是 Webpack 用于查找 index.njk 正在调用的任何文件的基本路径。尝试稍微弄乱路径以了解它是如何工作的。但不要删除它。

    此外,webpack 支持 glob 目录。我使用webpack-glob-folder-entries 编写了一个辅助函数,它为我提供了 nunjucks-html-loader 可以查看的所有子文件夹的列表。请理解,如果您不指定文件夹(即使它是子目录),它将不起作用

    换句话说,如果你想使用 _partials 文件夹(如上),并且你没有将它指定为 './client/templates/_partials',加载器将不会拾取它!

    还有,

     test: /\.html$|njk|nunjucks/,
    

    不用于 index.njk,但 用于 index.njk 调用的文件,在本例中为 layout.njk。未能包含 njk 或 nunjucks 扩展将不会加载 layout.njk,它会给你一个错误。

    【讨论】:

    • 来这里说声谢谢!花了一段时间试图解决这个问题。
    【解决方案2】:

    我在寻找解决方案时也遇到了这个问题,接受的解决方案对我不起作用,所以我发现将我的解决方案添加到组合中是合适的,关于如何使用 nunjucks 作为 web-pack 中的条目。

    我一直遇到有多个入口点的问题,直到最后我找到了以下 repo 并解决了这个问题。

    使用Nunjucks-Isomorphic-Loader

    在撰写本文时请注意,npm 注册表尚未随最近的代码更改而更新,因此您需要直接从 package.json 链接到 repo

    这是我的:proof of concept repository

    下面是我写的 webpack 配置供参考:

    const webpack = require('webpack');
    const path = require('path');
    const fs = require('fs');
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    // Notice, the below methods searches src/components and adds a HtmlWebpackPlugin for each folder
    // This is required, even for subfolders otherwise you nunjuck includes will nto work.
    const d = './src/components';
    const entryFolders = fs.readdirSync(path.resolve(d))
    			.map(f => path.join(__dirname, path.join(d, f))  )
    			.filter(f => fs.statSync(f).isDirectory());
    
    function getHtmlComponentPlugins() {
    	return entryFolders.map(templatePath => {
    		const name = templatePath.split('\\').pop()
    
    		const sett = {
    	    	customData: { foo: 'bar' },
    	    	filename: path.relative(__dirname, templatePath.replace('src\\', '') + `\\${name}.html`),
    	    	template: templatePath + `\\${name}.njk`
    	  	};
    
    		return new HtmlWebpackPlugin(sett)
    	});
    }
    
    module.exports = function() {
    	return {
    		devtool: '#source-map',
    		mode: 'development',
    		entry: [
    			'./src/index.js'
    		],
    		output: {
    			path: path.resolve(__dirname, 'dist')
    		},
    	    resolve: {
    	      extensions: [ '.js' ]
    	    },
    		module: {
    		    rules : [
    				{
    				  	test: /\.(njk|nunjucks|html|tpl|tmpl)$/,
    				  	use: [
    				    	{
    				    		loader: 'nunjucks-isomorphic-loader',
    				      		query: {
    				        	root: [
    				        		path.resolve(__dirname, 'src'),
    				        		
    				        	].concat(entryFolders)
    				      	}
    				    }
    				  ]
    				}
    		    ]
    		},
    		plugins: [
    		  new HtmlWebpackPlugin({
    		    customData: { foo: 'bar' },
    		    filename: 'index.html',
    		    template: 'src/index.njk'
    		  })
    		].concat(getHtmlComponentPlugins())
    	};
    }

    【讨论】:

      【解决方案3】:

      与其混合使用加载器 (nunjucks-loader) 和 Webpack 插件 (HtmlWebpackPlugin),不如试试 nunjucks-webpack-plugin

      它看起来是 HtmlWebpackPlugin 的一个很好的替代品!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-03
        • 2021-06-04
        • 1970-01-01
        • 1970-01-01
        • 2021-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多