create-react-app创建的项目配置多入口MPA模式。报Cannot read property ‘filter’ of undefined
多入口配置
一.首先eject项目
执行npx create-react-app train-ticket,安装react项目。这时候package.json中react-srcipt已经集成了所有的逻辑,此时需要个性化的配置,需要执行npm run eject,将webpack配置文件拉出,并执行npm install安装依赖。执行完上述命令之后,文件树如图所示
二.配置webpack文件
①在config/webpack.config首先找到配置文件入口entry处,这里只配置一个入口文件,要将这里改成多入口的模式,因此应该将这里改成对象的形式。
entry:[
paths.appIndexJs,
isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')
].filter(Boolean),
给每一个不同的入口起不同的名字
entry:{
index: [paths.appIndexJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean),
query: [paths.appQueryJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean),
ticket: [paths.appTicketJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean),
order: [paths.appOrderJs, isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient')].filter(Boolean),
②这里的入口文件的路径写在paths文件中,因此到config/paths中添加这几个变量。在项目中这几个文件被放在新建的单独的文件夹中,分别放在index,order,ticket,query中的index.js中。
在path中添加如下变量
appIndexJs: resolveModule(resolveApp, 'src/index/index'),
appQueryJs: resolveModule(resolveApp, 'src/query/index'),
appTicketJs: resolveModule(resolveApp, 'src/ticket/index'),
appOrderJs: resolveModule(resolveApp, 'src/order/index'),
③最后修改HtmlWebpackPlugin,生成四个不同的html引入这些入口打包后的文件。生成几个页面,就要配置几个HtmlWebpackPlugin,filename为最后的html名称,chunkwei所引用的打包文件。
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
filename: 'index.html',
chunk: ['index'],
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
filename: 'query.html',
chunk: ['query'],
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
在这里同样需要四个html模板,在public目录下创建,并在config/paths文件中指定路径。
appHtml: resolveApp('public/index.html'),
appQuery: resolveApp('public/query.html'),
appTicket: resolveApp('public/ticket.html'),
appOrder: resolveApp('public/iorder.html'),
三.运行打包命令
当配置完之后,运行打包命令,控制台报错,Cannot read property ‘filter’ of undefined,起初以为是entry里面的filter报错,后来发现entry里面就算不写filter也是会报错,最后定位到错误原因在ManifestPlugin
ManifestPlugin这个插件的作用是生成一份.json的文件,通过该文件的映射关系可以让我们知道webpack是如何追踪所有模块并映射到输出bundle中的。我们先来看原始的配置,这里fileName设置了输出文件名asset-manifest.json,publicPath设置了输出路径,最终要的是最后一个generate参数,自定义了输出的内容,里面有一段是取entrypoints.main,这是针对单一入口的配置,因为单一入口不指定name的情况默认name为main,当改成多入口的方式了之后这里面在entrypoints中自然是读取不到main这个值的,因此就报错,这里将generate这个参数去掉,恢复其默认值即可,或者将entrypoints这个key去掉。
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
generate: (seed, files, entrypoints) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
const entrypointFiles = entrypoints.main.filter(
fileName => !fileName.endsWith('.map')
);
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
如图所示为单入口的entrypoints对象
如图所示为打印出修改多入口后的的entrypoints对象