记录Next项目低版本浏览器代码兼容polyfill处理问题

今天发现一个Object.hasOwn的API在低版本浏览器中无法兼容的问题。
考虑了如下解决方案,一个个说

1. 回退之前的hasOwnProperty旧版本API。

治标不治本,还有其他的兼容API没有处理。

2. 引入polyfill

但是我以为next原本就配置好了polyfill的预设,为什么还会这样呢,可能是next的预设兼容的浏览器版本还是没有覆盖那个旧的版本。
说起来其实我对polyfill只知道babel做了处理,但却不知道具体操作,因此调研了一下:
参考:

  1. polyfill使用:https://juejin.cn/post/6923912946238095368?from=search-suggest
  2. next中预设polyfill的配置优化:https://juejin.cn/post/7077380997133631495

下面的文章顺序也是先讲怎么使用polyfill和它的规则,后面再说next里怎么配置的。

2.1 @babel/polyfill

一个早期方案,现已不再使用。会导致node_modules依赖的三方库的代码也被改写。

会导致

2.2 @babel/plugin-transform-runtime+core-js@3

配置如下

yarn add @babel/plugin-transform-runtime
yarn add core-js@"^3"
yarn add @babel/runtime-corejs3

module.exports = {
    presets: [
        [
            '@babel/preset-env'
        ],
    ],
    plugins: [
        [
          "@babel/plugin-transform-runtime",
          {
            corejs: 3,
          }
        ]
    ]
};

2.3 @babel/preset-env + usage or entry

usage和entry比较好理解,entry默认会把整个core-js打包进最终代码,而usage会分析你使用到的代码

// 首先在打包入口的index.js处引入垫片
import 'core-js/stable'
import "regenerator-runtime/runtime";

// 然后配置预设
module.exports = {
    presets: [
        [
            '@babel/preset-env',{
                useBuiltIns: 'entry',
                corejs: 3,
            },
        ],
    ],
};
useBuiltIns:entry or usage

如果是entry,可以在打包后的输出chunk代码中看到引入了polyfill的所有方法,随意搜索一个ES6+的API都能在打包后的代码中找到,同时打包未压缩前的体积非常大
因此才引入了usage的配置。
usage可以根据当前打包的代码中API引入对应的polyfill API。不过只针对ES modules规范,如果依赖是CJS规范的话,依赖中的代码若需要polyfill无法被usage检测出来,这样就把风险转移给了第三方代码库的自兼容上。

@babel/preset-env + useBuiltIns:usage + @babel/plugin-transform-runtime+core-js@3

但是@babel/preset-env会引入重复的内联函数(“助手函数”,具体看参考文章中的截图),为了能提取这些重复方法,还需要@babel/plugin-transform-runtime来解决,最终的设置如下:

module.exports = {
    presets: [
        [
            '@babel/preset-env',
            {
                useBuiltIns: 'usage',
                corejs: 3,
            },
        ],
    ],
    plugins: [
        [
          "@babel/plugin-transform-runtime",
          {
            // vue-cli的配置,可以避免重复注入相同兼容API
            // polyfills are injected by preset-env & polyfillsPlugin, so no need to add them again
            corejs: false,
            version: require('@babel/runtime-corejs3/package.json').version,
          }
        ]
    ]
};


3. Next中的polyfill处理

参考文章:
next中预设polyfill的配置优化,上面2写过一遍这个链接的。
什么是预设中的browserslist>0.25%和"last 2 versions" ?

我找了一下github我的这个12.0.7版本的babel预设,看起来是没有配置什么useBuiltIns和browserList,应该都是用的默认配置。

参考博主目前是采用了主动给第三方node_modules依赖增加该API的 polyfill来解决问题。

  1. webpack中主动增加打包入口,增加一个polyfill垫片的打包文件。

config.entry = async () => {
const entries = await originalEntry();
if (entries['main.js']) {
entries['main.js'].unshift('./static/js/polyfills-legacy.js');
}
return entries;
};
  1. 那个polyfill垫片文件./static/js/polyfills-legacy.js
// React
import 'core-js/es6/map';
import 'core-js/es6/set';
// Next.js
import 'core-js/fn/string/starts-with';

4. 调试方案:

可以看这里面推荐的:https://zhuanlan.zhihu.com/p/4030685403

  • 如果兼容的版本范围要求不是很高并且时间不是特别长,
    可以用这个网站,免费的:https://www.browserling.com/#pricing

  • 收费的有browserstack等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值