SPA,Single Page Application 单页应用

  • 将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript和CSS
  • 一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转
  • 利用JavaScript动态的变换HTML的内容, 从而实现UI与用户的交互

MPA,Mutiple Page Application 多页面应用

MPA配置

要修改的地方

  1. config/paths.js
  2. config/webpack.config.js
    1. entry
    2. output
    3. plugins
  3. src目录修改
  4. scripts/start, build目录修改

image.png

完成一个独立的 SPA项目配置,然后复制这个项目的配置,并重新命名
image.png

paths.js

新增入口文件

  1. module.exports = {
  2. // MPA
  3. appHtml: resolveApp('public/index.html'),
  4. appLoginHtml: resolveApp('public/login.html'),
  5. appHomeHtml: resolveApp('public/home.html'),
  6. appListHtml: resolveApp('public/list.html'),
  7. appIndexJs: resolveModule(resolveApp, 'src/index'),
  8. appLoginJs: resolveModule(resolveApp, 'src/Login'),
  9. appHomeJs: resolveModule(resolveApp, 'src/Home'),
  10. appListJs: resolveModule(resolveApp, 'src/List'),
  11. }

resolveModule的文件后缀是 .js

  1. const resolveModule = (resolveFn, filePath) => {
  2. // 如果有后缀,就用后缀名, 否则用 js
  3. const extension = moduleFileExtensions.find(extension =>
  4. fs.existsSync(resolveFn(`${filePath}.${extension}`))
  5. ) ?? 'js';
  6. return resolveFn(`${filePath}.${extension}`);
  7. };

webpack.config.js

修改 entry, plugins
去掉 build后的文件哈希后缀 [hash].js,[contenthash:8].css

  1. function mpaHtmlWebpackPlugin(template = paths.appHtml, filename = 'index') {
  2. return new HtmlWebpackPlugin(
  3. Object.assign(
  4. {},
  5. {
  6. inject: true,
  7. template,
  8. filename: `${filename}.html`,
  9. chunks: [filename] // chunks 为代码块,如果不写,默认引入 entry中所有文件
  10. },
  11. isEnvProduction
  12. ? {
  13. minify: {
  14. removeComments: true,
  15. collapseWhitespace: true,
  16. removeRedundantAttributes: true,
  17. useShortDoctype: true,
  18. removeEmptyAttributes: true,
  19. removeStyleLinkTypeAttributes: true,
  20. keepClosingSlash: true,
  21. minifyJS: true,
  22. minifyCSS: true,
  23. minifyURLs: true,
  24. },
  25. }
  26. : undefined
  27. )
  28. )
  29. }
  30. const config = {
  31. entry: {
  32. index: paths.appIndexJs,
  33. login: paths.appLoginJs,
  34. home: paths.appHomeJs,
  35. list: paths.appListJs,
  36. },
  37. output: {
  38. // '[name].[contentHash:8].js'
  39. filename: '[name].js', // [name] 对应入口的文件名
  40. },
  41. plugins: [
  42. // 入口有几个页面就配置几个实例
  43. mpaHtmlWebpackPlugin(paths.appHtml, 'index'),
  44. mpaHtmlWebpackPlugin(paths.appLoginHtml, 'login'),
  45. mpaHtmlWebpackPlugin(paths.appHomeHtml, 'home'),
  46. mpaHtmlWebpackPlugin(paths.appListHtml, 'list'),
  47. ]
  48. }

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 报错

image.png

  1. entry: paths.appIndexJs,
  2. // entrypoints.main.filter
  3. entrypoints {
  4. main: [ 'static/css/main.ba17183d.css', 'static/js/main.076e2cc7.js' ]
  5. }

解决

  1. const entrypointFiles = Object.values(entrypoints).flat(1).filter(
  2. fileName => !fileName.endsWith('.map')
  3. )
  4. // entry 多入口的数据
  5. const entrypoints = {
  6. index: [ 'static/css/index.ba17183d.css', 'static/js/index.5a4e7c32.js' ],
  7. login: [ 'static/css/login.ba17183d.css', 'static/js/login.04b67759.js' ],
  8. home: [ 'static/css/home.ba17183d.css', 'static/js/home.1714507a.js' ],
  9. list: [ 'static/css/list.ba17183d.css', 'static/js/list.e9f4436b.js' ]
  10. }

scripts

start 启动前检查依赖文件

  1. // Warn and crash if required files are missing 启动前检查依赖文件
  2. if (!checkRequiredFiles([
  3. paths.appHtml,
  4. paths.appIndexJs,
  5. paths.appHomeHtml,
  6. paths.appHomeJs
  7. ])) {
  8. process.exit(1);
  9. }

image.png

LICENSE.txt

webpack5进行打包时,多出了一个 LICENSE.txt的文件
image.png
解决:extractComments: false
默认为true,将注释提取到单独的 LICENSE.txt文件
https://webpack.js.org/plugins/terser-webpack-plugin/#extractcomments

  1. const config = {
  2. optimization: {
  3. minimize: isEnvProduction,
  4. minimizer: [
  5. // This is only used in production mode 压缩 js
  6. new TerserPlugin({
  7. extractComments: false,
  8. terserOptions: {}
  9. })
  10. ]
  11. }
  12. }

Webpack 5 默认压缩代码工具为terser-webpack-plugin,无需安装,默认使用