Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@babel/preset-env与@babel/plugin-transform-runtime #32

Open
Vibing opened this issue Jan 27, 2021 · 0 comments
Open

@babel/preset-env与@babel/plugin-transform-runtime #32

Vibing opened this issue Jan 27, 2021 · 0 comments

Comments

@Vibing
Copy link
Owner

Vibing commented Jan 27, 2021

babel 在转译时,会将源码分为两个部分来处理,分别是: syntax 和 api

  • syntax:类似对象展开、optional chain、let、const 等语法
  • api:类似数组的 includes 等函数、方法

@babel/preset-env

{
    "presets": [ ["@babel/preset-env"] ]
}

preset-env可以使用最新的 JavaScript Api ,它是许多 preset 的集合(es2015+),通过配置来智能使用 JavaScript。

但随着 ECMA 的发展会一直更新和增加里面的内容,比如今年(2021年)它包含的预设由:es2020、es2019、... es2015。到了明年,它的 preset 可能就多包含一个 es2021

默认情况下,preset-env 跟 babel-preset-latest 是等同的;

在发中,如果需要支持特定的浏览器,可以通过 targets 来配置,preset-env 会根据配置生成相符合的代码:

{
    "presets":[
        ["@babel/preset-env", {
            "targets": {
                "chrome": 88
            }
        }]
    ]
}

合理的配置,能减少很多无用的代码;

对于 preset-env ,syntax 语法很容易就转好了,但 api 不会做任务处理,比如:

const 属于 syntax 语法,但 includes 并没有被转译。如果运行在不支持 includes 的浏览器中就会报错。

core-js

babel 使用 polyfill 来处理 api,@babel/preset-env 中有个配置选项 useBuiltIns,用来告诉 babel 如何处理 api,它的默认值是 false,即默认不处理任何 api。

{
    "presets":[
        ["@babel/preset-env",{
            "useBuiltIns": "usage"
        }]
    ]
}

useBuiltIns 还有一个选项是entry, 即在项目入口处把整个 polyfill 引入,这样会导致包非常大,而我们需要的仅仅是能支持 includes 而已。所以不用 entry 而使用 usage ,它会根据使用 api 的情况来按需加载需要用到的 polyfill 。这里的 polyfill 来自 core-js这个库,所以完整配置如下:

{
    "presets":[
        ["@babel/preset-env",{
            "useBuiltIns": "usage",
            "corejs" 3
        }]
    ]
}

@babel/plugin-transform-runtime

babel 在转译 syntax 时,会经常使用一些辅助函数来帮忙转译,比如 class 语法中,babel 自定义了 _classCallCheck 这个辅助函数;typeof 则被重新自定义了一个 _typeof 辅助函数。这些函数叫做 helpers,一个项目中如果每个文件都有这些函数,显然会不合理。

@babel/plugin-transform-runtime就是为了解决这个问题:

  • api 从之前的直接修改原型改为从一个统一模块中引入,避免全局变量和原型的污染
  • heplers 从之前在当前文件中定义,改为从一个统一的模块中引入,这样打包结果中每个 hepler 只会存在一个

使用 @babel/plugin-transform-runtime

yarn add @babel/plugin-transform-runtime @babel/runtime -D

然后配置一下

"plugins":[
        ["@babel/preset-env",{
            "useBuiltIns": "usage",
            "corejs" 3
        }]
]

总结

  1. babel 在转译过程中,对 syntax 语法的处里非常好,但有很多 api 是不转译的,比如数组的 includes 方法

  2. preset-env 转译 JavaScript ,可以通过 useBuiltIns 来设置 core-js ,用于解决 api 的 polyfill

  3. babel 转译时,会自定义一些 helpers 函数,可以通过 @babel/plugin-transform-runtime 来抽离这些 heplers 统一导入

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant