[JS]使用babel 转译 ES7 的 Async function(适用于浏览器)--2

本篇主旨:透过babel转译使用Async function的js档,使其可在浏览器(非Node环境)运行
上篇

阅前注意:

本篇为个人使用笔记,为供未来使用,会包含一些琐碎的设定
新手发文,还请多多包涵并给予指教
流程为个人尝试以及思考的脉络,未必是最佳化的流程

Step0 发现问题

我们回到编译过的dist/index.js档,聚焦于找不到的regeneratorRuntime
var asyncFunc = /*#__PURE__*/function () {//regeneratorRuntime在这!  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {    return regeneratorRuntime.wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function asyncFunc() {    return _ref.apply(this, arguments);  };}();

遍寻上下文,确实找不到regeneratorRuntime在哪定义,唯一合理的解释,只有regeneratorRuntime是被定义在其他地方而在这里使用。

Step1 可能的解答

我们打开官方文件,搜索一番,发现:

The @babel/polyfill module includes core-js and a custom regenerator runtime to emulate a full ES2015+ environment.

原来,babel在转译一些太新的特性时,会产生一些额外的"引用",这些引用存在于@babel/polyfill里,regeneratorRuntime便是其中之一。
这意味着,在你编译后的档案中必须包含对@babel/polyfill的引用。

Step2 开始解决

1.安装plugin

我们顺着官方文件往下看,找找该如何引入@babel/polyfill,然而我们发现:

? As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable (to polyfill ECMAScript features) and regenerator-runtime/runtime (needed to use transpiled generator functions):

官方并不推这直接引用@babel/polyfillcore-js/stable以及regenerator-runtime/runtime,因为他们太肥了,例如我们只需要regeneratorRuntime,便不需要整包引入。

对此,官方推荐:

For library/tool authors this may be too much. If you don't need the instance methods like Array.prototype.includes you can do without polluting the global scope altogether by using the transform runtime plugin instead of @babel/polyfill.

打开transform runtime plugin文件,按部就班

npm install --save-dev @babel/plugin-transform-runtimenpm install --save @babel/runtime
@babel/plugin-transform-runtime-用来在转译后的js引入Step1所说的额外引入@babel/runtime-额外引入的实体档案,也就是包含regeneratorRuntime的地方,注意安装时的参数为--save没有-dev,因为它无论是在测试或正式环境都需要被参考

2.编辑.babelrc

我们需要加入plugins设定转译时使用的plugins

{  "presets": ["@babel/env"],  //加入以下设定,转译时会使用@babel/plugin-transform-runtime  "plugins": [    [      "@babel/plugin-transform-runtime"    ]  ]}

3.执行编译

于terminal执行:

npm run trans

4.检视转译后的档案

"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var asyncFunc = /*#__PURE__*/function () {  var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {    return _regenerator["default"].wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function asyncFunc() {    return _ref.apply(this, arguments);  };}();

走到这一步,原以为留暗花明又一村,却是半路杀出程咬金,细心的人可能已经发现了下面的问题

babel转译后的引用是透过require,这意味着babel的转译是为了在CommonJS中执行,或者说,在Node环境中执行如果我们的目标是在ES5的环境中使用babel转译的档案,这意味着我们不能做任何引入,自然不能require与import

Step3 小节

为了达成最终在浏览器+ES5的环境下使用babel转译过的async function,我们必须解决以下关键问题

不使用任何引入(require/import)下使用regeneratorRuntime
或者将regeneratorRuntime这部分的程式码注入转译后的js

碍于篇幅,请待下回分解

下一篇


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章