美文网首页
@babel/preset-env和@babel/plugin-

@babel/preset-env和@babel/plugin-

作者: PoWerfulHeart | 来源:发表于2022-08-04 14:16 被阅读0次

    前言

    babel只是转换语法,后为了解决API的兼容,又引入了pollify概念,再后来为了解决组件开发者的环境多样性,又引入了runtime。

    本文以async、Promise、Array.prototype.includes三个方法如何运行在IE9中作为例子,粗略探讨两者之间的差别和使用。
    详见官网

    环境

    为了清晰直观,本文采用两种方式编译

    • @babel/cli
      直接编译代码,更清晰看到babel帮我们引入了什么
    • rollup
      将代码编译成浏览器可运行代码,验证结果
      //package.json
      "devDependencies": {
        "@babel/cli": "^7.18.10",
        "@babel/core": "^7.18.10",
        "@babel/plugin-transform-runtime": "^7.18.10",
        "@babel/preset-env": "^7.18.10",
        "rollup": "^2.6.1",
        "rollup-plugin-babel": "^4.4.0",
        "rollup-plugin-commonjs": "^10.1.0",
        "rollup-plugin-node-resolve": "^5.2.0"
      },
      "dependencies": {
        "@babel/runtime": "^7.18.9",
        "@babel/runtime-corejs3": "^7.18.9",
        "core-js": "^2.6.12"
      }
    
    //rollup.config.js
    import resolve from 'rollup-plugin-node-resolve';   //帮助rollup查找外部模块,然后导入
    import babel from 'rollup-plugin-babel';            
    import commonjs from 'rollup-plugin-commonjs';      //将CommonJS模块转换为ES2015供rollup处理
    
    export default {
        input: './a.js',
        output: {
            file: './b.js',
            format: 'iife'
        },
        plugins: [
            resolve(),
            babel({
                exclude: 'node_modules/**',
                runtimeHelpers: true      //启用babel runtime
            }),
            commonjs({})
        ]
    };
    

    preset-env

    说明

    preset-env本身只解决了语法层面的问题,配合polyfill(polyfill是一个统称,常见的包括@babel/polyfill和core-js等)可以解决api兼容问题
    @babel/core 7.4.0后polyfill被废弃,被core-js/stable代替(因为@babel/polyfill的核心就是core-js)
    来自官方:

    As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable (to polyfill ECMAScript features)

    特别注意
    如果要转换generator或者async,当@babel/core版本小于7.18.0时,需要自行加载regenerator-runtime
    来自官方:

    If you are compiling generators or async function to ES5, and you are using a version of @babel/core or @babel/plugin-transform-regenerator older than 7.18.0, you must also load the regenerator runtime package. It is automatically loaded when using @babel/preset-env's useBuiltIns: "usage" option or @babel/plugin-transform-runtime

    配置

    useBuiltIns

    有三个值可选

    false

    不需要导入core-js
    不用polyfill,如果入口文件中导入了core-js, 会无视targets的配置加载所有的 polyfill

    entry

    需要在入口文件中导入core-js

    // a.js
    import "core-js/stable";
    
    (async () => {
        const arr = await Promise.resolve([1,2,3]);
        console.log(arr.includes(2));
    })();
    
    // .babelrc
    {
        "presets": [
            [
                "@babel/preset-env",
                {
                    "debug": true,
                    "useBuiltIns": "entry",
                    // "corejs": {      //默认version为2,使用3需要安装core-js@3
                    //     "version": "3"
                    // },
                    "targets":{
                        "browsers":["ie >= 9"]
                    }
                }
            ]
        ]
    }
    
    直接编译,执行命令:
    npx babel a.js -o b.js
    

    b.js结果如下:

    image.png
    可以看到babel导入了基于targets配置所有不支持的全部特性,并且注入了helper函数
    rollup编译,执行命令:
    npm run build
    

    Edge中模拟IE9顺利打印出true

    usage

    需要在入口文件中导入core-js(a.js同上)

    // .babelrc
    {
        "presets": [
            [
                "@babel/preset-env",
                {
                    "debug": true,
                    "useBuiltIns": "usage",
                    // "corejs": {      //默认version为2,使用3需要安装core-js@3
                    //     "version": "3"
                    // },
                    "targets":{
                        "browsers":["ie >= 9"]
                    }
                }
            ]
        ]
    }
    
    直接编译,执行命令:
    npx babel a.js -o b.js
    

    b.js结果如下:


    image.png

    可以看到babel只导入了基于targets配置且在代码中使用到的特性,并且注入了helper函数

    rollup编译,执行命令:
    npm run build
    

    Edge中模拟IE9顺利打印出true

    plugin-transform-runtime

    说明

    plugin-transform-runtime配和runtime使用可以按需引入特性,并且挂载在内建变量中,不污染全局,特别适合组件开发者使用。

    runtime

    组成

    runtime包含了helper 的 runtime 版本,corejs,和实现 async、await 的regenerator
    runtime 这3部分除了 helper 其他都是第三方的

    作用

    • 自动移除语法转换后内联的辅助函数(inline Babel helpers),使用@babel/runtime/helpers里的辅助函数来替代;

    • 当代码里使用了core-js的API,自动引入@babel/runtime-corejs3/core-js-stable/,以此来替代全局引入的core-js/stable;

    • 当代码里使用了generator/async函数,自动引入@babel/runtime/regenerator,以此来替代全局引入的regenerator-runtime/runtime;

    到这儿你应该知道了,plugin-transform-runtime其实是preset-env的增强

    特别注意
    corejs2仅支持全局变量和静态属性polyfill(例如:Promise和Array.from),要兼容incluedes等实例属性需要用到corejs3

    corejs option Install command
    false npm install --save @babel/runtime
    2 npm install --save @babel/runtime-corejs2
    3 npm install --save @babel/runtime-corejs3

    配置

    corejs

    不需要导入core-js

    // a.js
    (async () => {
        const arr = await Promise.resolve([1,2,3]);
        console.log(arr.includes(2));
    })();
    
    // .babelrc
    {
        "presets": [
            [
                "@babel/preset-env",
                {
                    "debug": true,
                    "targets":{
                        "browsers":["ie >= 9"]
                    }
                }
            ]
        ],
        "plugins": [
            [
                "@babel/plugin-transform-runtime",
                {
                    "corejs": "3"
                }
            ]
        ]
    }
    
    直接编译,执行命令:
    npx babel a.js -o b.js
    

    b.js结果如下:


    image.png

    可以看到内联的helper函数都被@babel/runtime-corejs3/helpers/替换,并且只导入了基于targets配置且在代码中使用到的特性

    rollup编译,执行命令:
    npm run build
    

    Edge中模拟IE9顺利打印出true

    相关文章

      网友评论

          本文标题:@babel/preset-env和@babel/plugin-

          本文链接:https://www.haomeiwen.com/subject/jgfewrtx.html