起因
最近再做一个 react 的多页应用,在修改过 webpack
的 entry
及 HtmlWebpackPlugin
等配置后,进行打包测试,运行 npm run build
后控制台报错:
Creating an optimized production build...
Failed to compile.
Cannot read property 'filter' of undefined
分析
因为控制台并没有明确提示错误位置,所以开始在修改的 webpack.config.js
文件中用到 filter
方法的地方排查。开始以为是 entry
配置有问题,但经过测试发现问题不在 entry
。
之后对比了不同版本的 create-react-app
生成的 webpack.config.js
文件中所用到 filter
方法的地方,发现新的配置文件中 ManifestPlugin
的配置项发生了变化。
// 这是旧版的 ManifestPlugin 配置
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: paths.publicUrlOrPath,
}),
// 这是新版的 ManifestPlugin 配置
new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: paths.publicUrlOrPath,
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')
);
console.log('!!', entrypointFiles)
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
可以看到配置项中多了 generate
这一属性,其中就有用到 filter
方法。其中 entrypoints.main
调用了 filter
方法,经过输出得知 entrypoints.main
的值是与 entry
配置对应的。
默认情况下 entry
的值是一个 Array
,因此 entrypoints.main
的值也一个 Array
,但是配置多页面时是把其改为了 Object
,Object
没有 filter
方法,因此报错。
解决方案
- 方案一:删除
generate
属性,保持与老版本生成的create-react-app
生成的ManifestPlugin
配置一致。 - 方案二:修改
entrypoints.main
中的main
为你在entry
中配置的项目首页的key
。我的entry
配置中首页的key
为index
,因此可改为entrypoints.index
。
再次运 npm run build
即可编译成功。