編寫(xiě)一個(gè)簡(jiǎn)單的babel插件

編寫(xiě)一個(gè)模塊按需加載的babel插件

當(dāng)我們導(dǎo)入lodash中指定的工具函數(shù)時(shí) 會(huì)將整個(gè)lodash打包進(jìn)來(lái)

import {flattenDeep, chunk} from 'lodash'

換成按需引入的寫(xiě)法 但是這樣寫(xiě)有些麻煩 我們想由上面寫(xiě)法 自動(dòng)分解為下面寫(xiě)法 所以我們就編寫(xiě)一個(gè)babel插件

import flattenDeep from 'lodash/flattenDeep'
import chunk from 'lodash/chunk'

Install package

npm i babel-core -D
npm i babel-types -D

插件編寫(xiě)

在當(dāng)前工程的node_modules下創(chuàng)建一個(gè)babel-plugin-extract目錄 里面創(chuàng)建index.js


const babel = require('babel-core');
const types = require('babel-types');

// 將import {flattenDeep, chunk} from 'lodash' 轉(zhuǎn)化為下面這種寫(xiě)法:
// import flattenDeep from 'lodash/flattenDepp'
// import chunk from 'lodash/chunk'

// Babel將源碼轉(zhuǎn)換AST之后,通過(guò)遍歷AST樹(shù)(其實(shí)就是一個(gè)js對(duì)象),對(duì)樹(shù)做一些修改,然后再將AST轉(zhuǎn)成code,即成源碼。
let visitor = {
    // import 語(yǔ)句解析時(shí)觸發(fā)該函數(shù)
    ImportDeclaration(path, ref = {opts: {}}) {  //path 語(yǔ)句抽象語(yǔ)法樹(shù) opts 插件參數(shù)
        let node = path.node;
        let {specifiers} = node; // 導(dǎo)入的包的說(shuō)明符 是個(gè)數(shù)組集合
        // 確認(rèn)導(dǎo)入庫(kù) 是否是 .babelrc library屬性指定庫(kù) 以及 如果不是默認(rèn)導(dǎo)入 才進(jìn)行按需導(dǎo)入加載
        if (ref.opts.library === node.source.value && !types.isImportDefaultSpecifier(specifiers[0])) {
            let newImports = specifiers.map(specifier => ( // 遍歷 出導(dǎo)入的每個(gè)包的說(shuō)明描述符
                types.importDeclaration([types.importDefaultSpecifier(specifier.local)],
                // 生成import語(yǔ)句如 import chunk from 'lodash/chunk'
                types.stringLiteral(`${node.source.value}/${specifier.local.name}`))
            ));

            // 將原有語(yǔ)句寫(xiě)法替換掉 新寫(xiě)法
           path.replaceWithMultiple(newImports);
        }
    }
}

module.exports = function(babel) { // 將插件導(dǎo)出
    return {visitor} // 屬性名固定為visitor
};

配置.babelrc

{
    "presets": [
        "env",
        "stage-0"
    ],
    "plugins": [
        [
            "extract", // 配置插件
            {
                "library": "lodash" // 指定處理的庫(kù)
            }
        ]
    ]
}

build

npm run build // 此時(shí)編譯后的bundle.js變小了

源碼地址

先npm install 然后將源碼目錄中babel-plugin-extract目錄 挪到 node_modules下,npm run build
babel-plugin-extract

參考

剖析Babel
Babel 插件開(kāi)發(fā)指南
Babel 從零入門(mén)
Babel plugin
AST 抽象語(yǔ)法樹(shù)在線(xiàn)轉(zhuǎn)換
babel-types

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容