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 = {
// MPA
appHtml: 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) => {
// 如果有后缀,就用后缀名, 否则用 js
const 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.filter
entrypoints {
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 压缩 js
new TerserPlugin({
extractComments: false,
terserOptions: {}
})
]
}
}
Webpack 5 默认压缩代码工具为terser-webpack-plugin,无需安装,默认使用