SPA,Single Page Application 单页应用
- 将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript和CSS
- 一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转
- 利用JavaScript动态的变换HTML的内容, 从而实现UI与用户的交互
MPA,Mutiple Page Application 多页面应用
- 每个页面都是一个主页面,都是独立的;
- 当我们访问一个页面时,需要重新加载HTML、Javascript和CSS,公共文件则按需下载
- 适用于对SEO要求很高的应用
- https://blog.csdn.net/qq_30136729/article/details/122938813
MPA配置
要修改的地方
- config/paths.js
- config/webpack.config.js
- entry
- output
- plugins
- src目录修改
- scripts/start, build目录修改

完成一个独立的 SPA项目配置,然后复制这个项目的配置,并重新命名
paths.js
新增入口文件
module.exports = {// MPAappHtml: resolveApp('public/index.html'),appLoginHtml: resolveApp('public/login.html'),appHomeHtml: resolveApp('public/home.html'),appListHtml: resolveApp('public/list.html'),appIndexJs: resolveModule(resolveApp, 'src/index'),appLoginJs: resolveModule(resolveApp, 'src/Login'),appHomeJs: resolveModule(resolveApp, 'src/Home'),appListJs: resolveModule(resolveApp, 'src/List'),}
resolveModule的文件后缀是 .js
const resolveModule = (resolveFn, filePath) => {// 如果有后缀,就用后缀名, 否则用 jsconst extension = moduleFileExtensions.find(extension =>fs.existsSync(resolveFn(`${filePath}.${extension}`))) ?? 'js';return resolveFn(`${filePath}.${extension}`);};
webpack.config.js
修改 entry, plugins
去掉 build后的文件哈希后缀 [hash].js,[contenthash:8].css
�
function mpaHtmlWebpackPlugin(template = paths.appHtml, filename = 'index') {return new HtmlWebpackPlugin(Object.assign({},{inject: true,template,filename: `${filename}.html`,chunks: [filename] // chunks 为代码块,如果不写,默认引入 entry中所有文件},isEnvProduction? {minify: {removeComments: true,collapseWhitespace: true,removeRedundantAttributes: true,useShortDoctype: true,removeEmptyAttributes: true,removeStyleLinkTypeAttributes: true,keepClosingSlash: true,minifyJS: true,minifyCSS: true,minifyURLs: true,},}: undefined))}const config = {entry: {index: paths.appIndexJs,login: paths.appLoginJs,home: paths.appHomeJs,list: paths.appListJs,},output: {// '[name].[contentHash:8].js'filename: '[name].js', // [name] 对应入口的文件名},plugins: [// 入口有几个页面就配置几个实例mpaHtmlWebpackPlugin(paths.appHtml, 'index'),mpaHtmlWebpackPlugin(paths.appLoginHtml, 'login'),mpaHtmlWebpackPlugin(paths.appHomeHtml, 'home'),mpaHtmlWebpackPlugin(paths.appListHtml, 'list'),]}
htmlWebpackPlugin 插件会生成页面,配置插件 htmlWebpackPlugin,生成多页面
chunks 为代码块,默认引入 entry 中所有文件
Failed to compile.
Cannot read properties of undefined (reading ‘filter’)
- entry,如果为 字符串,new WebpackManifestPlugin generate 输出的默认值 为 main
- 如果 entry修改为 {}, 就没有 main 这个属性了,导致
- const entrypointFiles = entrypoints.main.filter 报错

entry: paths.appIndexJs,// entrypoints.main.filterentrypoints {main: [ 'static/css/main.ba17183d.css', 'static/js/main.076e2cc7.js' ]}
解决
const entrypointFiles = Object.values(entrypoints).flat(1).filter(fileName => !fileName.endsWith('.map'))// entry 多入口的数据const entrypoints = {index: [ 'static/css/index.ba17183d.css', 'static/js/index.5a4e7c32.js' ],login: [ 'static/css/login.ba17183d.css', 'static/js/login.04b67759.js' ],home: [ 'static/css/home.ba17183d.css', 'static/js/home.1714507a.js' ],list: [ 'static/css/list.ba17183d.css', 'static/js/list.e9f4436b.js' ]}
scripts
start 启动前检查依赖文件
// Warn and crash if required files are missing 启动前检查依赖文件if (!checkRequiredFiles([paths.appHtml,paths.appIndexJs,paths.appHomeHtml,paths.appHomeJs])) {process.exit(1);}

LICENSE.txt
webpack5进行打包时,多出了一个 LICENSE.txt的文件
解决:extractComments: false
默认为true,将注释提取到单独的 LICENSE.txt文件
https://webpack.js.org/plugins/terser-webpack-plugin/#extractcomments
const config = {optimization: {minimize: isEnvProduction,minimizer: [// This is only used in production mode 压缩 jsnew TerserPlugin({extractComments: false,terserOptions: {}})]}}
Webpack 5 默认压缩代码工具为terser-webpack-plugin,无需安装,默认使用
