最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 50行代码实现组件使用次数统计

    正文概述 掘金(又在吃鱼)   2021-03-06   705

    背景

    最近有个领导想让我们搭组件库,然后我就想知道目前项目中使用的三方组件库哪些组件使用频率最高。本来想去咨询小伙伴,但是小伙伴太忙了,只能自己弄了。我就想能不能通过 webpack 来实现我的想法

    效果

    我们是用的 @material-ui,下面是组件使用情况

    50行代码实现组件使用次数统计

    实现

    我们知道 loader 的 source是文件的静态字符串如下图

    50行代码实现组件使用次数统计

    最快的方案通过字符串统计用正则的方式一把梭,但是这样会有问题就是如果注释部分有的话也会被统计进去就不准确,所以我们可以通过 AST 的方式来实现,关于 ast 的概念有很多大佬都讲过了我就不啰嗦了

    分析 AST

    我这边是通过 @babel/parser 来分析的,我们先看下面这段代码在网站上的构成

    import { Box } from '@material-ui/core';
    import Autocomplete from '@material-ui/lab/Autocomplete';
    

    50行代码实现组件使用次数统计

    我们可以看出路径 program => body ,然后声明类型是 type: ImportDeclaration,继续看如下构成

    "source": {
              "type": "StringLiteral",
              "value": "@material-ui/core"
      },
     // 第二段
      "source": {
               type": "StringLiteral",
              "value": "@material-ui/lab/Autocomplete"
     },
    

    我们发下这个字段里面的 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 节点类型,这里我们去过滤 import 声明类型 同时去过滤
        (i) => i.type === getImport && i.source.value.includes(getMaterialImport),
    );
    

    拿到相关的 ast 数组下一步就要去拿到组件名字了, 通过观察我们发现 specifiers 标识符这个字段里面有两个字段包含组件名:importedlocal

    50行代码实现组件使用次数统计

    • imported 表示从导出模块导出的变量
    • local 表示导入后当前模块的变量

    这里我取的 local, 因为下面这种方式并不会出现 imported 这个字段

    import Autocomplete from '@material-ui/lab/Autocomplete';
    

    这个时候包的名字也拿到了后面就简单了直奔主题贴完整代码了

    demo

    const parser = require('@babel/parser');
    const loaderUtils = require('loader-utils');
    const total = {
        len: 0,
        components: {},
    };
    // 对象排序
    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 节点类型,这里我们去过滤 import 声明类型 同时去过滤
                        (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);
        }
    };
    

    调用 loader

     {
        test: /\.(jsx|)$/,
        exclude: /node_modules/,
        include: [appConfig.eslintEntry],
        use: [
            {
                loader: path.resolve(__dirname, './loader/total.js'),
                options: {
                    packageName: '@material-ui',
                },
            },
        ],
    },
    

    一个简单的统计功能就完成了,当然可能还有其他更好的方式我只是提供这个想法,欢迎大家讨论

    最后

    做这个的意义是什么呢,比如是我们自己的组件库上线以后可以统计组件引用次数,并且以某个时间为维度比如说周。通过数据来分析我们组件库下个版本的优化方向,而且也可以做 kpi 汇报手段毕竟有数据支撑


    起源地下载网 » 50行代码实现组件使用次数统计

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元