50行代碼實(shí)現(xiàn)Webpack組件使用次數(shù)統(tǒng)計(jì)
背景
最近有個(gè)領(lǐng)導(dǎo)想讓我們搭組件庫,然后我就想知道目前項(xiàng)目中使用的三方組件庫哪些組件使用頻率最高。本來想去咨詢小伙伴,但是小伙伴太忙了,只能自己弄了。我就想能不能通過 webpack 來實(shí)現(xiàn)我的想法
效果
我們是用的 @material-ui,下面是組件使用情況

實(shí)現(xiàn)
我們知道 loader 的 source是文件的靜態(tài)字符串如下圖

最快的方案通過字符串統(tǒng)計(jì)用正則的方式一把梭,但是這樣會(huì)有問題就是如果注釋部分有的話也會(huì)被統(tǒng)計(jì)進(jìn)去就不準(zhǔn)確,所以我們可以通過 AST 的方式來實(shí)現(xiàn),關(guān)于 ast 的概念有很多大佬都講過了我就不啰嗦了
分析 AST
我這邊是通過 @babel/parser 來分析的,我們先看下面這段代碼在網(wǎng)站上的構(gòu)成
import { Box } from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';

我們可以看出路徑 program => body ,然后聲明類型是 type: ImportDeclaration,繼續(xù)看如下構(gòu)成
"source": {
"type": "StringLiteral",
"value": "@material-ui/core"
},
// 第二段
"source": {
type": "StringLiteral",
"value": "@material-ui/lab/Autocomplete"
},
我們發(fā)下這個(gè)字段里面的 value 有我們想要的包名所以第一段代碼就是
const ast = parser.parse(source, {
sourceType: 'module',
plugins: ['jsx'],
});
const getImport = 'ImportDeclaration';
const getMaterialImport = packageName || '@material-ui';
const importAst = ast.program.body.filter(
// type 節(jié)點(diǎn)類型,這里我們?nèi)ミ^濾 import 聲明類型 同時(shí)去過濾
(i) => i.type === getImport && i.source.value.includes(getMaterialImport),
);
拿到相關(guān)的 ast 數(shù)組下一步就要去拿到組件名字了, 通過觀察我們發(fā)現(xiàn) specifiers 標(biāo)識(shí)符這個(gè)字段里面有兩個(gè)字段包含組件名:imported、local

- imported 表示從導(dǎo)出模塊導(dǎo)出的變量
- local 表示導(dǎo)入后當(dāng)前模塊的變量
這里我取的 local, 因?yàn)橄旅孢@種方式并不會(huì)出現(xiàn) imported 這個(gè)字段
import Autocomplete from '@material-ui/lab/Autocomplete';
這個(gè)時(shí)候包的名字也拿到了后面就簡單了直奔主題貼完整代碼了
demo
const parser = require('@babel/parser');
const loaderUtils = require('loader-utils');
const total = {
len: 0,
components: {},
};
// 對(duì)象排序
const sortable = (obj) => Object.fromEntries(Object.entries(obj).sort(([, a], [, b]) => b - a));
module.exports = function(source) {
console.log(source, '--');
const options = loaderUtils.getOptions(this);
const { packageName = '' } = options;
const callback = this.async();
if (!packageName) return callback(null, source);
try {
// 解析成 ast
const ast = parser.parse(source, {
sourceType: 'module',
plugins: ['jsx'],
});
if (ast) {
setTimeout(() => {
const getImport = 'ImportDeclaration';
const getMaterialImport = packageName;
const importAst = ast.program.body.filter(
// type 節(jié)點(diǎn)類型,這里我們?nèi)ミ^濾 import 聲明類型 同時(shí)去過濾
(i) => i.type === getImport && i.source.value.includes(getMaterialImport),
);
total.len = total.len + importAst.length;
for (let i of importAst) {
const { specifiers = [] } = i;
for (let s of specifiers) {
if (s.local) {
const { name } = s.local;
total.components[name] = total.components[name] ? total.components[name] + 1 : 1;
}
}
}
total.components = sortable(total.components);
console.log(total, 'total');
callback(null, source);
}, 0);
} else callback(null, source);
} catch (error) {
callback(null, source);
}
};
調(diào)用 loader
{
test: /\.(jsx|)$/,
exclude: /node_modules/,
include: [appConfig.eslintEntry],
use: [
{
loader: path.resolve(__dirname, './loader/total.js'),
options: {
packageName: '@material-ui',
},
},
],
},
一個(gè)簡單的統(tǒng)計(jì)功能就完成了,當(dāng)然可能還有其他更好的方式我只是提供這個(gè)想法,歡迎大家討論
最后
做這個(gè)的意義是什么呢,比如是我們自己的組件庫上線以后可以統(tǒng)計(jì)組件引用次數(shù),并且以某個(gè)時(shí)間為維度比如說周。通過數(shù)據(jù)來分析我們組件庫下個(gè)版本的優(yōu)化方向,而且也可以做 kpi 匯報(bào)手段畢竟有數(shù)據(jù)支撐
到此這篇關(guān)于50行代碼實(shí)現(xiàn)Webpack組件使用次數(shù)統(tǒng)計(jì)的文章就介紹到這了,更多相關(guān)Webpack組件次數(shù)統(tǒng)計(jì)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript簡單實(shí)現(xiàn)鼠標(biāo)移動(dòng)切換圖片的方法
這篇文章主要介紹了JavaScript簡單實(shí)現(xiàn)鼠標(biāo)移動(dòng)切換圖片的方法,涉及JavaScript針對(duì)鼠標(biāo)事件的響應(yīng)及頁面元素的動(dòng)態(tài)變換技巧,需要的朋友可以參考下2016-02-02
?javascript數(shù)組中的findIndex方法?
這篇文章主要介紹了javascript數(shù)組中的findIndex方法,findIndex()?方法返回傳入一個(gè)測(cè)試條件函數(shù)符合條件的數(shù)組第一個(gè)元素位置,下面更多相關(guān)資料,需要的小伙伴可以參考一下2022-03-03
webpack DllPlugin xxx is not defined解決辦法
這篇文章主要介紹了webpack DllPlugin xxx is not defined解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
關(guān)于Bootstrap彈出框無法調(diào)用問題的解決辦法
這篇文章主要介紹了關(guān)于Bootstrap彈出框無法調(diào)用問題的解決辦法的相關(guān)資料,需要的朋友可以參考下2016-03-03
js實(shí)現(xiàn)按座位號(hào)抽獎(jiǎng)
本文主要介紹了js實(shí)現(xiàn)按座位號(hào)抽獎(jiǎng)的示例代碼。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-04-04
最簡單的JS實(shí)現(xiàn)json轉(zhuǎn)csv的方法
這篇文章主要介紹了最簡單的JS實(shí)現(xiàn)json轉(zhuǎn)csv的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01

