編寫一個模塊按需加載的babel插件
當我們導入lodash中指定的工具函數(shù)時 會將整個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下創(chuàng)建一個babel-plugin-extract目錄 里面創(chuàng)建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 語句解析時觸發(fā)該函數(shù)
ImportDeclaration(path, ref = {opts: {}}) { //path 語句抽象語法樹 opts 插件參數(shù)
let node = path.node;
let {specifiers} = node; // 導入的包的說明符 是個數(shù)組集合
// 確認導入庫 是否是 .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
參考
剖析Babel
Babel 插件開發(fā)指南
Babel 從零入門
Babel plugin
AST 抽象語法樹在線轉換
babel-types