1. 程式人生 > >寫一個模組按需載入的babel外掛 解決專案全量引入第三方資源的問題

寫一個模組按需載入的babel外掛 解決專案全量引入第三方資源的問題

babel 簡單的理解他是一個語法轉換器 

Babel 的三個主要處理步驟分別是: 解析(parse),轉換(transform),生成(generate)

Babel 專案是作為一個 monorepo 來進行管理的,它由無數 npm 包組成 其中babel-core為其核心庫

babel 解析程式碼的過程大致為

1,對輸入的原始碼字串進行解析並生成初始 抽象語法樹(AST)

2,對 AST 進行遍歷,解析出整個樹的 path,

3,遍歷 AST 樹並應用各個外掛 生成變換後的 AST 樹

4, 用 babel-generator 將 AST 輸出為轉碼後的程式碼字串

 

瞭解了這些思想後接下來我們可以參照各個 模組的文件 來開發一個我們的babel-plugin

程式碼如下

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

//Babel 的三個主要處理步驟分別是: 解析(parse),轉換(transform),生成(generate)。

const visitor = {//訪問者中 獲取抽象語法樹的 函式會在解析和轉換時分別進入一次 
    // 對import轉碼
    ImportDeclaration(path, state = {opts:{}}){
        const specifiers = path.node.specifiers;
        const source = path.node.source;
        // 只有libraryName滿足才會轉碼
        if (state.opts.libraryName == source.value && (!types.isImportDefaultSpecifier(specifiers[0])) ) { //state.opts是傳進來的引數
            var declarations = specifiers.map((specifier) => {      //遍歷 所又通過{ isEqual } 這種方式引入宣告 
                return types.ImportDeclaration(                         //建立importImportDeclaration節點
                    [types.importDefaultSpecifier(specifier.local)],
                    types.StringLiteral(`${source.value}/${specifier.local.name}`)
                )
            })
            path.replaceWithMultiple(declarations)    //轉換ast(抽象語法樹)
        }
    }

};
module.exports = function (babel) {
    return {
        visitor
    };
}

編寫好程式碼後 在我們的node_modules目錄下 新建一個目錄 babel-plugin-我們配置的plugin名字   安裝好我們所需要的依賴後 需要用 'browser', 'module', 'main'其中一個欄位指定我們的主入口檔案   

{
  "name": "babel-plugin-empty-import",
  "version": "0.0.1",
  "description": "",
  "main": "./lib/index.js",
  "dependencies": {},
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-types": "^6.26.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "freemenL",
  "license": "ISC",
  "_from": "
[email protected]
", "_resolved": "http://registry.npm.taobao.org/babel-plugin-empty-import/download/babel-plugin-empty-import-0.0.1.tgz" }

接下來配置我們的babel的plugin 

{
  "presets": [
    ["env", { "modules": false }],
    "react",
    "stage-0"
  ],
  plugins:[
	  ["empty-import",{
	  	"libraryName": "lodash"
	  }]
  ]
}

也可以將其上傳到npm上  方便我們以後使用