将 WorkBox 添加到 NX 工作区中的 Angular Webpack 应用程序

问题描述 投票:0回答:1

我正在尝试将应用程序中的 ServiceWorker 从 @angular/service-worker 切换到 workbox,但我发现文档缺乏好的示例。我知道这是一个与框架无关的工具,但构建似乎有点麻烦。有没有更简化的方法来做到这一点?或者我在这里遵循最佳实践?

我有以下结构:

  apps
  ⨽ myApp
    ⊦ sw.ts                  ← My Workbox SW template
    ⊦ tsconfig.workbox.json  ← Only needed because of my extra webpack build step
    ⊦ webpack.config.js      ← Config of the extra build step
    ⊦ workbox-build.js       ← Config for the workbox-cli when injecting
    ⊦ project.json           ← NX version of the angular cli config
  dist
  ⨽ apps
    ⨽ myApp

sw.ts

import { clientsClaim, skipWaiting } from 'workbox-core';
import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching';

declare const self: ServiceWorkerGlobalScope;

skipWaiting();
clientsClaim();
cleanupOutdatedCaches();

precacheAndRoute(self.__WB_MANIFEST); // Will be filled in build time

tsconfig.workbox.json:

{
  "compilerOptions": {
    "typeRoots": ["./typings"],
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "lib": ["esnext", "webworker"]
  },
  "files": ["./sw.ts"]
}

webpack.config.json:

const path = require('path');

module.exports = {
  mode: 'production',
  output: {
    path: path.resolve(__dirname, '../../dist/apps/myApp'),
    filename: 'sw.js',
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        options: { configFile: 'tsconfig.workbox.json' },
      },
    ],
  },
  resolve: { extensions: ['.js', '.ts'] },
};

workbox-build.js:

const { injectManifest } = require('workbox-build');

const workboxConfig = {
  globDirectory: 'dist/apps/myApp',
  globPatterns: ['**/*.{css,eot,html,ico,jpg,js,json,png,svg,ttf,txt,webmanifest,woff,woff2,webm,xml}'],
  globFollow: true, // follow symlinks
  globStrict: true, // fail on error
  globIgnores: [
    `**/*-es5.js*`,
    'sw.js',
  ],
  // Allows to avoid using cache busting for Angular files because Angular already takes care of that!
  dontCacheBustURLsMatching: new RegExp('.+.[a-f0-9]{20}..+'),
  maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // 10MB
  swSrc: 'dist/apps/myApp/sw.js',
  swDest: 'dist/apps/myApp/sw.js',
};

// Calling the method and output the result
injectManifest(workboxConfig).then(({ count, size }) => {
  console.log(`Generated ${workboxConfig.swDest},
  which will precache ${count} files, ${size} bytes.`);
});

还有我的

package.json
中的脚本:

"build:wb": "webpack ./apps/myApp/sw.ts --config ./apps/myApp/webpack.config.js && node ./apps/myApp/workbox-build.js"

所以这会运行两个任务; 1) 编译

sw.ts
和 2) 将静态资源作为预缓存注入到编译后的
sw.js
中。但我认为这是一个混乱的解决方案。

Angular 已经使用 webpack 进行构建,我不能使用自定义 webpack 配置将此构建过程集成到我的 project.json 中吗?该配置在 Angular webpack 完成后自动运行? 是否真的需要在 Angular 构建完成后手动启动额外的构建步骤?

我想我认为这里可能的是在我的

project.json
文件中引用自定义 webpack 配置,该配置是作为 Angular 构建管道中的最后一步执行的。 webpack 配置将首先编译我的
sw.ts
,然后从 Angular 构建中收集静态文件,将这些文件的预缓存注入到编译后的
sw.ts
中,并将结果与 Angular 编译的其余部分一起输出到 dist 文件夹中。

这将消除对额外 tsconfig 文件和单独构建脚本的需要,并使整个构建更容易理解。

angular webpack workbox nrwl-nx workbox-webpack-plugin
1个回答
0
投票

实际上使用自定义 webpack 解决了它:

projects.json:

{
  ...
  "targets": {
    "build": {
      "executor": "@angular-builders/custom-webpack:browser",
      "options": {
        "customWebpackConfig": {
          "path": "apps/myApp/webpack.config.js",
          "replaceDuplicatePlugins": true
        },
        ...
      },
      ...
    },
    "serve": {
      "executor": "@angular-builders/custom-webpack:dev-server",
      ...
    }
  }
}

webpack.config.js:

const path = require('path');
const { InjectManifest } = require('workbox-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const AngularWebpackPlugin = require('@ngtools/webpack').AngularWebpackPlugin;

module.exports = {
  plugins: [
    // Required to get InjectManifest to precache assets, since this webpack config
    // apparently runs before angular copies assets to dist.
    new CopyPlugin({
      patterns: [
        {
          context: 'apps/myApp/src/assets',
          from: '**/*',
          to: './assets',
        }
      ],
    }),
    new InjectManifest({
      swSrc: path.resolve(__dirname, './src/sw.ts'),
      swDest: path.resolve(__dirname, '../../dist/apps/myApp/sw.js'),
      // Allows the plugin to compile the sw.ts file
      compileSrc: true,
      // Without this, Webpack yields an error.
      webpackCompilationPlugins: [
        // The only reason for having a separate tsconfig here, is to add
        // a different `files` array. If I include the sw.ts file in the main
        // tsconfig, angular complains a lot.
        new AngularWebpackPlugin({ tsconfig: 'apps/myApp/tsconfig.wb.json' }),
      ],
      exclude: [/\-es5.js$/, /sw.js/],
      maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // 10MB
    }),
  ],
};

现在我可以运行

nx build myApp
,它构建了一切,包括服务工作者!

如果有人可以对此进行改进,我会很乐意接受其他答案。

© www.soinside.com 2019 - 2024. All rights reserved.