关于前端:Angular9-自定义webpack配置拆分入口文件-优化加载速度

35次阅读

共计 5167 个字符,预计需要花费 13 分钟才能阅读完成。

默认 angular 配置:入口文件 size 高达 7MB,DOMContentload 和 load 别离为 3.22s 和 3.43 秒

1、装置 angular-builders

npm install @angular-builders/custom-webpack --save-dev
npm install @angular-devkit/build-angular --save-dev

2. 批改 angular.json 中 build 和 server 的配置

    "architect": {
        ......
        "build": {
            "builder": "@angular-builders/custom-webpack:browser",
            "options": {
                "customWebpackConfig": {"path": "./webpack.config.js"}
            }
        },
        "serve": {
            "builder": "@angular-builders/custom-webpack:dev-server",
            "options": {
                "customWebpackConfig": {"path": "./webpack.config.js"}
            }
        }
    }

3. 自定义 webpack.config.js 配置

const webpack = require('webpack');
const pkg = require('./package.json');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
  optimization: {
    splitChunks: {chunks: 'all', // 共有三个值可选:initial( 初始模块)、async(按需加载模块) 和 all(全副模块)
      minSize: 30000, // 模块超过 30k 主动被抽离成公共模块
      // minChunks: 1, // 模块被援用 >= 1 次,便宰割
      maxAsyncRequests: 5, // 异步加载 chunk 的并发申请数量 <=5
      maxInitialRequests: 5, // 一个入口并发加载的 chunk 数量 <=3
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        angular: {
          name: 'angular',
          test: /[\\/]node_modules[\\/]@angular[\\/]/,
          priority: -8
        },
        monaco_editor: {test: /[\\/]node_modules[\\/](monaco-editor)[\\/]/,
          name: 'monaco-editor',
          priority: -9
        },
        vendors: {
          name: 'vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },

        // 缓存组,会继承和笼罩 splitChunks 的配置
        default: {
          // 模块缓存规定,设置为 false,默认缓存组将禁用
          minChunks: 2, // 模块被援用 >= 2 次,拆分至 vendors 公共模块
          priority: -20, // 优先级
          reuseExistingChunk: true // 默认应用已有的模块
        }
      }
    }
  },
  plugins: [
    new webpack.DefinePlugin({APP_VERSION: JSON.stringify(pkg.version)
    }),
    // new BundleAnalyzerPlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.join(__dirname, 'src/index.html'),
      chunksSortMode: 'manual',
      chunks: ['styles', 'runtime', 'polyfills', 'scripts', 'vendors', 'main'] // 限定程序,main.js 必须在最初
    })
  ]
};

··这里阐明下配置
(1).BundleAnalyzerPlugin
我正文掉了,因为不想编译时候主动启动,我抉择 npm 退出 script 命令,有须要的时候执行命令生成 stat.json 并运行

    "analyze": "webpack-bundle-analyzer dist/stats.json"

(2) DefinePlugin 测试 webpack.config.js 是否被引入。注:ng build 模式或 builder 为 custom-builder 才失效
app.component.ts 里申明

declare var APP_VERSION: string;
@Component({
  selector: 'root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
  ngOnInit(): void {console.log('APP_VERSION:', APP_VERSION);
  }

(3)最重要的是 htmlwebpackplugin
splitChunks 把最次要的 node_modules angular monaco-editor 三个包最次要的大型包都从主入口 main.js 抽出来了。
如果没有用 htmlwebpackplugin,angular.json 默认配置生成的 html,不会引入我新抽出来的 js,配置 mergeRules,mergeStrategies 都不好使。

 "customWebpackConfig": { 
··"path": "./webpack.config.js",
  "mergeRules": {"externals": "replace"}, 
 "mergeStrategies": {"module.rules": "prepend"}, 
 "replaceDuplicatePlugins": true 
}

最终用 htmlwebpackplugin 生成的 html,并批改 angular.json 配置, 把原 html 批改名字

    "index": {
      "input": "src/index.html",
      "output": "index-old.html"
    },

最初附上残缺的 angular.json

  "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dist/onenote",
            "index": {
              "input": "src/index.html",
              "output": "index-old.html"
            },
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets",
              {
                "glob": "**/*",
                "input": "./node_modules/mathjax",
                "output": "/"
              },
              {
                "glob": "**/*",
                "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
                "output": "/assets/"
              },
              {
                "glob": "**/*",
                "input": "./WEB-INF",
                "output": "/WEB-INF/"
              }
            ],
            "styles": [
              "src/styles/theme/light/antd-light.less",
              "src/styles.less",
              "./node_modules/highlight.js/styles/github.css",
              "./node_modules/monaco-editor/min/vs/editor/editor.main.css",
              "./node_modules/github-markdown-css/github-markdown.css"
            ],
            "stylePreprocessorOptions": {
              "includePaths": [
                "src/styles/theme",
                "src/styles/theme/dark",
                "src/styles/theme/light"
              ]
            },
            "scripts": [
              "node_modules/mathjax/MathJax.js",
              "node_modules/systemjs/dist/s.js",
              "node_modules/systemjs/dist/extras/amd.js",
              "node_modules/systemjs/dist/extras/named-register.js",
              "node_modules/systemjs/dist/extras/use-default.js"
            ],
            "customWebpackConfig": {"path": "./webpack.config.js"}
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": true,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
            },
            "analyzer": {
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": true,
              "namedChunks": true,
              "extractCss": true,
              "extractLicenses": true,
              "vendorChunk": true,
              "buildOptimizer": true,
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "onenote:build",
            "customWebpackConfig": {"path": "./webpack.config.js"}
          },
          "configurations": {
            "production": {"browserTarget": "onenote:build:production"}
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {"browserTarget": "onenote:build"}
        },
        "test": {
          "builder": "ngx-build-plus:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": ["src/styles.less"],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": ["**/node_modules/**"]
          }
        }
      }

最终优化完后果

感觉申请有点多,下步打算退出 file-loder,url-loder 把图片转成 base64 加载,缩小申请

正文完
 0