• babel7-按需加载polyfill


    babel7

    babel7发布了。
    在升级到 Babel 7 时需要注意几个重大变化:

    1. 移除对 Node.js 6 之前版本的支持;
    2. 使用带有作用域的 @babel 命名空间,以防止与官方 Babel 包混淆;
    3. 移除年度预设,替换为 @babel/preset-env;
    4. 使用选择性 TC39 个别提案替换阶段提案;
    5. TC39 提议插件现在是 -proposal,而不是 -transform;
    6. 为某些面向用户的包(例如 babel-loader、@babel/cli 等)在 @babel/core 中引入peerDependency。

    官方提供了一个工具babel-upgrade,对于老项目,只需要执行:npx babel-upgrade --write --install
    具体看https://github.com/babel/babel-upgrade

    useBuiltIns:usage

    babel的polyfill总是比较大,会影响一些性能,而且也会有一些没用的polyfill,怎么减少polyfill的大小呢?
    babel7提供了useBuiltIns的按需加载:usage。
    配置中设置useBuiltIns:usage,babel就会自动把所需的polyfill加载进来,不需要手动import polyfill文件。
    配置如:

    {
        "presets": [
          "@babel/preset-react",
          ["@babel/env", {
            "targets": {
              "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
            },
            "useBuiltIns": "usage",
            "debug": true
          }]
        ],
        "plugins": ["@babel/transform-runtime"]
      }
    

    babel提供的@babel/env全面替换es2015,stage插件。(如果用到stage的某些插件需要自行引入。个人感觉stage用起来太不方便了)。
    之前的babel-preset-env/babel-preset-react全都改名为@babel/xxx,如果在babel7你还按之前的写法,会报错:
    Error: Plugin/Preset files are not allowed to export objects, only functions.

    效果

    看下useBuiltIns:usage的效果。"debug"选项开到true,可以看到打包的文件。

    我用es6摘抄了一些语法,用来测试编译:

    const a = Object.assign({}, { a: 1 });
    console.log(a);
    function timeout(ms) {
        return new Promise((resolve) => {
            setTimeout(resolve, ms);
        });
    }
    
    async function asyncPrint(value, ms) {
        await timeout(ms);
        console.log(value);
    }
    
    let s = Symbol();
    
    typeof s;
    
    class ColorPoint {
        constructor(x, y, color) {
          this.color = color;
        }
      
        toString() {
          return this.color + ' ' + super.toString(); // 调用父类的toString()
        }
      }
    
    asyncPrint('hello world', 50);
    
    function* helloWorldGenerator() {
      yield 'hello';
      yield 'world';
      return 'ending';
    }
      
    var hw = helloWorldGenerator();
    
    console.log(hw.next());
    

    babel编译之后,可以看到加载的polyfill只加载了 es6.object.assign,es6.promise, es6.symbol,es7.symbol.async-iterator , regenerator-runtime。

    babel是怎么知道我们需要哪些polyfill的?

    根据我们填的"targets",babel会去查用到的api,当前的target环境支持什么不支持什么,不支持的才加polyfill。

    可以看到我们编译后的文件已经加了polyfill。


    文件大小和性能都有很多提高。

    useBuiltIns:entry

    useBuiltIns:entry就没有那么智能了,他会根据target环境加载polyfill,他需要手动import polyfill,不能多次引入。
    @babel/preset-env会将把@babel/polyfill根据实际需求打散,只留下必须的。做的只是打散。仅引入有浏览器不支持的polyfill。这样也会提高一些性能,减少编译后的polyfill文件大小。

    main.js需要引入polyfill。import '@babel/polyfill';
    可以看到效果。我只截了部分polyfill依赖。

    编译后的文件引入了一堆polyfill。

    最佳实践

    只用polyfill不是最完美的方案。
    polyfill会额外引入一些函数,比如:

    因为polyfill没有babel-runtime的helper函数,在编译async函数的时候,会引入以上的代码asyncGeneratorStep_asyncToGenerator
    如果你每个文件都用到了async,那么冗余的代码将会很大。

    babel-runtime

    最佳方案就是在用polyfill的同时,再用babel-runtime。
    babel-runtime会把asyncGeneratorStep,_asyncToGenerator等函数require进来。从而减小冗余。
    这得益于babel-runtime的helper函数。
    所以最佳的配置是polyfill+babel-runtime。
    如果用了react可以加@babel/preset-react。

    {
        "presets": [
          "@babel/preset-react",
          ["@babel/env", {
            "targets": {
              "browsers": ["last 2 versions", "ie 11"]
            },
            "useBuiltIns": "usage"
          }]
        ],
        "plugins": ["@babel/transform-runtime"]
      }
    

    可以看到,_asyncToGenerator2已被require。

  • 相关阅读:
    控件的用法ComboBox;RadionButton;Timer;DataGridView
    echo.js实现图片延迟加载,
    取消移动端a标签点击变色
    JS实现上传图片实时预览
    Myeclipse6.0安装svn插件
    警告: Parameters: Character decoding failed. Parameter skipped
    jsp到action 传递url时中文出现乱码
    java面试题
    myeclipse中hibernate出错
    java中abstract的用法
  • 原文地址:https://www.cnblogs.com/dh-dh/p/10071312.html
Copyright © 2020-2023  润新知