如何使用 Webpack 5 加载 Service Worker?

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

我正在使用 Webpack 5,我希望有一个 Service Worker 能够拦截获取请求并在本地返回响应,而无需访问网络。我还希望能够在 Service Worker 中导入 npm 模块。我曾经使用一个名为 serviceworker-webpack-plugin 的库来实现此目的,但它不再维护(并且当我使用它时会抛出错误)。 Webpack 文档建议使用 Workbox,但据我所知,这似乎只是为了在 Service Worker 中缓存资产。 有人可以告诉我 2020 年使用 Webpack 5 创建 Service Worker 的正确方法是什么吗?

javascript reactjs webpack service-worker
5个回答
13
投票

将 Service Worker 添加到您的 webpack.config.js 条目字段

entry: {
    'app': "./src/index.js",
    'service-worker': "./src/service-worker.ts",
},
output: {
    filename: "[name].js",
},

这将发出

dist/app.js
dist/service-worker.js
,并且可以在两者中导入内容。

serviceworker-webpack-plugin
还为 serviceworker 提供了一种查看其应缓存的所有捆绑文件列表的方法,但该功能无法直接使用,需要制作 webpack 插件才能获取。


4
投票

2022 年答案

Webpack 几乎开箱即用地支持这一点。

https://webpack.js.org/guides/progressive-web-application/

这将为您提供 web pack 正在为您处理的资源的基本缓存。

您可以获得更高级的: https://developer.chrome.com/docs/workbox/modules/workbox-webpack-plugin/

请注意,这是使用谷歌的 Workbox。我已经在离线第一个应用程序中使用它多年,并且效果非常好。


3
投票

Webpack 5 应该开箱即用地为您执行此操作,与其他工作人员类似:

将资源的

new URL
new Worker
/
new SharedWorker/navigator.serviceWorker.register
结合使用时,webpack 会自动为 Web Worker 创建一个新的入口点。

new Worker(new URL("./worker.js", import.meta.url))
.

选择语法是为了允许在没有捆绑器的情况下运行代码。此语法也可在浏览器中的本机 ECMAScript 模块中使用。

(来自https://webpack.js.org/blog/2020-10-10-webpack-5-release/#native-worker-support

使用 webpack 4,我们的 Service Worker 代码如下所示:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import downloadWorker from 'worker-plugin/loader!../workers/downloadHelper'

navigator.serviceWorker.register(downloadWorker).then( //...

使用 webpack 5,代码变成:

navigator.serviceWorker
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  .register(new URL('../workers/downloadHelper.ts', import.meta.url))
  .then( // ...

我们从 webpack 5 配置中删除了

worker-plugin
,v4 的代码在
import
语句中使用了它。

关键是使用

new URL()
- webpack 5 会将其解释为 Web Worker,并为此 Service Worker 创建一个块并正确链接 url。

我们必须添加

eslint-disable-next-line
@ts-ignore
,因为
navigator.serviceworker.register
的接口需要一个字符串,而不是
URL
。看起来 webpack 正确地发送了一个字符串,但是 TypeScript 似乎无法理解在 webpack 运行之前运行 TypeScript 的情况。


0
投票

单个文件(Web Workers):

功能:用于执行繁重的计算或后台任务而不阻塞主线程

  1. 先安装
    worker-loader
npm i worker-loader -D
  1. 将此配置添加到 webpack 配置中:
{
    test: /\.worker\.js$/,
    use: {
        loader: 'worker-loader',
        options: {
          filename: '[name].[contenthash].worker.js',
          esModule: false,
        },
    },
},

缓存所有代码(Service Workers)

功能:通过启用离线支持、缓存等功能来增强 Web 应用程序

  1. 先安装
    workbox-webpack-plugin
npm i workbox-webpack-plugin -D
  1. 在 webpack 配置中进行设置:
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

plugins: [
new WorkboxWebpackPlugin.GenerateSW({
  swDest: 'service-worker.js',
  maximumFileSizeToCacheInBytes: 20_000_000,
  clientsClaim: true,
  skipWaiting: true,
  cleanupOutdatedCaches: true,
  // here, we set the navigateFallback to '/',
  // so that any missing urls are handled by react-router
  // navigateFallback: '/',
  include: [/\.html$/, /\.js$/, /\.css$/, /\.wasm$/],
  exclude: [/\.js\.map$/, /\.css\.map$/],
  additionalManifestEntries: [
    {
      url: 'manifest.json',
      revision: hashFileContent(path.join('../../public', 'manifest.json')),
    },
    // Add other entries if needed
  ],
  runtimeCaching: [
    {
      urlPattern: /\.(?:png|gif|jpg|svg|ico|woff2)$/i,
      handler: 'CacheFirst',
      options: {
        cacheName: 'image-cache',

        // Only cache 300 images.
        expiration: {
          maxEntries: 300,
          maxAgeSeconds: 3600 * 24 * 7, // one week
        },
      },
    },
    {
      urlPattern: /\.html$/i,
      handler: 'NetworkFirst',
      options: {
        cacheName: 'index-cache',
      },
    },
    {
      urlPattern: /^https:\/\/fonts\.googleapis\.com/,
      handler: 'StaleWhileRevalidate',

      options: {
        cacheName: 'google-fonts-stylesheets',

        expiration: {
          maxEntries: 4,
        },
      },
    },
    {
      urlPattern: /^https:\/\/fonts\.gstatic\.com/,
      handler: 'CacheFirst',

      options: {
        cacheName: 'google-fonts-webfonts',

        cacheableResponse: {
          statuses: [0, 200],
        },

        expiration: {
          maxEntries: 30,
          maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
        },
      },
    },
  ],
})
]

-3
投票

不要把事情搞得太复杂。

只需 2 步即可让软件工作。创建一个 sw 并注册它。

创建一个像

sw.js
一样的.js文件并在其中写入:

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.open('mysite-dynamic').then(function (cache) {
      return cache.match(event.request).then(function (response) {
        var fetchPromise = fetch(event.request).then(function (networkResponse) {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
        return response || fetchPromise;
      });
    }),
  );
});

这就是 stale-while-revalidate 方法

现在就注册吧。

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.