金数据技术博客 · №2

polyfill in create-react-app

· silverWolf818 · frontend

一、create-react-app 中的 polyfill

上一篇我们已经了解了如何使用 Babel 进行 polyfill。现在我们基于 React 工程来实践。

1. 创建工程

这里使用官方的脚手架工具初始化项目,如下:

yarn create react-app react-polyfill

我们需要修改 Babel 配置,还需要运行如下命令:

yarn eject

2. 查看 Babel 配置

webpack.config.js 文件中,找到对应解析 js 的 loader 配置如下:

// ... code
presets: [
    [
        require.resolve('babel-preset-react-app'),
        {
            runtime: hasJsxRuntime ? 'automatic' : 'classic',
        },
    ],
]
// ... code    

观察源码发现,官方提供的 presets 是 babel-preset-react-app 而不是我们所熟悉的 @babel/preset-env

babel-preset-react-app 其实是 React 官方封装的一个库。

查看 babel-preset-react-app 找到对应的 preset 设置,对应源码中 create.js 文件,如下:

(isEnvProduction || isEnvDevelopment) && [
  // Latest stable ECMAScript features
  require('@babel/preset-env').default,
  {
    // Allow importing core-js in entrypoint and use browserlist to select polyfills
    useBuiltIns: 'entry',
    // Set the corejs version we are using to avoid warnings in console
    corejs: 3,
    // Exclude transforms that make all code slower
    exclude: ['transform-typeof-symbol'],
  },
],

看到这里就一目了然了,根据上一篇我们了解到的知识。@babel/preset-env 参数是 useBuiltIns: 'entry'corejs: 3,那么就需要我们手动导入对应的 polyfill 文件。这里对应的源码注释也说得非常详细。

3. 进行 polyfill

首先安装 corejs3regenerator-runtime 依赖,如下:

yarn add core-js@3 regenerator-runtime

然后在 src 目录下,创建一个 polyfill/index.js,在文件中导入我们需要 polyfill 的 API,如下:

import 'core-js/es/array/flat'
import 'core-js/es/array/flat-map'
import 'core-js/es/array/includes'
import 'regenerator-runtime/runtime'

我们有 2 种方式引入 polyfill:

  1. 直接在入口文件引入 index.js
import './polyfill/index.js'
  1. webpack.config.js 中的 entry 参数中添加:
entry:[
    // ... code
    paths.appPolyFillJs,
    paths.appIndexJs,
    // ... code
]   

然后我们启动工程,找到编译后的文件如下:

通过上述的配置方法就实现了 polyfill,这也算是官方推荐的一个方案。

二、按需加载

如果我们想要实现按需加载怎么办?

那么我们就从 Github 上 fork 一份 babel-preset-react-app 源码。

其他步骤和之前介绍过的一样,只需要修改 create.js 的 preset 即可,如下:

{
  target: {
    chrome: 61,
    firefox: 52,
    safari: 8,
    ie: 11
  },
  useBuiltIns: 'usage',
  corejs: 3,
  exclude: ['transform-typeof-symbol'],
}

然后发布到 npm 仓库,修改 webpack.config.js 文件中 loader 替换成自己的。如下:

// code ...
presets: [
  [
    require.resolve('xxxx/babel-preset-react-app'),
  ]
]
// code ...

以上就是通过 create-react-app 创建工程的 polyfill 方法。如果自己使用 webpack 搭建就直接修改 preset 就好。