【问题标题】:React (CRA) Service Worker Cache "public" folderReact (CRA) Service Worker 缓存“公共”文件夹
【发布时间】:2019-07-17 08:45:46
【问题描述】:

执行 create-react-app 并启用index.js 中的服务工作者后,src 文件夹中的所有相关文件都将被缓存。但是我的一些资源位于public 目录中。当我运行 npm run build 时,asset-manifest.jsonprecache-manifest.HASH.js 仅包含 HTML、损坏的 JS 和 CSS(所有内容都来自 src 文件夹)。

如何让服务人员额外缓存 public 文件夹中的特定文件?

这里是实际生成的precache-manifest.e431838417905ad548a58141f8dc754b.js

self.__precacheManifest = [
  {
    "revision": "cb0ea38f65ed9eddcc91",
    "url": "/grafiti/static/js/runtime~main.cb0ea38f.js"
  },
  {
    "revision": "2c226d1577937984bf58",
    "url": "/grafiti/static/js/main.2c226d15.chunk.js"
  },
  {
    "revision": "c88c70e5f4ff8bea6fac",
    "url": "/grafiti/static/js/2.c88c70e5.chunk.js"
  },
  {
    "revision": "2c226d1577937984bf58",
    "url": "/grafiti/static/css/main.7a6fc926.chunk.css"
  },
  {
    "revision": "980026e33c706b23b041891757cd51be",
    "url": "/grafiti/index.html"
  }
];

但我希望它也包含这些网址的条目:

  • /grafiti/icon-192.png
  • /grafiti/icon-512.png

它们来自public 文件夹。

或者:如何在src 文件夹中添加manifest.webmanifest 文件的图标,以便我可以从网络清单中引用它们?

【问题讨论】:

  • 这有什么更新吗?

标签: android service-worker create-react-app static-files


【解决方案1】:

如果您想在不弹出或重新布线的情况下采用非常基本的解决方案,您还可以执行以下操作

假设您使用 npx create-react-app app --template cra-template-pwa-typescript 之类的东西引导您的项目,然后在您的 service-worker.ts 文件中替换 this line...

precacheAndRoute(self.__WB_MANIFEST);

...带有以下内容:

// default static file URLs generated during the build process
const staticBuildFiles = self.__WB_MANIFEST as PrecacheEntry[];

// extra file URLs you want to be precached
const extraPrecachedFiles: PrecacheEntry[] = [
  "/cats.f137634a.png",
  "/dogs.1d77f71c.jpg",
];

// register all assets to be precached by the service worker
precacheAndRoute([
  ...staticBuildFiles,
  ...essentialMediaFiles.map((url) => ({ url, revision: null }))
]);

为了“缓存清除”,上述解决方案中的图像已经包含以前(手动)添加到其文件名中的哈希数字形式的修订信息。正如workbox docs中提到的:

在 URL 本身中包含修订信息,通常是静态资产的最佳做法。

但是,如果由于各种原因您不想在源代码的文件名中包含修订哈希,您也可以将唯一的字符串作为环境变量传递给您的构建命令,您可以稍后再选择它让工作箱使用它作为一个修订字符串来破坏你的缓存。例如。您可以使用构建过程的 unix 时间戳(或使用更高级的信息,例如 passing the current git commit hash 信息)...

REACT_APP_BUILD_VERSION=$(date +'%s') npm run build

...然后您可以在service-worker.ts 中获取:

precacheAndRoute([
  ...staticBuildFiles,
  ...essentialMediaFiles.map((url) => ({ url, revision: process.env.REACT_APP_BUILD_VERSION }))
]);

上述代码将导致所有使用REACT_APP_BUILD_VERSION 作为修订版的文件在每次构建时都无效。

【讨论】:

    【解决方案2】:

    我假设您正在寻找一个解决方案(像我一样),它可以在不弹出的情况下工作。这种方法对我有用:

    1. 通过yarn add -D react-app-rewired安装模块react-app-rewired
    2. 在 package.json 中的 npm 脚本中替换 react-scripts(eject 不需要)

      /* package.json */
      
      "scripts": {
      -   "start": "react-scripts start",
      +   "start": "react-app-rewired start",
      -   "build": "react-scripts build",
      +   "build": "react-app-rewired build",
      -   "test": "react-scripts test --env=jsdom",
      +   "test": "react-app-rewired test --env=jsdom",
          "eject": "react-scripts eject"
      
    3. 在与您的 package.json 相同的级别中创建一个 config-overrides.js 文件

    我的文件看起来像这样(因为我还想为我的 api 添加一个具有更复杂缓存选项的自己的服务工作者)但是 globPatternsglobDirectory 是你的寻找。添加此模式后,匹配文件(在我的情况下为图像、音乐和声音)被添加到生成的 precache-manifest-{hash} 中。

    const {InjectManifest} = require('workbox-webpack-plugin');
    const path = require('path');
    
    module.exports = {
      webpack: function(config, env) {
        config.plugins.push(
          new InjectManifest({
            globPatterns: [
              'images/*.png',
              'models/*.glb',
              'music/*.mp3',
              'sound/*.mp3'
            ],
            globDirectory: 'build',
            swSrc: path.join('src', 'custom-service-worker.js'),
            swDest: 'service-worker.js'
          })
        );
    
        return config;
      }
    }
    

    P.S.:如果你需要一个 custom-service.worker.js 文件来让它工作,workbox.precaching.precacheAndRoute([])应该足够作为这个文件的内容,但是the workbox docs对于那些缓存的东西也很有趣

    【讨论】:

    • 嗨@Fabian,如果我没有自定义工作文件怎么办?如何通过 create-react-app 使用默认的?谢谢。
    • 嗨@dli,正是为了这个缓存和预缓存的东西,我添加了我的自定义服务工作者。 :) 据我所知,无法修改生成的 cra 服务人员(没有弹出)。这就是为什么我建议 react-app-rewired + InjectManifest 这样你就不需要运行弹出。
    • 谢谢@Fabian,我会努力的。
    猜你喜欢
    • 1970-01-01
    • 2020-09-16
    • 2016-10-28
    • 2020-11-20
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 2016-02-23
    相关资源
    最近更新 更多