const path = require('path'); const chalk = require('chalk'); const fs = require('fs-extra'); const assert = require('assert'); const globby = require('globby'); // 不知是不是有兼容问题,11.0.3就正常,最新版本 11.0.4 使用模糊匹配查找不到目录 const chokidar = require('chokidar'); const fsExtra = require('fs-extra'); const childProcess = require('child_process'); const { CLIEngine } = require('eslint'); const vueRouteGenerator = require('../vue-route-generator/lib/index'); // 0.3.3 路由生成名称是驼峰命名方式 const pluginName = 'autoRouterPlugin'; class autoRouterPlugin { constructor(options) { this.options = { importPrefix: '../views/', routerPath: '../router/routes.js', dynamicImport: true, autoTemplates: true, ...options, }; assert(options, chalk.red.bold(`${pluginName} options is required!!!`)); assert(options.pages, chalk.red.bold(`${pluginName} options.pages is required!!!`)); this.watch = null; this.cli = new CLIEngine({ fix: true, }); } /** * 格式化path添加/斜杠 * @param {*} code * @returns */ // eslint-disable-next-line class-methods-use-this toHump(code) { return code.replace(/path: '/g, "path: '/"); // return code.replace(/\(\w)_(\w)/g, (all, letter) => letter.toUpperCase()); } /** * 通过 generateRoutes加载路由 */ async loadRouter() { const pages = await globby(this.options.pages, { onlyFiles: false }); Array.isArray(pages) && pages.forEach((page) => { const pageName = path.basename(path.dirname(page)); const code = vueRouteGenerator.generateRoutes({ pages: page, importPrefix: this.options.importPrefix, dynamicImport: this.options.dynamicImport, nested: true, }); const result = this.cli.executeOnText(code).results || []; const fileContent = result[0].output || ''; const content = this.toHump(fileContent.replace(/: "((\w|-)+)\\"/gm, `: "${pageName}-$1"`)); const to = path.resolve(page, this.options.routerPath); if (fs.existsSync(to) && fs.readFileSync(to, 'utf-8').trim() === content.trim()) { return; } if (!fs.existsSync(to)) fs.ensureFileSync(to); fs.writeFileSync(to, content); }); } /** * 复制模版 * @param {String} toPath */ copyTemplate(toPath) { fsExtra.copy('./mock/templates/', toPath); this.loadRouter(); } /** * 添加文件监听事件 */ addFile() { this.loadRouter(); } /** * 添加文件目录 * @param {String} dir */ addDir(dir) { fs.readdir(dir, (err, files) => { if (!files.length && this.options.autoTemplates) { this.copyTemplate(dir); } }); } /** * 删除文件 */ rmeoveFile() { this.loadRouter(); } /** * 删除文件目录 */ removeDir() { this.loadRouter(); } /** * 注册事件监听 */ registerWatch() { if (!this.watcher) { this.watcher = chokidar.watch('./src/pages/', { ignored: /router|store|api|assets|components|css|style|styles$/g, }); this.watcher.on('addDir', (dir) => { this.addDir(dir); }); this.watcher.on('add', (e, f = {}) => { if (e.indexOf('routes.js') >= 0) return; !f.size && this.loadRouter(); }); this.watcher.on('unlinkDir', () => { this.loadRouter(); }); this.watcher.on('unlink', () => { this.loadRouter(); }); } } async apply(compiler) { const { mode = 'development' } = compiler.options; compiler.hooks.done.tap(pluginName, (compilation) => { console.log('====>> 自动路由使用中...'); this.loadRouter(compilation); // 本地运行才启动文件变化监听 mode === 'development' && this.registerWatch(); }); } } module.exports = autoRouterPlugin;