前言
目前,大多数时候前端项目是单页应用,只有一个index.html
文件。然而,有些时候我们需要使用到多页应用,即多个html
文件。
比如,笔者有一个PC端项目,后期迭代时需要支持移动端,由于交互功能一致,但是UI变化大,不合适采用自适应布局的开发方式。因此将移动端组件重写,提取相同的JS公用,将移动端页面打包成h5.html
访问,PC端仍是index.html
访问。这就涉及到了打包时的多页配置。
多页配置方案
使用CRA
脚手架创建的react项目,无法灵活地配置webpack
,如果我们想要修改配置,可以采用2种方案。
-
使用
eject
命令将配置文件完全弹射出来,由开发者自由地修改,但是该操作是不可逆的,需谨慎操作。弹射出的
webpack
文件包含scripts
与config
文件夹,其中scripts
内包含dev/build/test
等脚本命令js,config
就是webpack的相关打包js。其中,调整多页配置,在config中的
paths.js
与webpack.config.js
中修改。// paths.js module.exports = { // ... + appH5Js: resolveModule(resolveApp, 'src/h5/index'), }
// webpack.config.js // 修改入口文件,出口文件以及html插件 - entry: paths.appIndexJs, + entry: { + main: paths.appIndexJs, + admin: paths.appH5Js, + }, output: { // ..., filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js - : isEnvDevelopment && 'static/js/bundle.js', + : isEnvDevelopment && 'static/js/[name].bundle.js', } plugins: [ // ... new HtmlWebpackPlugin( Object.assign( {}, { inject: true, template: paths.appHtml, + chunks: ['main'], }, // ... ) ), + // 新增下列配置,可以复制上方的默认HtmlWebpackPlugin插件配置,再相应修改 + new HtmlWebpackPlugin( + Object.assign( + {}, + { + inject: true, + template: paths.appHtml, // template默认是index.html,如果不需要额外的html文件,可以不填写 + filename: 'h5.html', + chunks: ['h5'], + }, + // ... + ) + ) ]
修改这2份文件即可完成配置,是不是超级简单吶😬😬
-
使用
craco
等工具,优雅地重写配置。
craco
多页配置
笔者也是在实际项目中使用了craco
。
- 参考文章:
首先,在项目目录最外层新增craco.config.js
文件,采用module.exports
导出配置对象,其中有一个属性webpack
,里面包含了关于webpack的相关配置,这里就是主战场。
// craco.config.js
module.exports = {
// ...
webpack: {
alias: { /* ... */ },
plugins: {
add: [ /* ... */ ],
remove: [ /* ... */ ],
},
configure: { /* ... */},
configure: (webpackConfig, { env, paths }) => {
/* ... */
return webpackConfig;
},
},
};
其中,configure
是一个函数也可以是对象。当采用对象覆盖无法完成的配置,可以在函数内完成覆盖。经过笔者实操,建议按下方配置一样采用函数写法,避免过多验证浪费表情😖😖。
例如本次需要修改的多页应用配置。
-
在
entry
下新增入口文件,新增h5/index.js打包入口。module.exports = { webpack: { //... configure(webpackConfig, {env, paths}){ webpackConfig.entry = { main: paths.appIndexJs, // 原来默认的配置 h5: path.resolve(__dirname, 'src/h5/index') }; return webpackConfig; } } }
- env:当前的
NODE_ENV
(development
,production
,etc.) - paths:包含了所有
CRA
使用的路径
- env:当前的
-
修改
output
配置,以文件名作为打包后js的文件名。module.exports = { webpack: { //... configure(webpackConfig, {env, paths}){ webpackConfig.ouput = { ...webpackConfig.output, filename: 'static/js/[name].bundle.js' } return webpackConfig; } } }
output
下还有其它旧配置,解构赋值,新增配置覆盖旧配置。 -
新增HTML配置,使用
HtmlWebpackPlugin
插件将打包生成的js/css文件注入到h5.html
。module.exports = { webpack: { //... plugins: [ new HtmlWebpackPlugin( { inject: true, filename: 'h5.html', chunks: ['h5'], } ), ] } }
这里关于
HtmlWebpackPlugin
的配置还有许多,其中template
不写,默认是index.html。如果需要另外的html作为模板,则需要配置对应的绝对路径。
CRA中的new HtmlWebpackPlugin
配置中没有chunks
项,表明打包产物都会注入到index.html中。如果不想h5相关资源注入到index.html中,可以遍历plugins
找到HtmlWebpackPlugin
的实例,明确chunks
的值,确保index.html中只注入main
相关资源。
module.exports = {
webpack: {
//...
configure(webpackConfig, {env, paths}){
webpackConfig.plugins.map(item => {
if(item instanceof HtmlWebpackPlugin){
if(!item.userOptions.chunks){
item.userOptions.chunks = ['main'];
}
};
return item;
})
return webpackConfig;
}
}
}
webpackConfig
是所有关于webpack的配置,可以通过console.log
输出配置的所有内容,了解当前的配置,调整对应配置项。
完整的配置:
// craco.config.js
module.exports = {
webpack: {
// ...
// 添加h5.html文件
plugins: [
new HtmlWebpackPlugin(
{
inject: true,
template: path.resolve(__dirname, 'public/h5.html'), // html模板的绝对地址
filename: 'h5.html',
chunks: ['h5'],
},
)
],
configure(webpackConfig, {env, paths}){
const isEnvProduction = env === 'production';
const isEnvDevelopment = env === 'development';
// 添加打包入口文件
webpackConfig.entry = {
main: paths.appIndexJs,
h5: path.resolve(__dirname, 'src/h5/index')
};
// 修改输出文件名
webpackConfig.output = {
...webpackConfig.output,
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/[name].bundle.js'
};
// 默认的index.html HtmlWebpackPlugin配置时没有添加chunks,为了只让main注入到index.html,配置chunks
webpackConfig.plugins.map(item => {
if(item instanceof HtmlWebpackPlugin){
if(!item.userOptions.chunks){
item.userOptions.chunks = ['main'];
}
};
return item;
});
// 最后返回更新后的config
return webpackConfig;
}
}
}
注意:
entry/output
对象是直接覆盖旧配置,因此需要把旧配置解构赋值,新配置放在末尾覆盖旧配置。entry
原先是字符串,新增入口文件需调整成对象,还原上main
的配置,再新增上h5
的配置。(entry
支持对象、数字、字符串格式)- 旧配置中有
HtmlWebpackPlugin
的配置,其中template未配置,默认是以src/index.html为模板文件生成index.html;其中chunks
未配置,默认是将所有打包后的js/css都注入到index.html中。为了将对应的js/css注入到对应的html文件中,需添加chunks
配置。 configure
的第一个参数,是最终使用的配置项,可以console.log查看。
最后
如果一开始对webpack不熟悉,也不知道怎么开始配置,可以新创建一个CRA项目,eject
出配置,边看官方文档,边看弹射出的配置文件,直接复制对应配置到实际项目中,修修改改下即可。
如果启动项目仍有报错,可以在craco.config.js
中configure
中打印webpackConfig
,看看配置项是否如所愿,一般这里进行修改后,项目可以成功启动。
祝好运,End.