使用 webpack 的多个 html 文件

我试图在一个项目中做一些事情,我不知道这是否可行,我在一个错误的方式或误解的东西。我们使用 webpack,其思想是提供多个 html 文件。

Localhost: 8181-> services index.html
Localhost: 8181/example.html-> services example.html

我试图通过设置多个入口点来做到这一点,遵循 文件:

文件夹结构如下:

/
|- package.json
|- webpack.config.js
/src
|- index.html
|- example.html
| /js
|- main.js
|- example.js

Webpack.config.js:

...
entry: {
main: './js/main.js',
exampleEntry: './js/example.js'
},
output: {
path: path.resolve(__dirname, 'build', 'target'),
publicPath: '/',
filename: '[name].bundle.js',
chunkFilename: '[id].bundle_[chunkhash].js',
sourceMapFilename: '[file].map'
},
...

Html

<!DOCTYPE html>
<html
<head>
...
<link type="text/css" href="/style/default.css">
</head>
<body>
<div id="container"></div>
<script src="/main.bundle.js"></script>
</body>
</html>

.html:

<!DOCTYPE html>
<html
<head>
...
<link type="text/css" href="/style/default.css">
</head>
<body>
...
<script src="/example.bundle.js"></script>
</body>
</html>

有人知道我做错了什么吗?

谢谢你。

79916 次浏览

See an entrypoint as the root of a tree that references many other assets like javascript modules, images, templates and so on. When you define more than one entrypoint, you basically split your assets into so called chunks to not have all your code and assets in one single bundle.

我认为您想要实现的是为不同的应用程序提供多个“ index.html”,这些应用程序也指向您已经用入口点定义的资产的不同块。

复制一个 index.html 文件,甚至生成一个包含对这些入口点的引用的文件,都不是由入口点机制来处理的,而是由入口点机制来处理。处理 html 页面的一个基本方法是使用 html-webpack-plugin,它不仅可以复制 html 文件,而且具有广泛的模板机制。如果您希望在 bundle 后面加上一个 bundle 散列,以避免在更新应用程序时出现浏览器缓存问题,那么这尤其有帮助。

因为已经将名称模式定义为 [id].bundle_[chunkhash].js,所以不能再将 javascript 包引用为 main.bundle.js,因为它将被称为类似于 main.bundle_73efb6da.js的东西。

看一下 Html-webpack-plugin,尤其是与你的用例相关的:

You should probably have something like that in the end (warning: not tested)

plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'src/index.html',
chunks: ['main']
}),
new HtmlWebpackPlugin({
filename: 'example.html',
template: 'src/example.html',
chunks: ['exampleEntry']
})
]

请注意在块数组中引用入口点的名称,因此在您的示例中这应该是 exampleEntry。也许将模板移动到特定的文件夹中而不是直接放在根 src 文件夹中也是一个好主意。

希望这个能帮上忙。

如果不需要两个不同的构建,也可以使用 复制 Webpack 插件,即假设您只想使用相同的 main.bundle.js提供不同的 HTML。

The plugin is really dead simple (only tested in webpack v4):

const CopyWebpackPlugin = require('copy-webpack-plugin');


const config = {
plugins: [
new CopyWebpackPlugin([
{ from: './src/example.html', to: './example.html' }
])
]
}

然后在 example.html中你可以从 index.html加载构建。例如:

<!DOCTYPE html>
<html
<head>
...
<title>Example</title>
</head>
<body>
<div id="container"> Show an example </div>
<script src="main.bundle.js"></script>
</body>
</html>

使用 HtmlWebpackPluginWebpack中使用 多重 HTML文件:

通过直接嵌入下面的代码修改 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');


let htmlPageNames = ['example1', 'example2', 'example3', 'example4'];
let multipleHtmlPlugins = htmlPageNames.map(name => {
return new HtmlWebpackPlugin({
template: `./src/${name}.html`, // relative path to the HTML files
filename: `${name}.html`, // output HTML files
chunks: [`${name}`] // respective JS files
})
});


module.exports = {
entry: {
main: './js/main.js',
example1: './js/example1.js',
//... repeat until example 4
},
module: {
//.. your rules
};
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
chunks: ['main']
})
].concat(multipleHtmlPlugins)
  

};

您可以根据需要向 htmlPageNames数组中添加尽可能多的 HTML 页面。确保每个 HTML 和相应的 JS 文件具有相同的名称(上面的代码假设)。

假设 Webpack ^ 4.44.1,还有另一种解决方案,即在 JS/TS 应用程序中导入 HTML。

示例 webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');




module.exports = {
entry: { app: './src/index.ts' },


mode: 'development',
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Development',
template: path.join(path.resolve(__dirname, 'src'), 'index.ejs')
}),
],
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
include: [path.resolve(__dirname, 'src')],
exclude: /node_modules/,
},
{
test: /\.html$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
],
// this exclude is required
exclude: path.join(path.resolve(__dirname, 'src'), 'index.html')
}
],
},
resolve: {
extensions: ['.ts', '.js'],
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 3900
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};

相应的应用程序

import './about.html';
    

console.log('this is a test');

Index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Question</title>
</head>
<body>
<a href="./about.html">About</a>
</body>
</html>

关于

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About</title>
</head>
<body>
<p>This is an about page</p>
</body>
</html>

Webpack will copy about.html to the corresponding 输出 folder.

plugins: [
...templates.map(template => new HtmlWebpackPlugin(template))
]

This code would help if you have a lot of templates :)

RICHARD ABRAHAM 的解决方案对我很有效,我还增加了 fsreaddir 函数来检测 html 文件

let htmlPageNames = [];
const pages = fs.readdirSync('./src')
pages.forEach(page => {
if (page.endsWith('.html')) {
htmlPageNames.push(page.split('.html')[0])
}
})
console.log(htmlPageNames);

返回@andreas-jägle point。使用‘ html-webpack-plugin’: html-webpack-plugin Html-webpack-plugin。然而优化你的代码以避免文件的 复制品:

  plugins: ['index', 'page1', 'page2'].map(
(file) =>
new HtmlWebpackPlugin({
template: './src/' + file + '.html',
inject: true,
chunks: ['index', 'main'],
filename: './' + file + '.html' //relative to root of the application
})
)