彻底弄懂babel配置

553 阅读2分钟

前言:babel 一个神奇的工具,可以让我们的代码随意跑在任何浏览器里面。但是很多人并不是特别理解babel的配置。这里我将写出我的心得。希望对大家有用。

一个简单的demo

src/index.js

let a = () => {}
new Promise(() => {});
[].includes(()=>{
  console.log(1)
})

webpack.config.js 的配置

const path = require('path');
module.exports = {
  mode: "development",
  devtool: 'source-map',
  context: process.cwd(),
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.jsx?$/,
      use: {
        loader: 'babel-loader',
        options: {
          "presets": [
            [
              "@babel/preset-env",
              {}
            ]
          ],
          "plugins": []
        }
      },
      include: path.join(__dirname, 'src'),
      exclude: /node_modules/
    }]
  }
}

知识点普及:babel 配置主要分成预设和插件, 预设可以理解没,是一个插件的集合。

根据上述配置,执行代码,得到如下结果: image.png 我们发现, 只有语法被转换了,像全局方法Promise,与数组的原型方法。并有么做任何转换。这样子在低版本浏览器中,就会出现白屏的现象。因为全局方法与原因方法未做任何转换

怎么办?

使用@babel/polyfill,修改配置如下:

module.exports = {
  entry: ['@babel/polyfill', './src/index.js'],
  module: {
    rules: [{
      test: /\.jsx?$/,
      use: {
        loader: 'babel-loader',
        options: {
          "presets": [
            [
              "@babel/preset-env",
              {
                useBuiltIns: "entry"
              }
            ]
          ],
          "plugins": 
        }
      },
    }]
  }
}

不管三七二十一,将兼容包全部导入进来就可以兼容低版本了。

缺点:

  • 体积增加到了470KiB, 压缩后 87.2 KiB,而原来只有 345 bytes,增加了好几百倍。

优化

还好babel7以后支持了按需引入。可以减少兼容包的体积,他只要的实现逻辑是: 遍历你的代码,找到需要引入的模块。从而减少打包体积。

配置:

 "presets": [
            [
              "@babel/preset-env",
              {
                // debug:true, // 打开debug
                useBuiltIns: "usage", // 按需引入
                corejs: {
                  version: 3,
                  proposals: true
                },
                 targets: {  // 支持兼容的版本
                   android: '4.2',
                   ios: '9'
                 }
              }
          ]

经过编译和打包后: 体积是114 KiB, 压缩体积是 19.8 KiB。体积小了许多。是不是已经很完美了!!!但是也有缺点。

缺点: 这种方式会在全局添加方法,和直接修改原型。 这样子会造成全局污染,如果别人也自定义扩展了同样的方法,则会出现相互覆盖的问题。

@babel/plugin-transform-runtime

此插件可以解决全局污染的问题。

更改配置

 "plugins": [
   [
     '@babel/plugin-transform-runtime',{
       corejs:3, 
       helpers: true,
       regenerator: true
     }
   ]
  ]

代码体积: 157 KiB,压缩后体积:26.7 KiB。 通过对比可知,体积稍微大了一点点。那么打包后的代码有什么区别了。我们一起来看一下。

没有配置transform-runtime 的编译代码 image.png

配置transform-runtime 之后的编译代码 image.png

我们发现 transform-runtime 把我们写的代码都改变了。进行了重新包装,这样子就不会有全局污染了。

总结:

体积压缩后体积结论
使用全量引入,@babel/polyfill470KiB87.2 KiB最好不要使用
按需引入114 KiB19.8 KiB在项目开发中使用比较合适
transform-runtime157 KiB 26.7 KiB在写库的时候比较合适

其实还有另一种方案,不过需要服务器配置成本比较大。

polyfill-service

  • 自动化的 JavaScript Polyfill 服务
  • Polyfill.io 通过分析请求头信息中的 UserAgent 实现自动加载浏览器所需的 polyfills
  • polyfill-service
  • polyfill-io
<script src="https://polyfill.io/v3/polyfill.min.js"></script>

可以自己搭建服务器使用的。根绝浏览器,返回不同的兼容代码。