⾃动⽣成element依赖⽂件

        最近在优化前端⼯程的时候,想把element改成按需引⼊,但是由于项⽬组件⾮常庞⼤复杂,不确定哪些组件有被使⽤到。受到最近在看的element-theme库的影响,想试着⽤脚本去帮我们处理,最好能⾃动⽣成element.js⽂件。
实现步骤:

  • 1. 先通过 fs 和 path 中间件递归查询 src 所有 vue 和 js ⽂件,解析⽂本中的element 组件信息;
  • 2. 只提取 el-组件名 形式的⽂本,并做去重;
  • 3. 根据官⽅提供的完整组件列表匹配提取出来的组件;
  • 4. 使⽤ fs.writeFile ⽣成element.js⽂件;
  • 5. 脚本如下:

⾃动⽣成element依赖⽂件:

// 该脚本用来查找目录下所有使用过element的组件并创建js文件
const fs = require('fs');  // 引入文件系统模块
const path = require('path');  // 引入路径模块

const elementComponentsSet = new Set();  // 创建一个集合用于存储element组件

// 递归读取目录下的文件
function readDirSync(dir, callback) {
  const files = fs.readdirSync(dir);  // 读取目录下的文件
  files.forEach(file => {
    const filePath = path.join(dir, file);  // 获取文件路径
    if (fs.statSync(filePath).isDirectory()) {  // 判断是否为目录
      readDirSync(filePath, callback);  // 递归读取子目录
    } else {
      if (path.extname(file) === '.vue') {  // 判断文件扩展名是否为.vue
        const content = fs.readFileSync(filePath, 'utf8');  // 读取文件内容
        const elementComponents = content.match(/el-([a-zA-Z]+)/g);  // 使用正则表达式匹配element组件
        if (elementComponents) {
          elementComponents.forEach(component => {
            if (component.split('-')[1]) {
              callback(component.split('-')[1]);  // 调用回调函数处理组件名
            }
          });
        }
      }
    }
  });
}

// 读取目录下的文件,将使用过的element组件添加到集合中
readDirSync('./src', component => {
  elementComponentsSet.add(component);
});

const elementComponentArr = Array.from(elementComponentsSet);  // 将集合转换为数组
console.log(elementComponentArr);  // 打印element组件数组

// 创建文件,生成element注册文件
// 不区分大小写的匹配
const all_el_components = [
  'Pagination',
  'Dialog',
  'Autocomplete',
  'Dropdown',
  'DropdownMenu',
  'DropdownItem',
  'Menu',
  'Submenu',
  'MenuItem',
  'MenuItemGroup',
  'Input',
  'InputNumber',
  'Radio',
  'RadioGroup',
  'RadioButton',
  'Checkbox',
  'CheckboxButton',
  'CheckboxGroup',
  'Switch',
  'Select',
  'Option',
  'OptionGroup',
  'Button',
  'ButtonGroup',
  'Table',
  'TableColumn',
  'DatePicker',
  'TimeSelect',
  'TimePicker',
  'Popover',
  'Tooltip',
  'Breadcrumb',
  'BreadcrumbItem',
  'Form',
  'FormItem',
  'Tabs',
  'TabPane',
  'Tag',
  'Tree',
  'Alert',
  'Slider',
  'Icon',
  'Row',
  'Col',
  'Upload',
  'Progress',
  'Spinner',
  'Badge',
  'Card',
  'Rate',
  'Steps',
  'Step',
  'Carousel',
  'CarouselItem',
  'Collapse',
  'CollapseItem',
  'Cascader',
  'ColorPicker',
  'Transfer',
  'Container',
  'Header',
  'Aside',
  'Main',
  'Footer',
  'Timeline',
  'TimelineItem',
  'Link',
  'Divider',
  'Image',
  'Calendar',
  'Backtop',
  'PageHeader',
  'CascaderPanel',
  'Loading',
  'MessageBox',
  'Message',
];
let indexPath = `./src/plugins/element.js`;  // 定义文件路径
fs.writeFile(indexPath, indexPage(elementComponentArr), function (err) {  // 写入文件
  if (err) {
    return console.log('创建element文件失败', err);
  }
  console.log(`创建element.js文件成功`);
});

// 定义文件模板
function indexPage(list) {
  let string = `import Vue from 'vue';\n`;  // 引入Vue
  const match_components_set = new Set();  // 创建一个集合用于存储匹配的组件
  list.forEach(item => {
    all_el_components.forEach(value => {
      if (value.toLowerCase().indexOf(item.toLowerCase()) > -1) {  // 不区分大小写的匹配
        match_components_set.add(value);  // 将匹配的组件添加到集合中
      }
    });
  });
  const match_components = Array.from(match_components_set);  // 将集合转换为数组
  console.log(match_components);  // 打印匹配的组件数组

  // 处理一些特殊的引入
  string += `import { Loading, MessageBox, Message, Notification} from 'element-ui' // 一般都会引入的文件 \n`;
  // 处理引入
  string += `import {\n${match_components.join(',\n')} \n} from 'element-ui';\n`;
  // 处理VueUse
  match_components.forEach(value => {
    string += `Vue.use(${value});\n`;  // 使用Vue.use注册组件
  });

  // 添加其他依赖
  string += `Vue.use(Loading.directive);
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;`;

  return string;  // 返回文件模板字符串
}

生成后的文件

import Vue from 'vue';
import { Loading, MessageBox, Message, Notification } from 'element-ui'; // 一般都会引入的文件
import {
  Icon,
  Select,
  TimeSelect,
  Option,
  OptionGroup,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Form,
  FormItem,
  Input,
  InputNumber,
  Tooltip,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Container,
  Header,
  PageHeader,
  Breadcrumb,
  BreadcrumbItem,
  Main,
  TableColumn,
  Col,
  Collapse,
  CollapseItem,
  ColorPicker,
  RadioButton,
  CheckboxButton,
  Button,
  ButtonGroup,
  Row,
  Upload,
  Badge,
  Table,
  Dialog,
  Image,
  Carousel,
  CarouselItem,
  DatePicker,
  Radio,
  RadioGroup,
  Checkbox,
  CheckboxGroup,
  Pagination,
  Tree,
  Backtop,
  Transfer,
  Divider,
  Cascader,
  CascaderPanel,
  Card,
  Tabs,
  TabPane,
  Tag,
  Steps,
  Step,
  Autocomplete,
  Progress,
  Timeline,
  TimelineItem,
} from 'element-ui';
Vue.use(Icon);
Vue.use(Select);
Vue.use(TimeSelect);
Vue.use(Option);
Vue.use(OptionGroup);
Vue.use(Dropdown);
Vue.use(DropdownMenu);
Vue.use(DropdownItem);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Input);
Vue.use(InputNumber);
Vue.use(Tooltip);
Vue.use(Menu);
Vue.use(Submenu);
Vue.use(MenuItem);
Vue.use(MenuItemGroup);
Vue.use(Container);
Vue.use(Header);
Vue.use(PageHeader);
Vue.use(Breadcrumb);
Vue.use(BreadcrumbItem);
Vue.use(Main);
Vue.use(TableColumn);
Vue.use(Col);
Vue.use(Collapse);
Vue.use(CollapseItem);
Vue.use(ColorPicker);
Vue.use(RadioButton);
Vue.use(CheckboxButton);
Vue.use(Button);
Vue.use(ButtonGroup);
Vue.use(Row);
Vue.use(Upload);
Vue.use(Badge);
Vue.use(Table);
Vue.use(Dialog);
Vue.use(Image);
Vue.use(Carousel);
Vue.use(CarouselItem);
Vue.use(DatePicker);
Vue.use(Radio);
Vue.use(RadioGroup);
Vue.use(Checkbox);
Vue.use(CheckboxGroup);
Vue.use(Pagination);
Vue.use(Tree);
Vue.use(Backtop);
Vue.use(Transfer);
Vue.use(Divider);
Vue.use(Cascader);
Vue.use(CascaderPanel);
Vue.use(Card);
Vue.use(Tabs);
Vue.use(TabPane);
Vue.use(Tag);
Vue.use(Steps);
Vue.use(Step);
Vue.use(Autocomplete);
Vue.use(Progress);
Vue.use(Timeline);
Vue.use(TimelineItem);
Vue.use(Loading.directive);
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;

你可能感兴趣的:(vue.js,前端,javascript)