144 lines
3.9 KiB
JavaScript
144 lines
3.9 KiB
JavaScript
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;
|