babel外掛編寫
編寫一個模組按需載入的babel外掛
當我們匯入lodash中指定的工具函式時 會將整個lodash打包進來
import {flattenDeep, chunk} from 'lodash'
複製程式碼
換成按需引入的寫法 但是這樣寫有些麻煩 我們想由上面寫法 自動分解為下面寫法 所以我們就編寫一個babel外掛
import flattenDeep from 'lodash/flattenDeep'
import chunk from 'lodash/chunk'
複製程式碼
Install package
npm i babel-core -D
npm i babel-types -D
複製程式碼
外掛編寫
在當前工程的node_modules下建立一個babel-plugin-extract目錄 裡面建立index.js
const babel = require('babel-core');
const types = require('babel-types');
// 將import {flattenDeep, chunk} from 'lodash' 轉化為下面這種寫法:
// import flattenDeep from 'lodash/flattenDepp'
// import chunk from 'lodash/chunk'
// Babel將原始碼轉換AST之後,通過遍歷AST樹(其實就是一個js物件),對樹做一些修改,然後再將AST轉成code,即成原始碼。
let visitor = {
// import 語句解析時觸發該函式
ImportDeclaration(path, ref = {opts: {}}) { //path 語句抽象語法樹 opts 外掛引數
let node = path.node;
let {specifiers} = node; // 匯入的包的說明符 是個陣列集合
// 確認匯入庫 是否是 .babelrc library屬性指定庫 以及 如果不是預設匯入 才進行按需匯入載入
if (ref.opts.library === node.source.value && !types.isImportDefaultSpecifier(specifiers[0])) {
let newImports = specifiers.map(specifier => ( // 遍歷 出匯入的每個包的說明描述符
types.importDeclaration([types.importDefaultSpecifier(specifier.local)],
// 生成import語句如 import chunk from 'lodash/chunk'
types.stringLiteral(`${node.source.value}/${specifier.local.name}`))
));
// 將原有語句寫法替換掉 新寫法
path.replaceWithMultiple(newImports);
}
}
}
module.exports = function(babel) { // 將外掛匯出
return {visitor} // 屬性名固定為visitor(訪問者)
};
複製程式碼
配置.babelrc
{
"presets": [
"env",
"stage-0"
],
"plugins": [
[
"extract", // 配置外掛
{
"library": "lodash" // 指定處理的庫
}
]
]
}
複製程式碼
build
npm run build // 此時編譯後的bundle.js變小了
複製程式碼
原始碼地址
先npm install 然後將原始碼目錄中babel-plugin-extract目錄 挪到 node_modules下,npm run build babel-plugin-extract