使用 angular 自定义生成器修改资产

Assets revisioning using angular custom builder

来自 this Stack Overflow question,我正在尝试将 @angular-builders/custom-webpack:browser 与使用 html-loader 和 file-loader 的自定义 Webpack 配置一起使用,以便使用其哈希重命名资产文件内容以及源代码中对它们的每个引用。

最终目的是能够将资产缓存在浏览器中,但保证用户始终拥有最新版本的资产(因为如果它因新版本而更改,名称资产也会改变)。

我从 Angular 英雄之旅指南 (https://angular.io/tutorial) 开始,并执行了以下步骤:

(在dashboard.component.html我加了)

...
<img src="assets/angular-logo.png" />
...

然后我添加了src/assets/angular-logo.png

我更改了 angular.json 文件以使用自定义生成器

"architect": {
    "build": {
      "builder": "@angular-builders/custom-webpack:browser", <------------- (changed this)
      "options": {
        "outputPath": "dist",
        "index": "src/index.html",
        "main": "src/main.ts",
        "polyfills": "src/polyfills.ts",
        "tsConfig": "tsconfig.app.json",
        "assets": [
          "src/favicon.ico",
          "src/assets"
        ],
        "styles": [
          "src/styles.css"
        ],
        "scripts": []
      },
      "configurations": {
        "production": {
          "fileReplacements": [
            {
              "replace": "src/environments/environment.ts",
              "with": "src/environments/environment.prod.ts"
            }
          ],
          "customWebpackConfig": { <---------------------------------------- (added this)
            "path": "custom-webpack.config.js"
          },
          "optimization": true,
          "outputHashing": "all",
          "sourceMap": false,
          "extractCss": true,
          "namedChunks": false,
          "aot": true,
          "extractLicenses": true,
          "vendorChunk": false,
          "buildOptimizer": true,
          "budgets": [
            {
              "type": "initial",
              "maximumWarning": "2mb",
              "maximumError": "5mb"
            },
            {
              "type": "anyComponentStyle",
              "maximumWarning": "6kb",
              "maximumError": "10kb"
            }
          ]
        }
      }
    },
    ...
}

然后我在应用程序的根目录下创建了custom-webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.ts$/,
                loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
                exclude: [/\.(spec|e2e)\.ts$/]
            },
            {
                test: /\.html$/,
                use: ['html-loader']
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loader: 'file-loader',
                options: {
                    outputPath: 'assets/',
                    name: '[name].[contenthash].[ext]',
                },
            }
        ]
    }
}

我 npm 安装了所有必需的加载程序以及 @angular-builders/custom-webpack

据我了解,当我 运行 ng build --prod 时,这将(在现有 Angular Webpack 配置之上)

  1. 加载 TypeScript 文件(使用 awesome-typescript-loader
  2. 从 Angular 个组件加载 templateUrl 和 styleUrls(使用 angular2-template-loader
  3. 加载 HTML 个文件
  4. 加载图像文件并使用其内容哈希将它们重命名为资产

问题是,当我 运行 ng build --prod 它似乎不起作用,因为资产图像名称在 [=57= 中仍然是 angular-logo.png ].

我觉得我对 Webpack 的工作方式有些不理解。我缺少什么?

  1. 您需要删除 angular.json 中的资产 属性 并且就像 jonrsharpe 在 import 语句中所说的通过加载程序带来它们一样。现在您需要在它们上激活正确的加载器。

  2. Angular 将其自己的加载程序放在您的 .component.css/.component.html/component.ts 文件中, 所以 当你的 webpack.config.js 没有导出函数时 - 你 自动删除 angular 个加载程序

    您需要应用 angular 个加载器 (ngtools/webpack/src/index.js) 在你的 src 文件上:

    自定义-webpack.config.js:

    module.exports = function (angularConfig) {
         let rules = angularConfig.module.rules || [];
    
         // feel free to take some rules off, or change the path that they apply on
         // Picking up only Angular core rules from Angular default webpack config.
         angularConfig.module.rules = [
            ...rules.filter(rule => rule.test.source.match(/@angular|\.js/)),
            ...rules.filter(rule => rule.test.source.match(/\.(css|scss|less|styl)/)).map(rule => util.replaceRawLoader(util.excludeUnnecessarryPaths(rule))),
            ...rules.filter(rule => rule.test.source.match(/\.tsx\?/)).map(rule => util.excludeUnnecessarryPaths(rule))
         ];
    
          return merge(angularConfig, { /* your webpack configuration */ });
    }
    

    为了方便起见,我特地打了一个断点来调试这段代码。