如何在构建时替换图像和文件而不在应用程序中引用它们?

How to replace images and files at build without referencing them in the app?

我们正在将现有的 Angular 8 PWA 重写为 Vuejs,我们在构建过程中面临一些问题。 (我们不是来讨论这个选择的原因或任何人对此的看法)

我们的应用程序必须为不同的客户构建,每个客户都有特定的资产(manifest.json 文件、图标和图像)。

在 Angular 中,我们通过使用 fileReplacements 键在 angular.json 文件中定义规则来完成文件替换,如下所示:

"configurations": {
        "production-customer-a": {
          "fileReplacements": [
            {
              "replace": "src/manifest.json",
              "with": "src/environments/customer-a/assets/manifest.json"
            },
          ],
          // Some more json stuff

我们尝试在 vue.config.js 中的 vue 应用程序中使用 webpack 的 NormalModuleReplacementPlugin 实现类似的过程,如下所示:

configureWebpack: () => {
let plugins;
switch (customer) {
  case customer-a:
    plugins = [
      new NormalModuleReplacementPlugin(
        /\.\.\/public\/manifest\.json/,
        "../environments/customer-a/assets/manifest.json"
      ),
     // Some more config

如果在构建 时使用其 url 在应用 中实际引用相关文件,则效果很好。 让我用一个例子来解释:

<img src="@/assets/myImageWhichShouldBeReplacedAtBuild.png" /> /* Will actually be replaced and the dist folder will contain the file properly */
<img src="@/assets/myImageWhichShouldBeReplacedAtBuildButIsBase64EncodedWithWebpackUrlLoader.png" /> /* Will be replaced as the base64 string but the dist folder wont contain the file and might be an issue if the image is to be used by files like manifest.json */

后者不是一个完整的问题,因为我们可以在 vue.config.js 中覆盖 webpack 的 url-loader。但仍然是一个很好的收获。

由于我们不在 Vue 模板中引用 manifest.json 或 favicon.ico 等文件,不会替换这些文件

有没有办法确保 我们需要的每个 文件都将在构建时被替换以获得与 Angular 的 angular.json 配置相同的结果文件 ?也许使用与 NormalModuleReplacementPlugin 不同的东西?

因此,对于来到这里的任何迷失的灵魂,我们设法找到了合适的解决方案。

我们摆脱了 webpack 的 NormalModuleReplacementPlugin 并结合任务 运行ner(gulp,在我们的例子中)和 Vue 静态资产处理。

由于相关资产始终相同,我们将默认资产放在解决方案的 public 文件夹中,并在我们的环境文件夹中为每个客户重新创建相同的结构。

-public
--img
---icons

-environments
--customer
---img
----icons

利用 Vue's URL transform rule,我们使用绝对路径引用应用程序中的所有资源,因此文件不会经过 webpack 的处理。 构建之后,我们 运行 我们的 gulp 文件获取所有客户的资产(作为参数传递)并在 dist 文件夹中覆盖它们。

gulpfile.js:

const gulp = require('gulp');
const yargs = require('yargs').argv;

gulp.task('moveassets', () => {
  return gulp.src(`environments/${yargs.customer}/**/**/**`)
    .pipe(gulp.dest('dist'));
})

package.json 脚本:

"build:customer": "vue-cli-service build && gulp moveassets --customer customer"

这可能会给缓存处理带来一些麻烦,因为 webpack 会将哈希值放入文件中,但是 Angular 不会这样做,所以它不会改变我们的习惯。