ant按需加载改版自动化脚本

2020/9/17 1:50:48ant-design-vueframework

说明:
ant从全局引用,改造成按需引用,需要在每个页面中,单独引用具体的组件:

import Vue from 'vue'
import { Button } from 'ant-design-vue'
Vue.use(Button)

费时费力,都是重复性工作。
于是写成一个脚本,一键全局扫描替换。

let fs = require('fs')
// ant modules的目录
let antFrameworkPath = 'D:/proj/node_modules/ant-design-vue/es'
// 
let project = 'D:/proj/src/views'

// 读取ant所有组件列表
function getAnt(path) {
    let list = fs.readdirSync(path).filter(item => {
        return !/(^(_|vc-))|(\.js$)|version/.test(item)
    })
    return list
}

// 扫描项目组件中的所有vue文件
function scannerVueFile(filePath, list) {
    let pathList = fs.readdirSync(filePath).map(item => filePath + '/' + item);
    pathList.forEach(item => {
        if (fs.statSync(item).isDirectory()) {
            scannerVueFile(item, list)
        } else if (fs.statSync(item).isFile()) {
            if (/\.vue$/i.test(item)) {
                list.push(item)
            }
        }
    });
    return list
}

// 从vue文件中的template代码中识别不重复的组件名称列表
function scannerComponentInTemplate(file) {
    let componentMaps = {}
    let template = file.match(/^\s*<template[^>]*>([\s\S]+?)<\/template>[\s\r\n]*<script>/i)
    template = template ? template[1] : '';
    if (template) {
        let antComponentList = template.match(/<a-([^\s>]+)/ig)
        antComponentList = antComponentList ? antComponentList : [];
        if (antComponentList.length > 0) {
            antComponentList.forEach(item => {
                item = item.replace(/<a-/i, '')
                item = item.toLowerCase();
                if (!componentMaps[item] && vueComponentNameList.includes(item)) {
                    item = item.replace(/^(\S)/i, ($0, $1) => {
                            return $1.toUpperCase()
                        })
                        .replace(/-([\S])/i, ($0, $1) => {
                            return $1.toUpperCase()
                        })
                    componentMaps[item] = 1
                }
            })
        }
    }
    return componentMaps
}

function scannerImported(file) {
    let script = file.match(/import\s+\{([^\}]+)\} from ['"]ant-design-vue['"]/i)
    script = script ? script[1] : '';
    if (script) {
        return script.split(',').map(item => item.trim())
    }
    return []
}

function getNewFile(filePath) {
    let testFile = fs.readFileSync(filePath, { encoding: 'utf-8' })
    let needImportMap = scannerComponentInTemplate(testFile)
    let needImportMapCopy = { ...needImportMap }
    let imporedList = scannerImported(testFile)
    imporedList.forEach(item => {
        delete needImportMap[item]
    })
    let needImportList = Object.keys(needImportMap);
    let importStr = ''
    if (needImportList.length > 0) {
        // 全新引入
        let useStr = needImportList.map(item => 'Vue.use(' + item + ')\n');
        let components = needImportList.join(',\n  ');
        let newFile = '';
        // 如果已经引入了部分组件,则进行追加剩余的组件
        if (/from [\'\"]ant-design-vue[\'\"]/i.test(testFile)) {
            let reg = /import\s+\{([^\}]+)\} from [\'\"]ant-design-vue[\'\"]/i;
            newFile = testFile
                .replace(reg, ($0, $1) => {
                    let str = '';
                    if ($1) {
                        let oldComponents = $1.trim();
                        str = `import {\n  ${oldComponents},\n  ${components}\n} from 'ant-design-vue'`;
                    } else {
                        str = $0;
                    }
                    return str
                })
                .replace(/(Vue\.use\(\w+\)\n?)+/i, ($0, $1) => {
                    return $0 + '\n' + useStr.join('')
                })
        } else {
            importStr = `import {\n  ${components}\n} from 'ant-design-vue'\n`;
            importStr += useStr.join('');

            // 判断是否引入了vue
            if (!/import Vue from/.test(testFile)) {
                importStr = `import Vue from 'vue'\n` + importStr
            }
            newFile = testFile.replace(/(<\/template>\s*<script[^>]*>)/i, ($0, $1) => {
                return $0 + '\n' + importStr
            })
        }
        console.log('追加了', needImportList.length, '个组件', needImportList.join(',').trim(), filePath.match(/([^\/]+)$/)[1].trim());

        fs.writeFileSync(filePath, newFile, { encoding: 'utf-8' })
        // console.log('newFile ', newFile);
    } else {
        if (Object.keys(needImportMapCopy).length > 0 && needImportList.length === 0) {
            console.log('追加了', needImportList.length, '个组件', needImportList.join(',').trim(), filePath.match(/([^\/]+)$/)[1].trim());
            // console.log(filePath, '已经添加');
        } else if (Object.keys(needImportMapCopy).length === 0) {
            console.log('追加了', needImportList.length, '个组件', needImportList.join(',').trim(), filePath.match(/([^\/]+)$/)[1].trim());
            // console.log(filePath, '未引用组件');
        }
    }
}
let vueComponentNameList = getAnt(antFrameworkPath)
let vueList = scannerVueFile(project, []);
console.log('总共有:', vueList.length);
vueList.forEach((filePath, index) => {
    getNewFile(filePath)
})