乐趣区

关于javascript:Babel配置不要再复制粘贴了带你自己配一个Babel

前言

问题

咱们在应用各种打包工具,须要配置 Babel 的时候,置信大家一开始都是间接在网上 复制粘贴 一段配置过去,而后能跑通就高枕无忧了吧?因而,咱们有时会遇到打包部署后,手机运行呈现白屏问题;或者是,打包后代码包过大,加载迟缓等等问题。

其实这所有,大部分起因是因为咱们对 Babel 各项配置没有一个零碎的了解,所以即便从网上复制粘贴了配置,呈现问题了,不晓得怎么去剖析呈现的问题。

筹备

如果你曾经对 Babel 曾经有一个大略的理解了,那浏览这篇文章,会让你对配置有一个更零碎的理解;如果你才刚接触 Babel,或者对Babel 处于懵懵懂懂的状态,那我强烈建议你先浏览这篇文章——想弄懂 Babel?你必须得先弄清楚这几个包,它次要介绍剖析了一些概念跟以下几个包:

  • @babel/core
  • @bable/cli
  • @bable/preset-env
  • polyfill
  • @babel/polyfill
  • core-js
  • @babel/runtime
  • @babel/plugin-transform-runtime

并且为咱们答疑了一些看官网时的纳闷。因为在分明了这几包后,咱们学习配置这块会更容易了解一些。

备注

  • 以后 @babel/core 最新版本是:7.20.12
  • 以后 @babel/preset-env 最新版本是:7.20.2

再谈core-js

通过上篇文章—— 想弄懂 Babel?你必须得先弄清楚这几个包咱们晓得:core-js是一种 polyfill,它提供了旧版本浏览器缺失的 所有 ES6+ API的办法与实现。

在这里,以及下文,咱们把通过引入 core-js某个模块 ,来实现旧版本浏览器不反对的 某个 ES6+ API 的过程,叫做垫平。

咱们看看 core-js 这个包外面的次要一些模块:

  • es:外面只蕴含有稳固的 ES 性能。
  • proposals:外面蕴含所有 stage 阶段的API
  • stable:它外面蕴含了,只有稳固的 ES 性能跟网络规范

