前言
基于我的上篇文章胆筒,webpack4.0 入門篇 - 構(gòu)建前端開發(fā)的基本環(huán)境冒冬,補充對babel
進(jìn)行的一次探究宦焦。上篇文章講敘到的 webpack babel
時幾乎一筆帶過博秫,所以這篇文章將進(jìn)行補充說明.
Babel 是一個讓我們能夠使用 ES 新特性的 JS 編譯工具督怜,我們可以在
webpack
中配置Babel
丘跌,以便使用 ES6袭景、ES7 標(biāo)準(zhǔn)來編寫 JS 代碼。
本文以當(dāng)前最新版本的 babel - 7.10 為例闭树, 做 babel
的配置. 相關(guān)版本號如下
{
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/plugin-proposal-decorators": "^7.1.6",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.6",
"@babel/runtime": "^7.1.5",
"babel-loader": "^8.0.4",
"webpack": "^4.26.1",
"webpack-cli": "^3.1.2"
}
}
babel-loader 和 @babel/core
建立基本的 webpack
配置文件
mkdir webpack-babel => cd webpack-babel => yarn init -y // 初始化
npm i yarn -g // 安裝了yarn可以忽略
yarn add webpack webpack-cli -D
// package.json 中添加:
"scripts": {
"start": "webpack --mode development",
"build": "webpack --mode production"
}
yarn add babel-loader @babel/core -D
-
yarn : 和
npm
幾乎一樣耸棒,本文使用yarn
安裝... - babel-loader: 轉(zhuǎn)義 js 文件代碼的 loader
- @babel/core:babel 核心庫
根目錄下添加 webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: { loader: 'babel-loader' } // options 在 .babelrc 定義
}
]
}
}
src/index.js
const func = () => {
console.log('hello webpack')
}
func()
class User {
constructor() {
console.log('new User')
}
}
const user = new User()
執(zhí)行 yarn build
后就可以打包成功,打包后的代碼是壓縮后的报辱。而 yarn start
后的代碼是未壓縮的与殃。為了使代碼可讀性高一點,我們可以在webpack.config.js
添加:
module.exports = {
//...
devtool: true
}
@babel-preset-env
打包后我們可以發(fā)現(xiàn)箭頭函數(shù)并未轉(zhuǎn)化為 ES5
語法碍现!
查閱 babel plugins 文檔幅疼,如果要轉(zhuǎn)義箭頭函數(shù),需要使用到 @babel/plugin-transform-arrow-functions
這個插件
同理轉(zhuǎn)義 class
需要使用 @babel/plugin-transform-classes
yarn add @babel/plugin-transform-arrow-functions @babel/plugin-transform-classes -D
根目錄下建立 .babelrc
文件:
{
"plugins": [
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-classes"
]
}
yarn build
之后可以看出 箭頭函數(shù)和類都被轉(zhuǎn)義了昼接。
但是假如你再使用 async await
之類的 es6
語法爽篷,你還得一個個添加,這是不實際的慢睡。
@babel-preset-env 就整合了這些語法轉(zhuǎn)義插件:
Using plugins:
transform-template-literals {}
transform-literals {}
transform-function-name {}
transform-arrow-functions {}
transform-block-scoped-functions {}
transform-classes {}
transform-object-super {}
//...
使用如下:
yarn add @babel-preset-env -D
.babelrc
{
"presets": ["@babel/preset-env"]
}
@babel/polyfill
Babel 默認(rèn)只轉(zhuǎn)換新的 JavaScript 句法(syntax)逐工,而不轉(zhuǎn)換新的 API ,比如 Iterator漂辐、Generator泪喊、Set、Maps髓涯、Proxy袒啼、Reflect、Symbol复凳、Promise 等全局對象瘤泪,以及一些定義在全局對象上的方法(比如 Object.assign)都不會轉(zhuǎn)碼。
這樣就導(dǎo)致了一些新的 API 老版瀏覽器不兼容育八。如上述所說对途,對于新的 API,你可能需要引入 @babel-polyfill
來進(jìn)行兼容
yarn add @babel-polyfill -D
修改 weboack.config.js
module.exports = {
entry: ['@babel-polyfill', './src/index.js']
}
yarn build
發(fā)現(xiàn)文件體積大了很多髓棋,因為上面的代碼表示將 @babel-polyfill
的代碼也打包進(jìn)去了实檀。
當(dāng)然這不是我們希望的惶洲,如何按需編譯呢? 我們可以這么做:
index.js
import '@babel/polyfill' // 引入
const func = () => {
console.log('hello webpack')
}
func()
class User {
constructor() {
console.log('new User')
}
}
const user = new User()
new Promise(resolve => console.log('promise'))
Array.from('foo')
還原 webpack.config.js
module.exports = {
entry: './src/index.js'
}
修改 .babelrc
{
"presets": [["@babel/preset-env", { "useBuiltIns": "usage" }]]
}
yarn build
后發(fā)現(xiàn)我們的代碼體積就變得很小了膳犹!
@babel/runtime 和 @babel/plugin-transform-runtime
-
babel-polyfill
會污染全局作用域, 如引入Array.prototype.includes
修改了 Array 的原型恬吕,除此外還有 String... -
babel-polyfill
引入新的對象:Promise
、WeakMap
等
這也不是我們希望出現(xiàn)的须床。
-
@babel/runtime
的作用:- 提取輔助函數(shù)铐料。ES6 轉(zhuǎn)碼時,babel 會需要一些輔助函數(shù)豺旬,例如 _extend钠惩。babel 默認(rèn)會將這些輔助函數(shù)內(nèi)聯(lián)到每一個 js 文件里, babel 提供了 transform-runtime 來將這些輔助函數(shù)“搬”到一個單獨的模塊
babel-runtime
中族阅,這樣做能減小項目文件的大小篓跛。 - 提供
polyfill
:不會污染全局作用域,但是不支持實例方法如 Array.includes
- 提取輔助函數(shù)铐料。ES6 轉(zhuǎn)碼時,babel 會需要一些輔助函數(shù)豺旬,例如 _extend钠惩。babel 默認(rèn)會將這些輔助函數(shù)內(nèi)聯(lián)到每一個 js 文件里, babel 提供了 transform-runtime 來將這些輔助函數(shù)“搬”到一個單獨的模塊
-
@transform-runtime
的作用:-
babel-runtime
更像是分散的polyfill
模塊坦刀,需要在各自的模塊里單獨引入愧沟,借助 transform-runtime 插件來自動化處理這一切,也就是說你不要在文件開頭 import 相關(guān)的polyfill
鲤遥,你只需使用沐寺,transform-runtime
會幫你引入。
-
yarn add @babel/runtime-corejs2
yarn add @babel/plugin-transform-runtime -D
修改 .babelrc
{
"presets": ["@babel/preset-env"],
"plugins": [["@babel/plugin-transform-runtime", { "corejs": 2 }]]
}
index.js
移除 import '@babel/polyfill'
@babel/plugin-proposal-decorators
添加裝飾器模式的支持
yarn add @babel/plugin-proposal-decorators -D
index.js
function annotation(target) {
target.annotated = true
}
@annotation
class User {
constructor() {
console.log('new User')
}
}
//...
.babelrc
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
["@babel/plugin-transform-runtime", { "corejs": 2 }]
]
}