Webpack:链接加载器

dod*_*0ro 4 webpack

ejs-loader当我单独使用和时,一切正常html-loader

<body>
    <%= require('./header.html')({x:1})  %>
</body>

// compiles to:

<body>
    <header><div>1</div></header>
</body>
Run Code Online (Sandbox Code Playgroud)

但是当我链接它们时,我得到的是 js 代码而不是 html:

module.exports = function (obj) {
obj || (obj = {});
var __t, __p = '';
with (obj) {
__p += '\n<body>\n  ' +
((__t = ( require('./header.html')({x:1})  )) == null ? '' : __t) +
'\n</body>';

}
return __p
}
Run Code Online (Sandbox Code Playgroud)

发生了什么事以及如何解决?

这是我的配置:

const config = {
    //...
    module: {
        rules: [
            {
                test: /\.html$/,
                use: ['html-loader', 'ejs-loader']
            }
        ]
    },
    //...
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './src/index.html',
        })
    ]

}
Run Code Online (Sandbox Code Playgroud)

Pha*_*ord 5

我现在正在努力解决同样的问题并找到了答案。

首先,我们需要了解加载器是如何工作的。简而言之:它们接受任何文件类型作为输入,但加载器的输出始终是 JS,然后 webpack 执行该文件以获得最终输出。

ejs-loader 和 html-loader 都期望 html 代码作为其输入。当我们链接加载器时,第二个加载器接收的不是 HTML,而是第一个加载器返回的 javascript。所以我们需要从 JS 生成 HTML。为此,我编写了一个简单的加载器,需要将其放在 html 加载器和 ejs 加载器之间。

我们称之为“loader.js”:

module.exports = function (source) {
    let x = eval(source);
    let z = x();
    return z;
}
Run Code Online (Sandbox Code Playgroud)

Webpack 配置将是:

module: {
    rules: [
        {
            test: /\.html$/,
            use: ['html-loader', path.resolve('loader.js'), 'ejs-loader']
        }
    ]
},
Run Code Online (Sandbox Code Playgroud)

重要提示:顺序或加载程序很重要。如果我在链中交换 ejs 和 html 加载器,则 eval 会失败,因为 html-loader 返回 js 代码,其中包含 eval 无法解析的其他导入。然而,ejs-loader 返回纯独立的代码,该代码使用 eval() 成功求值。

因此,因为加载器以相反的顺序执行,所以我们将 ejs 放在前面(意思是 - 在数组的末尾),然后是中间加载器,最后是 html 加载器(在数组的开头)

更新:有一个现成的加载器可以完成这项工作,称为extract-loader. 简单的方法eval在很多情况下会失败,但extract-loader总是可以正常工作。