編寫一個簡單的babel外掛

Brolly發表於2018-03-25

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

參考

相關文章