Skip to main content

制作渐进式 Web 应用

生产版本具有生成一流 渐进式 Web 应用 所需的所有工具,但离线/缓存优先行为仅是可选的。

¥The production build has all the tools necessary to generate a first-class Progressive Web App, but the offline/cache-first behavior is opt-in only.

从 Create React App 4 开始,你可以将一个 src/service-worker.js 文件添加到你的项目中,以使用对 工作箱InjectManifest 插件的内置支持,这将 compile 你的服务工作者并向其中注入一个指向 precache 的 URL 列表。

¥Starting with Create React App 4, you can add a src/service-worker.js file to your project to use the built-in support for Workbox's InjectManifest plugin, which will compile your service worker and inject into it a list of URLs to precache.

如果你使用其中一个 PWA 自定义模板 开始一个新项目,你将获得一个 src/service-worker.js 文件,它可以作为离线优先服务工作者的良好起点:

¥If you start a new project using one of the PWA custom templates, you'll get a src/service-worker.js file that serves as a good starting point for an offline-first service worker:

npx create-react-app my-app --template cra-template-pwa

TypeScript 等价物是:

¥The TypeScript equivalent is:

npx create-react-app my-app --template cra-template-pwa-typescript

如果你知道你不会使用 service worker,或者如果你更愿意使用不同的方法来创建 service worker,请不要创建 src/service-worker.js 文件。在这种情况下,InjectManifest 插件将不会运行。

¥If you know that you won't be using service workers, or if you'd prefer to use a different approach to creating your service worker, don't create a src/service-worker.js file. The InjectManifest plugin won't be run in that case.

除了创建本地 src/service-worker.js 文件外,还需要在使用前进行注册。为了选择离线优先行为,开发者应该在他们的 src/index.js 文件中查找以下内容:

¥In addition to creating your local src/service-worker.js file, it needs to be registered before it will be used. In order to opt-in to the offline-first behavior, developers should look for the following in their src/index.js file:

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://cra.link/PWA
serviceWorkerRegistration.unregister();

如注释所述,将 serviceWorker.unregister() 切换到 serviceWorker.register() 将使你选择使用 service worker。

¥As the comment states, switching serviceWorker.unregister() to serviceWorker.register() will opt you in to using the service worker.

为什么选择加入?

¥Why Opt-in?

离线优先的渐进式 Web 应用比传统网页更快、更可靠,并提供引人入胜的移动体验:

¥Offline-first Progressive Web Apps are faster and more reliable than traditional web pages, and provide an engaging mobile experience:

  • 作为 webpack 构建的一部分的所有静态站点资源都被缓存,以便你的页面在后续访问时快速加载,无论网络连接如何(例如 2G 或 3G)。更新在后台下载。

    ¥All static site assets that are a part of your webpack build are cached so that your page loads fast on subsequent visits, regardless of network connectivity (such as 2G or 3G). Updates are downloaded in the background.

  • 无论网络状态如何,你的应用都可以正常工作,即使离线也是如此。这意味着你的用户将能够在 10,000 英尺高空和地铁上使用你的应用。

    ¥Your app will work regardless of network state, even if offline. This means your users will be able to use your app at 10,000 feet and on the subway.

  • 在移动设备上,你的应用可以直接添加到用户的主屏幕、应用图标等。这消除了对应用存储的需要。

    ¥On mobile devices, your app can be added directly to the user's home screen, app icon and all. This eliminates the need for the app store.

然而,他们 可以使调试部署更具挑战性

¥However, they can make debugging deployments more challenging.

workbox-webpack-plugin 已集成到生产配置中,它将负责编译一个服务工作文件,该文件将自动预缓存所有 webpack 生成的资源,并在你部署更新时使它们保持最新。service worker 将使用 缓存优先策略 来处理对 webpack 生成的资源的所有请求,包括对你的 HTML 的 导航请求,确保你的网络应用始终如一地快速,即使在缓慢或不可靠的网络上也是如此。

¥The workbox-webpack-plugin is integrated into production configuration, and it will take care of compiling a service worker file that will automatically precache all of your webpack-generated assets and keep them up to date as you deploy updates. The service worker will use a cache-first strategy for handling all requests for webpack-generated assets, including navigation requests for your HTML, ensuring that your web app is consistently fast, even on a slow or unreliable network.

注意:不是由 webpack 生成的资源,例如从本地 public/ 目录 或第三方资源复制过来的静态文件,将不会被预缓存。你可以选择设置 Workbox routes 以将你选择的运行时缓存策略应用于这些资源。

¥Note: Resources that are not generated by webpack, such as static files that are copied over from your local public/ directory or third-party resources, will not be precached. You can optionally set up Workbox routes to apply the runtime caching strategy of your choice to those resources.

定制化

¥Customization

从 Create React App 4 开始,你可以通过创建自己的 src/service-worker.js 文件或自定义由 cra-template-pwa(或 cra-template-pwa-typescript)模板添加的文件来完全控制自定义此 Service Worker 中的逻辑。你可以使用 Workbox 项目中的 附加模块,添加推送通知库,或删除一些默认缓存逻辑。一个要求是你将 self.__WB_MANIFEST 保留在文件中的某个位置,因为 Workbox 编译插件在生成要预缓存的 URL 清单时会检查此值。如果你不想使用预缓存,你可以将 self.__WB_MANIFEST 分配给一个将被忽略的变量,例如:

¥Starting with Create React App 4, you have full control over customizing the logic in this service worker, by creating your own src/service-worker.js file, or customizing the one added by the cra-template-pwa (or cra-template-pwa-typescript) template. You can use additional modules from the Workbox project, add in a push notification library, or remove some of the default caching logic. The one requirement is that you keep self.__WB_MANIFEST somewhere in your file, as the Workbox compilation plugin checks for this value when generating a manifest of URLs to precache. If you would prefer not to use precaching, you can assign self.__WB_MANIFEST to a variable that will be ignored, like:

