前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用babel插件的注意事项

使用babel插件的注意事项

原创
作者头像
挥刀北上
修改2021-02-22 14:56:57
5500
修改2021-02-22 14:56:57
举报
文章被收录于专栏:Node.js开发Node.js开发

这里我们主要讲解babel7的相关方法。

首先第一点就是babel的三个核心包:@babel/core、@babel/cli、@babel/type。

如果要使用命令行来执行babel则需要安装@babel/cli,如果需要在js脚本中使用babel,那么就需要安装@babel/core、和@babel/type了。

这里要注意一下这个@这个符号,这个是只有babel7才特有的,babel6都木有,市面上大量代码都是基于6的所以要特别注意。

babel常用的库有以下几种:

@babel/cli

@babel/core

@babel/preset-env

@babel/polyfill

@babel/runtime

@babel/plugin-transform-runtime

@babel/plugin-transform-xxx。

这里需要注意@babel/cli依赖@babel/core。

babel转化js语法分为两部分一部分与语法结构如const、let一部分为api也就是内置函数如includes等。

而@babel/preset-env就是转化语法结构的,@babel/preset-env是一系列插件的集合,包含了我们在babel6中常用的es2015,es2016, es2017等最新的语法转化插件,允许我们使用最新的js语法,比如 let,const,箭头函数等等。

而@babel/polyfill的polyfill直译过来就是垫片的意思就是为了转化api的工具。

@babel/preset-env如何使用呢?

简单的使用如下:

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env"
    ]
  ]
}

此时会根据只会转译语法而不会转译api,并且会根据另外一个配置来转译,这就是browserslist,这个配置有三种配置方式,一种是在.babelrc中的target参数中配置,一种是在.browserslistrc中配置,一种是在package.json中配置。

package.json中配置如下:

代码语言:javascript
复制
{
  "browserslist": [
    "last 1 version",
    "> 1%",
    "maintained node versions",
    "not dead"
  ]
}

.browserslistrc配置如下:

代码语言:javascript
复制
# 注释是这样写的,以#号开头
last 1 version #最后的一个版本
> 1%  #代表全球超过1%使用的浏览器
maintained node versions #所有还被 node 基金会维护的 node 版本
not dead

在.babelrc中的配置方式为:

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": "58",
          "ie": "11"
          }
      }
    ]
  ]
}

通过配置browserslist可以根据浏览器版本转译相应的语法,那api如何转译呢?也就是@babel/polyfill如何使用呢?答案就是配置babel/preset-env。babel/preset-env中有一个参数是开启@babel/polyfil的默认为false,也就是不开启垫片,默认如下:

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": false
      }
    ]
  ]
}

上面这种方式,即不开启垫片,不需要转译api。

第二种方式,参数值为entry,意思是在入口文件引入所有api,代码如下:

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "debug": true
      }
    ]
  ]
}

使用这种方式,还需要在入口文件手动引入@babel/polyfill,如图:

上图展示了如何引入babel/polyfill和其转译后的结果,我们可以通过转译结果看到其弊端,有两个,1是覆盖全局变量,2是引入所有垫片,用这种方式第一个缺点是无法解决的,但是我们可以通过配置browserlistrc来限制引入的方法,代码如下:

代码语言:javascript
复制
// .browserslistrc

Chrome > 75

这样转译是会根据chrome的版本来适量引入,而不是全部。

第三种方式,参数为useage,此时代码中用到谁就引入谁,比较智能。

代码语言:javascript
复制
{
  "presets": [
    ["@babel/preset-env", 
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

corejs指定polyfill的版本。

但是此时还有两个问题:api转译是全局引入,一些helper函数也是会在编译时重复生成,例如如下代码:

这样就会生成无数重复代码,咋办呢?

此时需要@babel/plugin-transform-runtime 与@babel/runtime-corejs3,其中 @babel/plugin-transform-runtime 的作用是转译代码,转译后的代码中可能会引入 @babel/runtime-corejs3 里面的模块。所以前者运行在编译时,后者运行在运行时。类似 polyfill,后者需要被打包到最终产物里在浏览器中运行。最终代码如下:

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "debug": true
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3 // 指定 runtime-corejs 的版本,目前有 2 3 两个版本
      }
    ]
  ]
}

再看转译后的代码:

从上图可以看到,在引入了 transform-runtime 这个插件后:api 从之前的直接修改原型改为了从一个统一的模块中引入,避免了对全局变量及其原型的污染,解决了第一个问题,helpers 从之前的原地定义改为了从一个统一的模块中引入,使得打包的结果中每个 helper 只会存在一个,解决了第二个问题

babel 在转译的过程中,对 syntax 的处理可能会使用到 helper 函数,对 api 的处理会引入 polyfill。

默认情况下,babel 在每个需要使用 helper 的地方都会定义一个 helper,导致最终的产物里有大量重复的 helper;引入 polyfill 时会直接修改全局变量及其原型,造成原型污染。

@babel/plugin-transform-runtime 的作用是将 helper 和 polyfill 都改为从一个统一的地方引入,并且引入的对象和全局变量是完全隔离的,这样解决了上面的两个问题。

@babel/plugin-transform-runtime需要与@babel/runtime、@babel/runtime-corejs3结合使用。

以上便是babel使用时的一些注意事项,希望对你有所帮助。

参考:https://zhuanlan.zhihu.com/p/147083132

https://segmentfault.com/a/1190000021188054

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档