使用 Quicklink 在 create-react-app 中预提取

Addy Osmani
Addy Osmani
Anton Karlovskiy
Anton Karlovskiy
Demián Renzulli
Demián Renzulli

此 Codelab 将介绍如何在 React SPA 演示中实现 Quicklink 库,以演示预提取如何加快后续导航的速度。

测量

在添加优化之前,最好先分析应用的当前状态。

  • 点击 Remix to Edit 以使项目可修改。
  • 如需预览网站,请按查看应用。然后按 全屏 全屏

该网站是一个使用 create-react-app 构建的简单演示。

在刚刚打开的新标签页中,按照以下说明操作:

  1. 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。
  3. 选中停用缓存复选框。
  4. 限制下拉列表中,选择 Fast 3G 以模拟慢速连接类型。
  5. 重新加载应用。
  6. 过滤器文本框中输入 chunk 可隐藏名称中不包含 chunk 的所有资源。

显示首页区块的网络面板。

该网站使用基于路由的代码拆分,因此在开始时仅请求必要的代码。

  1. 在开发者工具中清除网络请求
  2. 在应用中,点击博客链接即可前往该页面。

系统会加载新路线的 JS 和 CSS 区块以呈现网页。

显示博客页面块的网络面板。

接下来,您将在此网站中实现 Quicklink,以便在首页中预提取这些区块,从而加快导航速度。

这样,您就可以将这两种技术的优势结合起来:

  • 基于路由的代码拆分会告知浏览器在网页加载时仅以更高的优先级加载必需的分块。
  • 预取会告知浏览器在浏览器闲置期间以最低优先级加载视口内链接的区块。

配置 webpack-route-manifest

第一步是安装并配置 webpack-route-manifest,这是一个 webpack 插件,可让您生成将路由与其相应分块相关联的清单文件。

通常,您需要安装此库,但我们已代您完成安装。以下是您需要运行的命令:

npm install webpack-route-manifest --save-dev

config-overrides.js 是位于项目根目录下的文件,您可以通过该文件替换 webpack 配置的现有行为,而无需弹出项目

  • 要查看源代码,请按查看源代码

打开 config-overrides.js 进行修改,并在文件开头添加 webpack-route-manifest 依赖项:

const path = require('path');
const RouteManifest = require('webpack-route-manifest');

接下来,通过添加以下代码来配置 webpack-route-manifest 插件 添加到 config-overrides.js 底部的代码:

module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: {
      '@assets': `${path.resolve(__dirname, 'src/assets')}`,
      '@pages': `${path.resolve(__dirname, 'src/pages')}`,
      '@components': `${path.resolve(__dirname, 'src/components')}`,
    },
  };

  config.plugins.push(
    new RouteManifest({
      minify: true,
      filename: 'rmanifest.json',
      routes(str) {
        let out = str.replace('@pages', '').toLowerCase();
        if (out === '/article') return '/blog/:title';
        if (out === '/home') return '/';
        return out;
      },
    }),
  );

  return config;
};

新代码将执行以下操作:

  • config.resolve 使用页面、资产和组件的内部路由来声明变量。
  • config.plugins.push() 会创建一个 RouteManifest 对象并向其传递配置,以便根据网站的路由和分块生成 rmanifest.json 文件。

系统将生成 manifest.json 文件,并在 https://site_url/rmanifest.json 提供该文件。

此时,您需要在自己的项目中安装 Quicklink 库。为简单起见,我们已将其添加到项目中。以下是您需要运行的命令:

npm install --save quicklink

打开 src/components/App/index.js 进行修改。

首先,导入 Quicklink 高阶组件 (HOC):

import React, { lazy, Suspense } from 'react';
import { Route } from 'react-router-dom';

import Footer from '@components/Footer';
import Hero from '@components/Hero';
import style from './index.module.css';
import { withQuicklink } from 'quicklink/dist/react/hoc.js';

const Home = lazy(() => import(/* webpackChunkName: "home" */ '@pages/Home'));
const About = lazy(() => import(/* webpackChunkName: "about" */ '@pages/About'));
const Article = lazy(() => import(/* webpackChunkName: "article" */ '@pages/Article'));
const Blog = lazy(() => import(/* webpackChunkName: "blog" */ '@pages/Blog'));

接下来,在 Blog 变量声明后创建一个 options 对象,以在调用 quicklink 时用作实参:

const options = {
    origins: []
};

最后,使用 withQuicklink() 高阶组件封装每条路线,并向其传递 options 参数和该路线的目标组件:

const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading...</div>}>
        <Route path="/" exact component={withQuicklink(Home, options)} />
        <Route path="/blog" exact component={withQuicklink(Blog, options)} />
        <Route
          path="/blog/:title"
          component={withQuicklink(Article, options)}
        />
        <Route path="/about" exact component={withQuicklink(About, options)} />
      </Suspense>
    </main>
    <Footer />
  </div>
);

上面的代码指示当链接进入视图时,为使用 withQuicklink() 封装的路由预提取区块。

再次测量

重复测量中的前 6 步。暂时不要导航到博客页面。

在首页加载时,系统会加载该路线的分块。然后,Quicklink 会预提取视口内链接的路线块:

Network 面板,其中显示了首页预提取分块。

系统会以最低优先级请求这些区块,而不会屏蔽网页。

下一个:

  1. 再次清除网络日志。
  2. 取消选中停用缓存复选框。
  3. 点击博客链接即可前往该页面。

Network 面板,显示了博客页面以及从缓存中选取的数据块。

Size 列表示这些分块是从“预提取缓存”(而非网络)中检索的。在不使用快速链接的情况下加载这些文本块大约需要 580 毫秒。现在,使用该库耗时 2 毫秒,相当于 99% 缩短了