• @babel/plugin-transform-runtime


    博客:姜瑞涛的官方网站
    原文链接:https://www.jiangruitao.com/babel/transform-runtime/
    版权采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议 转载需注明原文作者、链接与版权协议

    本节主要讲@babel/plugin-transform-runtime以及@babel/runtime。

    在我们用Babel做语法转换的时候(注意,这里是单纯的做语法转换,暂时不使用polyfill补齐API),需要Babel在转换后的代码里注入一些函数才能正常工作,先看一个例子。

    github配套代码是babel13的例子。

    Babel配置文件如下,用@babel/preset-env做语法转换:

      {
        "presets": [
          "@babel/env"
        ],
        "plugins": [
          
        ]
      }
    

    转换前的代码使用了ES6的class类语法:

      class Person {
        sayname() {
          return 'name'
        }
      }
    
      var john = new Person()
      console.log(john)
    

    Babel转码后生成的代码如下:

      "use strict";
    
      function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
    
      function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
    
      function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
    
      var Person = /*#__PURE__*/function () {
        function Person() {
          _classCallCheck(this, Person);
        }
    
        _createClass(Person, [{
          key: "sayname",
          value: function sayname() {
            return 'name';
          }
        }]);
    
        return Person;
      }();
    
      var john = new Person();
      console.log(john);
    
    

    可以看到转换后的代码上面增加了好几个函数声明,这就是注入的函数,我们称之为辅助函数。@babel/preset-env在做语法转换的时候,注入了这些函数声明,以便语法转换后使用。

    但样这做存在一个问题。在我们正常的前端工程开发的时候,少则几十个js文件,多则上千个。如果每个文件里都使用了class类语法,那会导致每个转换后的文件上部都会注入这些相同的函数声明。这会导致我们用构建工具打包出来的包非常大。

    那么怎么办?一个思路就是,我们把这些函数声明都放在一个npm包里,需要使用的时候直接从这个包里引入到我们的文件里。这样即使上千个文件,也会从相同的包里引用这些函数。通过webpack这一类的构建工具打包的时候,我们只会把使用到的npm包里的函数引入一次,这样就做到了复用,减少了体积。

    @babel/runtime就是上面说的这个npm包,@babel/runtime把所有语法转换会用到的辅助函数都集成在了一起。

    我们先安装这个包:

      npm install --save @babel/runtime
      npm install --save-dev @babel/cli @babel/core  @babel/preset-env
    

    然后到node_modules目录下看一下这个包结构

    _classCallCheck, _defineProperties与 _createClass这个三个辅助函数就在图片所示的位置,我们直接引入即可。

    github配套代码是babel13a的例子。

    我们手动把辅助函数替换掉函数声明,之前文件的代码就变成如下所示:

      "use strict";
    
      var _classCallCheck = require("@babel/runtime/helpers/classCallCheck");
      var _defineProperties = require("@babel/runtime/helpers/defineProperties");
      var _createClass = require("@babel/runtime/helpers/createClass");
    
      var Person = /*#__PURE__*/function () {
        function Person() {
          _classCallCheck(this, Person);
        }
    
        _createClass(Person, [{
          key: "sayname",
          value: function sayname() {
            return 'name';
          }
        }]);
    
        return Person;
      }();
    
      var john = new Person();
      console.log(john);
    
    

    这样就解决了代码复用和最终文件体积大的问题。不过,这么多辅助函数要一个个记住并手动引入,平常人是做不到的,我也做不到。这个时候,Babel插件@babel/plugin-transform-runtime就来帮我们解决这个问题。

    @babel/plugin-transform-runtime有三大作用,其中之一就是自动移除语法转换后内联的辅助函数(inline Babel helpers),使用@babel/runtime/helpers里的辅助函数来替代。这样就减少了我们手动引入的麻烦。

    github配套代码是babel13b的例子。

    现在我们除了安装@babel/runtime包提供辅助函数模块,还要安装Babel插件@babel/plugin-transform-runtime来自动替换辅助函数:

      npm install --save @babel/runtime
      npm install --save-dev @babel/cli @babel/core  @babel/preset-env @babel/plugin-transform-runtime
    

    现在,我们的Babel配置文件如下:

      {
        "presets": [
          "@babel/env"
        ],
        "plugins": [
          "@babel/plugin-transform-runtime"
        ]
      }
    

    转换前a.js代码:

      class Person {
        sayname() {
          return 'name'
        }
      }
    
      var john = new Person()
      console.log(john)
    

    执行"npx babel a.js -o b.js"命令后,转换生成的b.js里代码如下:

      "use strict";
    
      var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
    
      var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
    
      var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
    
      var Person = /*#__PURE__*/function () {
        function Person() {
          (0, _classCallCheck2["default"])(this, Person);
        }
    
        (0, _createClass2["default"])(Person, [{
          key: "sayname",
          value: function sayname() {
            return 'name';
          }
        }]);
        return Person;
      }();
    
      var john = new Person();
      console.log(john);
    

    可以看到,它生成的代码比我们完全手动引入@babel/runtime里的辅助函数更加优雅。实际前端开发的时候,我们除了安装@babel/runtime这个包外,一定会安装@babel/plugin-transform-runtime这个Babel插件包的。

    下一节接着讲@babel/plugin-transform-runtime的使用。

    注:

    1.每个转换后的文件上部都会注入这些相同的函数声明,那为何不用webpack一类的打包工具去掉重复的函数声明,而是要单独再引一个辅助函数包?

    webpack在构建的时候,是基于模块来做去重工作的。每一个函数声明都是引用类型,在堆内存不同的空间存放,缺少唯一的地址来找到他们。所以webpack本身是做不到把每个文件的相同函数声明去重的。因此我们需要单独的辅助函数包,这样webpack打包的时候会基于模块来做去重工作。

  • 相关阅读:
    POJ1239
    HDU 2829 四边形不等式优化
    返回数字二进制的最高位位数o(n)
    矩阵快速幂 模板
    HDU4718 The LCIS on the Tree(LCT)
    HDU4010 Query on The Trees(LCT)
    HDU3487 Play With Chains(Splay)
    CF444C DZY Loves Colors
    HDU4836 The Query on the Tree(树状数组&&LCA)
    HDU4831&&4832&&4834
  • 原文地址:https://www.cnblogs.com/zhansu/p/13339745.html
Copyright © 2020-2023  润新知