所以,咱们能够这么应用:

  • 当咱们只须要垫平 某个 稳固的 ES6+ API,咱们能够用es 这个文件夹里的 polyfill 来垫平(import X from 'es/xx'
  • 当咱们须要用到 提案阶段 API时,我就用 proposals 这个文件夹里的 polyfill 来垫平(import X from 'proposals/xx'
  • 当咱们想垫平 所有稳固版本 ES6+ API,能够导入用 stable 文件夹(import 'core-js/stable'
  • 当咱们想垫平 所有 ES6+ API(包含提案阶段),能够间接import 'core-js'

以上是我集体的应用习惯,因人而异,具体的介绍能够看看参考文章。

参考文章:core-js

再谈@bable/preset-env

通过上篇文章—— 想弄懂 Babel?你必须得先弄清楚这几个包,咱们晓得:

  • Babel大体由两个性能组成:

    1. 编译 ES6+ 最新语法(letclass() => {}等)
    2. 实现旧版本浏览器不反对的 ES6+APIPromiseSymbolArray.prototype.includes等)
  • @babel/preset-env有以下两个性能:

    1. 只编译 ES6+ 语法
    2. 它并不提供 polyfill,然而能够通过 配置 咱们代码运行的 指标环境 ,从而管制polyfill 的导入跟语法编译,使 ES6+ 的新个性能够在咱们想要的 指标环境 中顺利运行
  • @babel/plugin-transform-runtime也有以下两个性能:

    1. @babel/runtime@babel/plugin-transform-runtime 两者配合,能够缩小打包体积
    2. 也有一个配置性能,用来解决 polyfill 如何垫平
  • 如果咱们想要在旧浏览器用到 ES6+ API 时,咱们应该装置 3 版本的core-js(或者后续更高版本的);

那咱们能够很分明的晓得:

  • 实现 Babel 第一个性能:咱们用 @babel/preset-env 就能够了
  • 实现 Babel 第二个性能:咱们就须要用 core-js 这个包来提供 polyfill,并与@babel/preset-env 或者 @babel/plugin-transform-runtime 的配置性能相互配合应用

咱们先来看看 @babel/preset-env 的配置项有哪些:

// babel.config.js
const presets = [
    [
        '@babel/preset-env',
        {
            modules,
            targets,
            corejs,
            useBuiltIns,
            
            spec,
            loose,
            debug,
            bugfixes,
            include,
            exclude,
            forceAllTransforms,
            configPath,
            ignoreBrowserslistConfig,
            browserslistEnv,
            shippedProposals
        }
    ]
];
module.exports = {presets};

咱们能够看到配置项还是蛮多的(有一些配置项,前期可能会废除),然而,其实咱们平时我的项目中次要用到前四个配置,所以在这里咱们重点来看看前四个配置(能不学的尽量不学,太累了)。

参考文章:@babel/preset-env

modules

  • 性能:启用 ES 模块语法向另一种模块类型的转换
  • 默认值:auto
  • 可取的值:"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false

当咱们设置成 false 的时候,Babel编译产生的一些辅助函数的引入形式会变成 ES6 的模式引入(import A from 'B')。

咱们把 use-transform-runtime 这个案例 Babel 配置改成以下配置,感受一下 modules 这个配置的性能。

// babel.config.js

const plugins = ['@babel/plugin-transform-runtime']

const presets = [
    [
        '@babel/preset-env',
        {modules: false}
    ]
];

module.exports = {plugins, presets};

没设置 modules 配置项 时,编译后的文件是:

咱们会发现辅助函数都是以 require 的形式引入的;

设置了 modules 配置项 后,编译后的文件是:

咱们会发现辅助函数变成了咱们相熟的 ES6 模块形式 import 引入。

这样有一个益处,就是咱们用一些像 Webpack 打包工具时,能够对代码动态剖析,很好地 tree shaking 缩小代码体积,所以咱们配置 Babel 的时候倡议设置modules: false

参考文章:modules

targets

作用

它的用法与 browserslist 统一。它能够用来设置咱们的代码须要兼容的 指标环境,因而它:

  • 能够无效地缩小 ES6+ 的语法编译
  • 能够无效管制 polyfill 导入多少

留神

第一点

如果咱们没有设置这个配置项时,它会去咱们的 Babel 配置文件找 顶层的 targets;如果顶层没有设置targets,则会去咱们的package.json 里的 browserslist 或者根目录找.browserslistrc;如果还没有则默认值为{}。查找过程大抵如下,序号代表查找程序:

// Babel 配置文件
{
    targets: 'ie 10', // 2. 如果 presets 外面没有设置 targets,会来这里查找
    presets: [
        [
            '@babel/preset-env',
            {targets: 'ie 9' // 1. 先在这里查找,没的话去顶层 targets 查找}
        ]
    ]
}

// package.json
{
    ...,
    browserslist: ['ie 11' // 3. 如果顶层 targest 外面没有设置,会来这里查找;如果这里也没设置,则为默认值{}
    ]
}
第二点

如果咱们没有设置这个配置项时,Babel会假如咱们要兼容的指标环境是最旧的浏览器,所以会将所有的 ES6+ 语法代码转化为 ES5 所以咱们配置 Babel 的时候,要设置 targets 以缩小输入代码大小。

针对这点,咱们用这个案例 preset-env-targets-config 来感受一下:

咱们会发现 ES6+ 的写法全副被转成了ES5,还退出了一些辅助函数(红色框)。

ok,咱们设置 targets: 'chrome 80'。这示意,咱们的代码是要在chrome 80 上运行的,再看看打包后的后果:

咱们会发现编译进去的代码,跟咱们入口文件写的代码根本没差。因为 chrome 80 曾经实现了入口文件代码的写法了。所以,如果咱们的代码不须要在一些比拟低端的浏览器跑的话,设置 targets 就非常有必要。

参考文章:targets

corejs

useBuiltIns 不为 false 的时候,须要设置这个配置项

配置

它有两种配置形式:

  1. 间接设置 core-js 版本号

    ...
    {
        useBuiltIns: 'usage',
        corejs: '3.27.2'
    }
    ...
  2. 配置corejs

    ...
    {
        useBuiltIns: 'usage',
        corejs: {
            version: '3.27.2',
            // 是否编译提案阶段 ES6+ API
            proposals: false
        },
    }
    ...

留神

  1. 当咱们的 useBuiltIns 不为 false 的时候,须要设置 corejs 这个配置项
  2. 2版本的 core-js 曾经不倡议应用了;咱们用当然要用最新的,目前最新的版本是core-js@3.27.2
  3. 咱们装置的 core-js 要尽量放弃最新,因为越新的包,蕴含的 polyfill 才会越多
  4. 咱们设置 corejs 的版本号时,不要间接指定 2 或者 3,它会被解析为2.0 或者 3.0。所以,咱们应该带上 子版本号3.27.2),这样才会有最新的polyfill
  5. core-js默认用 稳定版 polyfill来垫平,但如果有时咱们想用还处在提案阶段的 API 怎么办?

    • 如果咱们配置的是 useBuiltIns: entry,咱们得手动引入core-js 提案的 polyfill 来垫平。提案的 polyfill 放在 core-js/proposals 文件夹中import 'core-js/proposals/array-last'
    • 如果咱们配置的是 useBuiltIns: 'usage',则咱们用下面说的corejs 模块外面提到的第二种配置形式,把 proposals 设为 true 就能够了

它的作用会联合上面的 useBuiltIns 一起讲。

参考文章:targets

useBuiltIns

下面咱们提到了,咱们把通过引入 core-js某个模块 ,来实现旧版本浏览器不反对的 某个 ES6+ API 的过程,叫做垫平。

这个配置就是用来设置咱们 core-js 的垫平形式的。它有上面三个值:

为了更好的了解,咱们用 Promise 这个 ES6+ API 作为上面的例子。咱们都晓得:

  • IE 11并不反对Promise
  • Promise这个对象其实还有很多办法,例如 Promise.anyPromise.allPromise.finally 等。
  • 咱们用这个案例 preset-env-useBuiltIns-config 来解说

entry

咱们能够这么了解,entry中文是“进入”的意思,这个值阐明咱们的 polyfill 应该是须要从某个 入口 引入来垫平。

体现

咱们把配置设置为:useBuiltIns: 'entry'

  • 咱们先来看看这个配置在 IE 11 的表现形式,咱们设置targets: 'ie 11'
  • 咱们再把 targets 设置成 chrome: 80 看看体现:
剖析
  • IE 11 的体现

    咱们 import 'core-js/es/promise'(相当于import 某块 polyfill 来垫平),因为咱们的 IE 11 不反对 Promise,所以useBuiltIns: 'entry' 配置把咱们 所有 不反对的 Promise 办法都垫平了(打印的 window.Promise.any 有值)。

  • chrome 80 体现

    咱们 import 'core-js/es/promise'(相当于import 某块 polyfill 来垫平),因为在 chrome 80 中,Promise大部分办法曾经实现,只有 Promise.any 没有实现,所以此时只垫平了 promise.any 办法。

总结

所以咱们能够总结出,它的执行原理大抵是这样的:

  1. 咱们须要 手动 import 所有 或者 某块polyfill
  2. Babel会依据咱们设置的 targets(指标环境),来判断咱们手动import所有 或者 某块 polyfill 是不是以后缺失的
  3. 如果是的话,就会把咱们手动 import 所有 或者 某块 polyfill,拆分成很多小模块, 引入咱们指标环境不反对的模块
留神
  • 为了防止一些奇奇怪怪的问题,咱们手动 importpolyfill应该 对立在入口文件(咱们当初的工程项目个别都会有一个入口文件)
  • 如果咱们想一劳永逸,间接把以后环境 所有 不反对的 ES6+ API 垫平,那咱们就 import 'core-js/stable'(这会垫平以后targets 不反对的所有稳固版本的ES6+ API,所以也会导致包变大)
  • 如果咱们只想单纯垫平 某个 ES6+ API(前提是targets 不反对这个 API,否则手动import 了也没用;例如只想垫平 Promise),那咱们import 'core-js/es/promise 就能够了
  • 如果想垫平提案阶段的 API,则也须要手动import 对应提案的polyfillimport "core-js/proposals/string-replace-all

参考文章:usebuiltins

usage

这个值的作用,就是咱们不须要手动 import,它会主动帮咱们import 以后 targets 缺失的polyfill

体现

咱们把配置设置为:useBuiltIns: 'usage'

  • 咱们先来看看这个配置在 IE 11 的表现形式,咱们设置targets: 'ie 11'
    !
  • 咱们再把 targets 设置成 chrome: 80 看看体现:
剖析
  • IE 11 的体现

    咱们不必本人手动 import 相干 polyfill,咱们的代码中只用到了繁多的Promise 对象,所以 只垫平 Promise这个对象,不会垫平它其余相干的办法(打印的 window.Promise.any 无值)。

  • chrome 80 的体现

    咱们不必本人手动 import 相干 polyfill,此时没有任何对于Promise 的垫平,因为繁多的 Promise 对象在 chrome 80 曾经实现,且咱们代码中没有用 Promise.any 办法,天然也就不会垫平 Promise.any。此时代码只垫平了提案阶段的array.lastItem 办法,因为 chrome 80 不反对它,并且咱们代码中用到了它

总结

所以咱们能够总结出,它的执行原理大抵是这样的:

  1. 咱们 不须要手动 import 所有 或者 某块polyfill
  2. Babel会依据咱们以后代码中用到的 ES6+ API,并判断以后的targets 支不反对咱们用到的这个ES6+ API
  3. 如果不反对的话,则 主动导入这个 ES6+ API 对应的polyfill

因为它会主动导入,所以咱们专一写咱们的 ES6+ 就好了。

参考文章:usebuiltins

false

它是默认值。它示意不要在每个文件中主动增加 polyfill,也 不会依据 targets 判断 缺不缺失,也不会将咱们手动 import 所有 或者 某块 polyfill 拆分为单个 polyfill 引入。

体现

咱们把配置设置为:useBuiltIns: false

  • 咱们先来看看这个配置在 IE 11 的表现形式,咱们设置targets: 'ie 11'
  • 咱们再把 targets 设置成 chrome: 80 看看体现:
总结

useBuiltIns设置为false:

  • 对咱们的垫平形式没作用,源码是什么样,输入就是什么样
  • 设置 targets 有效

参考文章:usebuiltins

应用

适配 IE 11

置信通过下面的解说,咱们对各个配置项有个大略的理解了,那咱们再更深刻体验一下。

咱们都晓得 IE 11 根本是不反对 ES6+ 的,咱们抽几个罕用的 ES6+ API 看看:

那咱们就用 IE 11 作为咱们的 targets(指标环境),钻研一下如何配置Babel,使咱们写的ES6+ 代码能在 IE 11 中跑起来。咱们用这个案例 preset-env-template-config

留神:
为了防止 Webpack 打包谬误,咱们把 targets 写在 package.json 中,这样 Webpack 能力辨认环境打包

...
"browserslist": ["ie 11"]
 ...

咱们用一下这段代码作为咱们的入口文件:

// 如果用 `usage` 形式,则正文掉这段代码
import 'core-js/stable';

const lMC = {
    name: 'limingcan',
    like: ['eat', 'drink', 'play', 'fun'],
    breath() {
        return new Promise(resolve => {setTimeout(() => resolve(), 1000)
        })
    }
};

lMC.breath().then(() => console.log('breath'));
console.log(lMC.like.includes('play'));
console.log(Array.of(1, 2, 3));

依据咱们下面几个配置项的解说,如果咱们想:

  • 一劳永逸的间接垫平 targets 所有不反对的ES6+ API,那咱们的配置应该是:

    const presets = [
        [
            '@babel/preset-env',
            {
                modules: false,
                useBuiltIns: 'entry',
                corejs: {
                    version: '3.27.2',
                    proposals: true
                }
            }
        ]
    ];
    module.exports = {presets};

    此时 IE 11 失常输入:

    红色框是咱们源码中 没用到的ES6+ API,也都被垫平了;此时包的大小有115K

  • 如果咱们想缩小包的体积,只垫平咱们用到的ES6+ API,那咱们的配置应该是:

    const presets = [
        [
            '@babel/preset-env',
            {
                modules: false,
                useBuiltIns: 'usage',
                corejs: {
                    version: '3.27.2',
                    proposals: true
                }
            }
        ]
    ];
    module.exports = {presets};

    此时 IE 11 失常输入:

    然而咱们会发现,红色框是咱们源码中没用到的ES6+ API,它并没有被垫平的,它只会垫平咱们代码中用到的API;此时包的大小只有29K

常见问题

通过下面的例子,咱们会发现:

如果配置是useBuiltIns: 'entry'

  1. 咱们垫平的 polyfill,都是注入到window 全局的,或者是某个内置对象的原型(prototype)上,这 影响到了全局
  2. 一劳永逸的形式会垫平以后 targets 所有不反对的 ES6+ API,这尽管不便,但这会导致 包变得很大

如果配置是useBuiltIns: 'usage'

  1. 它也会将垫平的 polyfill 注入到全局。
  2. 因为 useBuiltIns: 'usage' 是判断以后 targets 支不反对咱们代码中用到的 ES6+ API,如果不反对会本人import
    那有这样一种状况,如果第三方库用到了咱们以后 targets 不反对的 ES6+ API,但咱们本人的代码没有用到这个API,那么这个API 是不会被叠平的,这会导致咱们我的项目报错。

第三方库问题

针对 useBuiltIns: 'usage' 配置的第二点弊病,咱们来看这个例子 use-third-party-library-problem 更间接的感受一下。

咱们把 targets 设为 IE 11,咱们 本人的代码只用 includes 这个 ES6+ API,而后再用第三方库 tars-utils 的optimizeImage 办法,生成一个 Blob 对象(外面是用 Promise 实现的)。

咱们在 IE 11 跑一下看看:

通过 Babel 编译后的文件,咱们会发现:

  • 只有咱们代码中应用的 includes 办法被垫平;
  • 第三方库中用到的 Promise 并没有被垫平,所以导致 IE 11 报错了。这是一个十分事实的问题。

咱们在高级一点的浏览器(chrome 108)看看:

chrome 108 运行没有任何问题,因为 chrome 108 曾经外部实现了Promise

总结

看到这里,置信咱们对 @babel/preset-env 的配置性能曾经有个大略的理解了。上述所说的问题的确是咱们很理论的问题。

因而,useBuiltIns设置 entry 还是usage,还是得依据咱们我的项目理论需要来,我集体倡议:

  • 因为咱们 @babel/preset-env 配置形式,是会把以后 targets 缺失的 API 注入到全局 ,所以这个配置形式是比拟适宜咱们做的一些 前端工程项目 或者 应用程序 。如果对包的体积不是很在意,倡议应用useBuiltIns: entry 的形式,而后再import 'core-js/stable',一劳永逸的垫平,这样能够帮咱们防止掉一些奇怪的问题,
  • 如果应用 useBuiltIns: usage,那还是得留神第三方库的问题。如果判断出哪块polyfill 缺失,咱们能够本人手动 import 去垫平

再谈@babel/plugin-transform-runtime

下面说到,@babel/preset-env配置形式,是会把以后浏览器缺失的 API 注入到全局的 ,那么有没有不注入全局的方法呢?答案是有的。它就是咱们接下来要讲的@babel/plugin-transform-runtime 配置。

咱们先来看看它有几个配置项(谢天谢地,不算很多):

// babel.config.js
const plugins = [
    [
        '@babel/plugin-transform-runtime',
        {
            helpers,
            regenerator,
            corejs,
            
            version
        }
    ]
];
module.exports = {plugins};

helpers && regenerator

解析

咱们先看前两个配置,因为前两个配置比较简单,咱们放在一起讲。

  • helpers默认值是:true
  • regenerator默认值是:true

通过上篇文章——想弄懂 Babel?你必须得先弄清楚这几个包,咱们晓得:

对于@babel/runtime

  • @babel/runtime 寄存了 Babel 辅助函数的一个汇合包

对于辅助函数

  • 当咱们只用了一些 ES6+ 语法糖的时候,Babel编译时会内联注入一些辅助函数
  • @babel/plugin-transform-runtime@babel/runtime 配合应用时,会将咱们用到的辅助函数,从 @babel/runtime 中以 require 或者 import 的形式,引入到咱们的文件中,实现复用,从而减小咱们最终输入包的体积。

对于regenerator

  • 咱们的源码外面应用了 async function() {} 等异步函数,或者 fuction* myGenerator() {} 这种 Generator 函数的话,就会须要用到 regenerator-runtime 这个包来编译。
  • Babel >= 7.18.0regenerator-runtime包里的内容,会以 局部变量的形式内联注入到咱们的代码中 ,这样咱们就不须要全局提供一个regeneratorRuntime 对象。

例如咱们应用了 class 语法糖跟 async function() {},而后用@babel/runtime@babel/plugin-transform-runtime(默认状况下,helpersregenerator 值为true)配合应用,编译后如下图:


当咱们把 helpersregenerator的值设为false

咱们会发现咱们的辅助函数,跟 regenerator-runtime 这个包又变回了内联形式。所以:

  • helpers:管制的是咱们的辅助函数,是否不内联 进咱们的代码中。

    • true的话是不内联,而是援用 @babel/runtime 辅助函数汇合包
    • false的话,则会内联
  • regenerator:与 helpers 相似,管制的是咱们 regenerator-runtime 这个包的代码,是否不内联 进咱们的代码中。

    • true的话是不内联,而是援用 @babel/runtime 辅助函数汇合包
    • false的话,则会内联

留神

官网中对于 regenerator 的解释,大抵意思是:
regenerator如果设为 false,须要咱们提供一个全局的regeneratorRuntime 的对象。

然而:

  • Babel >= 7.18.0 当前,regenerator-runtime包里的内容,会以 局部变量的形式内联注入到咱们的代码中 。所以其实Babel >= 7.18.0 regenerator 这个配置项集体感觉是根本没用了
  • Babel < 7.18.0的话,则须要咱们提供一个全局的 regeneratorRuntime 的对象。相干案例可查看 import-regenerator-runtime,开启 babel.config.js 相干正文代码。

corejs

解析

corejs这个配置项一旦不为 false,就是用来设置咱们的要垫平的ES6+ API,以 不净化全局局部变量形式垫平。

它有三个值:

对应依赖 补充
false(默认值) @babel/runtime
2 @babel/runtime-corejs2 1. 只能编译反对全局变量(如Promise)和动态属性(如Array.from);<br/>2. 不能编译实例相干办法([].includes
3 @babel/runtime-corejs3 1. 既能编译能编译反对全局变量和动态属性,又能编译实例办法
2. 开启proposals: true,还能够编译提案阶段的API

咱们用这个例子 transform-runtime-config 体验一下。

  • 如果配置的是 corejs: 2 的话,会怎么样:

    咱们会发现,实例办法 includes 没被垫平,提案 APIMath.signbit)也没有被垫平;Promise 是以局部变量的形式呈现在咱们的代码中。

  • 咱们再看看配置的是corejs: {version: 3, proposals: true}

咱们会发现,实例办法 includes 被垫平,提案 APIMath.signbit)也垫平;但它们都以 局部变量 的形式注入。

所以,如果咱们不想以全局的形式净化的形式垫平咱们的 ES6+ API,咱们corejs 就不能为 false,并且优先应用@babel/runtime-corejs3 这个包来垫平(设置为3

优化

下面的案例咱们并没有设置 targets,所以@babel/plugin-transform-runtime 配置下,会把咱们代码中用到的 所有 ES6+ API 都垫平。咱们来设置 targets,看看能不能垫平咱们的targets 不反对的ES6+ API

咱们在 package.json 外面增加,或者在 配置文件的顶层 增加是能够的(通过测试,在 @babel/preset-env 外面设置 targets 是不行的):

// package.json
"browserslist": ["chrome 80"]

// 或者在顶层增加
module.exports = {targets: {chrome: 80}, // 在这里增加
    presets: ['@babel/preset-env'],
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {...}
        ]
    ]
}

