webpack 将WorkBox添加到NX工作区中的angular应用程序

tquggr8v  于 2023-10-19  发布在  Webpack
关注(0)|答案(1)|浏览(130)

我试图在我的应用程序中切换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中吗?它真的必须是一个额外的构建步骤,这是手动启动后,角是完成建设?
我想我在这里认为可能的是,在我的project.json文件中引用一个自定义的webpack配置,这是在Angular 构建管道的最后一步执行的。webpack配置将首先编译我的sw.ts,然后从angular构建中收集静态文件,将这些文件的预缓存注入到编译后的sw.ts中,并将结果输出到dist文件夹中,与其余的angular编译一起沿着。
这将消除对一个额外的tsconfig文件和一个单独的构建脚本的需要,并使整个构建更容易理解。

pbpqsu0x

pbpqsu0x1#

实际上使用自定义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,它构建了所有内容,包括服务工作者!
我很乐意接受其他的答案,如果有人可以改进这一点。

相关问题