前些天使用了 babel7
,特來作個筆記。原文發佈在GitHub。javascript
在 babel7
中,已經廢棄了以前的階段性提案,如今統一使用 @babel/preset-env
。因此呢,這裏卻是省去了一些麻煩。在 webpack
配置中 preset-env
配合 babel-loader
就能夠轉換 ES2015+
語法了。同時,官方建議咱們使用 targets
設定目標瀏覽器決定須要兼容的功能。舉個例子:java
module.exports = { presets: [ [ '@babel/preset-env', { targets: { ie: "11" } } ] ] }
polyfill
在以前都是用來引入新的 api
和功能的。如咱們經常使用的 promise
,Object.assign
等。在 babel6
及以前,只須要在入口引入 polyfill
便可。然而這也帶來了問題,一次性加載了整個 polyfill
,十分冗餘。 而用了 babel7
經過簡單的配置就能夠達成按需加載的目的,咱們也再也不須要手動引入 polyfill
。node
沒錯,使用這個新的配置項,就能夠實現按需加載 polyfill
。其值可取如下3個:webpack
值爲 false
的時候,至關於沒用,這時就得手動引入全部的 polyfill
。git
使用 entry
的時候,也須要手動引入 polyfill
,即 import '@babel/polyfill';
,同時也引入了全部的 polyfill
。這個配置項,總以爲沒什麼用,若是有老哥知道的話能夠在評論區提出一塊兒討論。github
值爲 usage
的時候,無需引入 polyfill
,babel
會自動按需加載須要的功能:web
{ \\... useBuiltIns: 'usage' }
若是須要在命令行打印加載項,能夠設置 debug
:npm
{ \\... useBuiltIns: 'usage', dubug: true }
例如使用 class(類)
的時候,babel
會在這前面添加一個幫助函數。以下所示:
源代碼:api
// source code class Test {}
編譯後:promise
"use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Test = function Test() { _classCallCheck(this, Test); };
能夠看到,在編譯輸出的代碼裏,helper
函數被直接嵌入代碼中。若是你只有這一個 js
文件用到了這個 helper
,那這樣並無問題。但試想一下,若是你有不少個腳本文件,每個你都用到了 class
,babel
可無論你這麼多,每一個編譯後的文件都包含一個如出一轍的 helper
函數,便形成了冗餘。所幸,咱們可使用 @babel/plugin-transform-runtime
和 @babel/runtime
來解決這個問題。添加以下配置:
plugins: [ '@babel/plugin-transform-runtime' ]
此時再編譯上面的代碼,獲得的結果以下:
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var Test = function Test() { (0, _classCallCheck2.default)(this, Test); };
此時再也不是直接把 helper
函數嵌入代碼中,而是使用 require
加載公共 helper
。
polyfill
仍是 runtime
@babel/runtime
比較合適。由於 @babel/polyfill
會污染全局環境,別人引入你的庫可能會形成沒必要要的污染。@babel/runtime
不能提供一些實例方法,諸如 "foobar".includes("foo")
這類的。還需本身手動引入。對於本身的應用項目,仍是引入 @babel/polyfill
更好,提供的功能更全面,也不須要擔憂全局污染。但如我上面所說的,一些 helper
函數,若是不使用 @babel/plugin-transform-runtime
插件的話,會引入冗餘的代碼。而這二者放在一塊兒使用的時候,若是沒有對 plugin-transform-runtime
進行配置,是不會有重複功能的引入的。
上面說了這麼多,如今給出 babel7
和 webpack
的實踐做爲結束。
1.添加依賴
cnpm i --save-dev babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime // & cnpm i --save @babel/polyfill @babel/runtime
2.webpack
配置
module.exports = { // ... module: { rules: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ } ] } };
3.babel
配置
如下是在本身的應用項目中的配置:
// babel.config.js module.exports = { presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', targets: { ie: 10 // 根據本身的目標環境進行配置 }, debug: true, // corejs這一項也須要加上,corejs有2和3兩個版本 // 若是不肯定有沒有下載core-js,可執行 cnpm i core-js@2 --save corejs: 2 } ] ], plugins: [ '@babel/plugin-transform-runtime' ] };
發佈給別人使用的工具或庫,可使用如下配置:
// babel.config.js module.exports = { presets: [ '@babel/preset-env' ], plugins: [ [ '@babel/plugin-transform-runtime', { corejs: 2 // ... } ] ] };