输入:

咱们会发现,Promiseincludes 都没有被垫平,因为 chrome 80 曾经反对了

总结

  • @babel/preset-env是以全局形式垫平,@babel/plugin-transform-runtime是以局部变量形式垫平,两者咱们应该抉择其一,不要又用 @babel/preset-env 配置形式,又用 @babel/plugin-transform-runtime 配置形式,这样必定会呈现一些奇奇怪怪的问题。
  • 因为应用 @babel/plugin-transform-runtime 垫平是以 局部变量的形式 来垫平,所以 @babel/plugin-transform-runtime 这种配置形式更适宜来做 的开发。它能够很好的帮咱们的库与使用者的我的项目解耦。

参考文章:babel-plugin-transform-runtime

其余

  • 案例 preset-env-useBuiltIns-config 外面有个 stage-1 阶段的提案 API—— Array.prototype.lastItem(取数组最初一项)。原本是想用Array.prototype.uniqueBy 这个以后处在 stage-1API来给大家做例子的,后果发现编译当前在 IE 11 有问题。所以给 Babel 提了个 issues:

    目前应该是修复了,在等合并。复现问题的代码包在 babel-use-proposals-problem,感兴趣的敌人也能够 Fork 本人瞅瞅。说这个事次要也是想表白,学习还是不能进行(不是卷啊,还是要有学习的习惯)。

  • 在讲 @babel/plugin-transform-runtime 如何配置时,咱们说到开启 {version: 3, proposals: true} 时,能够以局部变量的形式对提案阶段的 ES6+ API 垫平。

    然而通过测试发现,有些提案阶段的 API,用这个办法仿佛是不能按预期实现的,所以又提了个 issues,有个Babel 之一的大佬说能够用 babel-plugin-polyfill-corejs3 来实现:

    对于 babel-plugin-polyfill-corejs3 这块,其实 Babel 还有一种垫平配置形式,是应用 babel-polyfills 这个包来实现的,这块前期再看看要不要出文章聊聊。

最初

通过以上的理解,咱们最初来总结一下这个配置。

  • 如果咱们开发的我的项目是 应用程序 ,或者 大型的我的项目,那咱们能够这么配置:

    // Babel 配置
    const presets = [
        [
            '@babel/preset-env',
            {
                modules: false,
    
                // 或者只想用垫平咱们代码中用到的 --> useBuiltIns: 'usage',
                useBuiltIns: 'entry',
                corejs: {
                    version: '3.27.2',
                    proposals: true
                }
            }
        ]
    ];
    const plugins = ['@babel/plugin-transform-runtime'];
    module.exports = {plugins, presets};
    
    // package.json
    {
        ...,
        // 设置指标环境
        "browserslist": ["ie 11"]
    }
    
    // 入口文件
    // ---- useBuiltIns: 'entry' 时,须要引入以下 ----
    // 垫平全副 ES6+ 稳定版 API
    import 'core-js/stable'; 
    // ---- 或者 -----
    // 垫平所有 ES6+ API,包含提案阶段
    import 'core-js';

  • 如果咱们是想开发一个 第三方库,咱们能够这么配置:

    // Babel 配置
    const presets = [
        [
            '@babel/preset-env',
            {modules: false}
        ]
    ];
    const plugins = [
        [
            '@babel/plugin-transform-runtime',
            {
                corejs: {
                    version: 3,
                    proposals: true
                }
            }
        ]
    ];
    module.exports = {plugins, presets};
    
    // package.json
    {
        ...,
        // 设置指标环境
        "browserslist": ["ie 11"]
    }
    
    // 入口文件
    const Method = {wait(delay) {return new Promise(resolve => setTimeout(() => resolve(), delay);
        }
    }
    ...

文章波及到的例子,曾经上传 Github,感觉有帮忙的话,欢送 Star 或者 Fork 学习。

如果读完这篇文章的你,感觉真的有帮忙到,欢送点赞珍藏 ;如果有异同点, 欢送在评论区探讨

本文参加了 SegmentFault 思否写作挑战赛,欢送正在浏览的你也退出。

退出移动版