編寫一個分析程式碼依賴的工具(一)

laihuamin發表於2017-12-20

一個原始碼中,理不清的依賴是最煩的,讓我們繼續往下看,如何實現一個小工具,來分析依賴關係,工具的github地址,覺得可以的可以點個star,部落格的地址,喜歡的也可以點個star,謝謝。

先讓我們來看看最後的效果如何:

all-js-analysis
one-analysis

選中的情況下,會把其餘的都隱藏,顯示它引入的依賴。

怎麼實現它

編寫一個分析程式碼依賴的工具(一)
編寫一個分析程式碼依賴的工具(一)

我們先了解echart和node的fs和path模組,這是編寫的基礎。fs的幾個處理檔案的方法,path幾個處理路徑的方法,還有echart中的和絃圖,我們要整理出來的nodes節點和links依賴關係。

編寫一個分析程式碼依賴的工具(一)

編寫一個分析程式碼依賴的工具(一)

第二步,先定義一些常量,然後我們要用fs模組去讀取資料夾中的檔案的filename和pathname,我們還要判斷一個檔案是不是資料夾,如果是資料夾,我們要遞迴呼叫的個函式,繼續讀取,直到所有的都遍歷完畢。程式碼如下:

  • 定義常量
// 該檔案是這個npm包用到的常量

// 需要忽略的資料夾
module.exports.IGNORE_DIR = ['node_modules', '.git', 'dist', 'build', 'test', '.DS_Store', '.gitignore', 'package-lock.json', 'README.md'];

// 符合標準的檔案的副檔名
module.exports.INCLUDE_EXT = ['.js', '.json', '.node']
複製程式碼
  • 收集檔案的filename和pathname
var fs = require('fs');
var path = require('path');
// 引入我們定義好的常量
var extName = require('./constant.js').INCLUDE_EXT,
    ignoreFile = require('./constant.js').IGNORE_DIR,
    res = {
        filename: [],
        pathname: []
    };

function getFileName(dir, addIgnore) {
    var files = fs.readdirSync(dir),
        ignoreList = [];

    // 判斷不需要的檔案
    if(Array.prototype.isPrototypeOf(addIgnore)) {
        ignoreList = addIgnore.concat(ignoreFile);
    } else {
        ignoreList = ignoreFile;
    }

    // 收集檔名稱和所屬路徑

    files.forEach(function(item) {
        var extname = path.extname(item),
            currentPath = path.join(dir, item),
            isFile = fs.statSync(currentPath).isFile(),
            isDir = fs.statSync(currentPath).isDirectory();
        
        // 先在ignore的列表中尋找,如果找到直接return
        if (ignoreList.indexOf(item) !== -1) {
            return;
        } else {
            // 判斷他是不是我們需要的檔名
            if(isFile && extName.indexOf(extname) !== -1) {
                res.filename.push(item);
                res.pathname.push(currentPath);
            } else if (isDir) {
                // 如果是資料夾,呼叫函式繼續處理
                getFileName(currentPath);
            }
        }
    })
    return res;
}

複製程式碼

編寫一個分析程式碼依賴的工具(一)

你會發現這裡的輸出結果整理一下已經可以作為echarts的節點了。

編寫一個分析程式碼依賴的工具(一)
第三步的話,我傾向於把links這個關係整理出來,那麼我們要做的活就是用fs讀取每一個檔案,然後在用正則,將import和require的檔案整理到target中,這樣我們就得未經處理的links。那我就直接上程式碼了!!!

編寫一個分析程式碼依賴的工具(一)

var fs = require('fs'),
    path = require('path'),
    reqReg = /require\(['|"](.*?)['|"]\)/g,
    impReg = /import\s.*?['|"](.*?)['|"]/g,
    resDep = [];

function getDepend(res, dir) {
    // 根據上一個檔案res獲得的pathname陣列進行依賴收集
    res.pathname.forEach(function(item, index) {
        // 讀取檔案
        var data = fs.readFileSync(item, 'utf-8'),
            results = [];
            // 正則匹配require
        while((results = reqReg.exec(data)) !== null) {
            var link = {
                source: res.pathname[index],
                target: results[1],
                weight: 1,
                name: '依賴'
            };
            resDep.push(link);
        }
        // 正則匹配import
        while((results = impReg.exec(data)) !== null) {
            var link = {
                source: res.pathname[index],
                target: results[1],
                weight: 1,
                name: '依賴'
            };
            resDep.push(link);
        }
    });
    return resDep;
}
複製程式碼

編寫一個分析程式碼依賴的工具(一)
第四步的話,下回在講吧,要跑去要飯了

編寫一個分析程式碼依賴的工具(一)

總結

最後在死皮賴臉的推薦一下工具部落格,歡迎star,謝謝

相關文章