// eslint-disable-next-line no-restricted-globals
const ignored = self.__WB_MANIFEST;

// Your custom service worker code goes here.

离线优先注意事项

¥Offline-First Considerations

如果你决定选择加入 Service Worker 注册,请考虑以下因素:

¥If you do decide to opt-in to service worker registration, please take the following into account:

  1. 初始缓存完成后,服务工作线程生命周期 控制更新内容何时最终显示给用户。为了防范 具有延迟加载内容的竞争条件,默认行为是保守地将更新后的 Service Worker 保持在“waiting”状态。这意味着用户最终会看到较旧的内容,直到他们关闭(重新加载是不够的)他们现有的、打开的选项卡。有关此行为的更多详细信息,请参阅 这篇博文

    ¥After the initial caching is done, the service worker lifecycle controls when updated content ends up being shown to users. In order to guard against race conditions with lazy-loaded content, the default behavior is to conservatively keep the updated service worker in the "waiting" state. This means that users will end up seeing older content until they close (reloading is not enough) their existing, open tabs. See this blog post for more details about this behavior.

  2. 用户并不总是熟悉离线优先的网络应用。当 service worker 完成缓存填充(显示 "此网络应用可离线使用!" 消息)时,它对 让用户知道 很有用,还可以让他们知道 service worker 何时获取最新更新,这些更新将在他们下次加载页面时可用(显示 "现有选项卡关闭后,新内容可用。" 信息)。显示这些消息目前留给开发者作为练习,但作为起点,你可以使用 src/serviceWorkerRegistration.js 中包含的逻辑,它演示了要监听哪些 service worker 生命周期事件以检测每个场景,以及哪些是默认情况 , 仅将适当的消息记录到 JavaScript 控制台。

    ¥Users aren't always familiar with offline-first web apps. It can be useful to let the user know when the service worker has finished populating your caches (showing a "This web app works offline!" message) and also let them know when the service worker has fetched the latest updates that will be available the next time they load the page (showing a "New content is available once existing tabs are closed." message). Showing these messages is currently left as an exercise to the developer, but as a starting point, you can make use of the logic included in src/serviceWorkerRegistration.js, which demonstrates which service worker lifecycle events to listen for to detect each scenario, and which as a default, only logs appropriate messages to the JavaScript console.

  3. Service workers 需要 HTTPS,虽然为了方便本地测试,那政策 不适用于 localhost。如果你的生产 Web 服务器不支持 HTTPS,则服务工作者注册将失败,但你的 Web 应用的其余部分将保持正常运行。

    ¥Service workers require HTTPS, although to facilitate local testing, that policy does not apply to localhost. If your production web server does not support HTTPS, then the service worker registration will fail, but the rest of your web app will remain functional.

  4. Service Worker 仅在 生产环境 中启用,例如 npm run build 的输出。建议你不要在开发环境中启用离线优先服务工作者,因为当使用以前缓存的资源并且不包括你在本地所做的最新更改时,这可能会导致挫败感。

    ¥The service worker is only enabled in the production environment, e.g. the output of npm run build. It's recommended that you do not enable an offline-first service worker in a development environment, as it can lead to frustration when previously cached assets are used and do not include the latest changes you've made locally.

  5. 如果你需要在本地测试离线优先服务工作者,请构建应用(使用 npm run build)并从你的构建目录运行标准的 http 服务器。运行构建脚本后,create-react-app 将给出在本地测试生产构建的一种方法的说明,部署说明 将提供使用其他方法的说明。请务必始终使用隐身窗口,以免浏览器缓存出现问题。

    ¥If you need to test your offline-first service worker locally, build the application (using npm run build) and run a standard http server from your build directory. After running the build script, create-react-app will give instructions for one way to test your production build locally and the deployment instructions have instructions for using other methods. Be sure to always use an incognito window to avoid complications with your browser cache.

  6. 默认情况下,生成的服务工作者文件不会拦截或缓存任何跨源流量,例如 HTTP API 请求、图片或从不同域加载的嵌入。从 Create React App 4 开始,这可以自定义,如上所述。

    ¥By default, the generated service worker file will not intercept or cache any cross-origin traffic, like HTTP API requests, images, or embeds loaded from a different domain. Starting with Create React App 4, this can be customized, as explained above.

渐进式 Web 应用元数据

¥Progressive Web App Metadata

默认配置包括位于 public/manifest.json 的 Web 应用清单,你可以使用特定于你的 Web 应用的详细信息对其进行自定义。

¥The default configuration includes a web app manifest located at public/manifest.json, that you can customize with details specific to your web application.

当用户在 Android 上使用 Chrome 或 Firefox 将网络应用添加到他们的主屏幕时,manifest.json 中的元数据决定了在显示网络应用时要使用的图标、名称和品牌颜色。Web 应用清单指南 提供了更多关于每个字段含义的上下文,以及你的自定义将如何影响用户体验。

¥When a user adds a web app to their homescreen using Chrome or Firefox on Android, the metadata in manifest.json determines what icons, names, and branding colors to use when the web app is displayed. The Web App Manifest guide provides more context about what each field means, and how your customizations will affect your users' experience.

已添加到主屏幕的渐进式 Web 应用加载速度更快,并且在有活跃的 service worker 时可以离线工作。也就是说,无论你是否选择加入 Service Worker 注册,Web 应用清单中的元数据仍将被使用。

¥Progressive web apps that have been added to the homescreen will load faster and work offline when there's an active service worker. That being said, the metadata from the web app manifest will still be used regardless of whether or not you opt-in to service worker registration.