如何使用 nunjucks 文件作为 webpack 的入口点?
How do I use a nunjucks file as an entry point with webpack?
我和 ejs 一起看过这个 post。但是如何使用 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']
}]
};
这可能很长,但请耐心等待:
问题是 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 并且会给您一个错误。
我在寻找解决方案时也遇到了这个问题,公认的解决方案对我不起作用,所以我发现将我的解决方案添加到混合中是合适的,关于如何使用 nunjucks 作为 web-pack 中的条目.
我一直 运行 解决具有多个入口点的问题,直到最后我找到了以下 repo 并解决了这个问题。
在撰写本文时请注意,npm 注册表尚未更新最近的代码更改,因此您需要 link 直接从您 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())
};
}
与其混合使用加载程序 (nunjucks-loader) 和 Webpack 插件 (HtmlWebpackPlugin),不如尝试 nunjucks-webpack-plugin。
它看起来是 HtmlWebpackPlugin 的一个很好的替代品!
我和 ejs 一起看过这个 post。但是如何使用 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']
}]
};
这可能很长,但请耐心等待:
问题是 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 并且会给您一个错误。
我在寻找解决方案时也遇到了这个问题,公认的解决方案对我不起作用,所以我发现将我的解决方案添加到混合中是合适的,关于如何使用 nunjucks 作为 web-pack 中的条目.
我一直 运行 解决具有多个入口点的问题,直到最后我找到了以下 repo 并解决了这个问题。
在撰写本文时请注意,npm 注册表尚未更新最近的代码更改,因此您需要 link 直接从您 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())
};
}
与其混合使用加载程序 (nunjucks-loader) 和 Webpack 插件 (HtmlWebpackPlugin),不如尝试 nunjucks-webpack-plugin。
它看起来是 HtmlWebpackPlugin 的一个很好的替代品!