前面的章节里,我们应用 less-loader
编译过 less 文件,应用 xml-loader
编译过 xml 文件,那 js 文件需要编译吗?我们来做一个实验,修改 hello-world.js
文件:
08-babel-loader/src/hello-world.js
function getString() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello world~~~') }, 2000) }) } async function helloWorld() { let string = await getString() console.log(string) } // 导出函数模块 export default helloWorld
执行编译:
[felix] 08-babel-loader $ npx webpack
查看 bundle.js 文件:
08-babel-loader/dist/bundle.js
//... /***/ "./src/hello-world.js": /*!****************************!*\ !*** ./src/hello-world.js ***! ****************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function getString() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello world~~~') }, 2000) }) } async function helloWorld() { let string = await getString() console.log(string) } // 导出函数模块 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (helloWorld); /***/ }), //...
我们发现,编写的ES6代码原样输出了。启动服务,打开浏览器:
[felix] 08-babel-loader $ npx webpack serve
1.7.1 为什么需要 babel-loader
webpack 自身可以自动加载JS文件,就像加载JSON文件一样,无需任何 loader。可是,加载的JS文件会原样输出,即使你的JS文件里包含ES6+的代码,也不会做任何的转化。这时我们就需要Babel来帮忙。Babel 是一个 JavaScript 编译器,可以将ES6+转化成ES5。在Webpack里使用Babel,需要使用 babel-loader
。
1.7.2 使用 babel-loader
安装:
npm install -D babel-loader @babel/core @babel/preset-env
-
babel-loader
: 在webpack里应用 babel 解析ES6的桥梁 -
@babel/core
: babel核心模块 -
@babel/preset-env
: babel预设,一组 babel 插件的集合
在 webpack 配置中,需要将babel-loader
添加到module
列表中,就像下面这样:
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
执行编译:
[felix] 08-babel-loader $ npx webpack
查看 bundle.js 文件:
08-babel-loader/dist/bundle.js
/***/ "./src/hello-world.js": /*!****************************!*\ !*** ./src/hello-world.js ***! ****************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function getString() { return new Promise(function (resolve, reject) { setTimeout(function () { resolve('Hello world~~~'); }, 2000); }); } function helloWorld() { return _helloWorld.apply(this, arguments); } // 导出函数模块 function _helloWorld() { _helloWorld = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee() { var string; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return getString(); case 2: string = _context.sent; console.log(string); case 4: case "end": return _context.stop(); } } }, _callee); })); return _helloWorld.apply(this, arguments); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (helloWorld); /***/ }),
从编译完的结果可以看出,async/await
的ES6语法被 babel
编译了。
1.7.3 regeneratorRuntime 插件
此时执行编译,在浏览器里打开项目发现报了一个致命错误:
regeneratorRuntime
是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法。
regeneratorRuntime is not defined
这个错误显然是未能正确配置babel。
正确的做法需要添加以下的插件和配置:
/# 这个包中包含了regeneratorRuntime,运行时需要
npm install --save @babel/runtime
/# 这个插件会在需要regeneratorRuntime的地方自动require导包,编译时需要
npm install --save-dev @babel/plugin-transform-runtime
/# 更多参考这里
https://babeljs.io/docs/en/babel-plugin-transform-runtime
接着改一下babel的配置:
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
}
08-babel-loade/webpack.config.js
//... module.exports = { //... // 配置资源文件 module: { rules: [{ test: /.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], plugins: [ [ '@babel/plugin-transform-runtime' ] ] } } }, //... ], }, //... }
启动服务,打开浏览器: