mirror of
https://github.com/vbenjs/vben-admin-thin-next.git
synced 2025-02-02 18:08:40 +08:00
feat: the production environment can be dynamically configured
This commit is contained in:
parent
e83cb06bb9
commit
bb3b8f817d
@ -9,3 +9,7 @@ VITE_GLOB_API_URL=/api
|
||||
|
||||
# Interface prefix
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
|
||||
# TODO use Cdn
|
||||
VITE_USE_CDN = true
|
||||
|
@ -218,6 +218,7 @@ yarn clean:lib # 删除node_modules,兼容window系统
|
||||
- [x] 图表库
|
||||
- [x] 数字动画
|
||||
- [x] 首屏加载等待动画
|
||||
- [x] 抽取生产环境配置文件
|
||||
|
||||
## 正在开发的功能
|
||||
|
||||
@ -228,7 +229,7 @@ yarn clean:lib # 删除node_modules,兼容window系统
|
||||
- [ ] 主题配置
|
||||
- [ ] 黑暗主题
|
||||
- [ ] 打包 Gzip
|
||||
- [ ] 抽取生产环境配置文件
|
||||
- [ ] 打包 CDN
|
||||
- [ ] 系统性能优化
|
||||
|
||||
更多组件/功能/建议/bug/欢迎提交 pr 或者 issue
|
||||
|
21
build/config/vite/cdn.ts
Normal file
21
build/config/vite/cdn.ts
Normal file
@ -0,0 +1,21 @@
|
||||
const css = ['//cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css'];
|
||||
|
||||
// TODO use esm?
|
||||
const js = [
|
||||
'//cdn.bootcdn.net/ajax/libs/vue/3.0.0/vue.global.prod.js',
|
||||
'//cdn.bootcdn.net/ajax/libs/vue-router/4.0.0-beta.13/vue-router.global.min.js',
|
||||
'//cdn.bootcdn.net/ajax/libs/vuex/4.0.0-beta.4/vuex.global.prod.js',
|
||||
'//cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js',
|
||||
'//cdn.bootcdn.net/ajax/libs/qs/6.9.4/qs.min.js',
|
||||
'//cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js',
|
||||
// '//cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.min.js',
|
||||
// '//cdn.bootcdn.net/ajax/libs/crypto-js/3.3.0/crypto-js.min.js',
|
||||
// '//cdn.bootcdn.net/ajax/libs/vue-i18n/8.18.1/vue-i18n.min.js',
|
||||
];
|
||||
|
||||
export const externals = ['vue', 'vuex', 'vue-router', 'axios', 'qs', 'nprogress'];
|
||||
|
||||
export const cdnConf = {
|
||||
css,
|
||||
js,
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
import moment from 'moment';
|
||||
// @ts-ignore
|
||||
import pkg from '../../../package.json';
|
||||
export function setupBasicEnv() {
|
||||
// version
|
||||
process.env.VITE_VERSION = (pkg as any).version;
|
||||
// build time
|
||||
process.env.VITE_APP_BUILD_TIME = moment().format('YYYY-MM-DD HH:mm:ss');
|
||||
process.env.VITE_BUILD_SHORT_TIME = moment().format('MMDDHHmmss');
|
||||
}
|
1
build/constant.ts
Normal file
1
build/constant.ts
Normal file
@ -0,0 +1 @@
|
||||
export const GLOB_CONFIG_FILE_NAME = '_app.config.js';
|
5
build/getShortName.ts
Normal file
5
build/getShortName.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const getShortName = (env: any) => {
|
||||
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
|
||||
.toUpperCase()
|
||||
.replace(/\s/g, '');
|
||||
};
|
36
build/jsc.js
Normal file
36
build/jsc.js
Normal file
@ -0,0 +1,36 @@
|
||||
// js调用cli 兼容调用ts
|
||||
|
||||
const { sh } = require('tasksfile');
|
||||
const { argv } = require('yargs');
|
||||
|
||||
let command = ``;
|
||||
|
||||
Object.keys(argv).forEach((key) => {
|
||||
if (!/^\$/.test(key) && key !== '_') {
|
||||
// @ts-ignore
|
||||
if (argv[key]) {
|
||||
command += `--${key} `;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 执行任务名称
|
||||
let taskList = argv._;
|
||||
|
||||
let NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
|
||||
if (taskList.includes('build') || taskList.includes('report') || taskList.includes('preview')) {
|
||||
NODE_ENV = 'production';
|
||||
}
|
||||
|
||||
if (taskList && Array.isArray(taskList) && taskList.length) {
|
||||
sh(
|
||||
`cross-env NODE_ENV=${NODE_ENV} ts-node --project ./build/tsconfig.json ./build/script/cli.ts ${taskList.join(
|
||||
' '
|
||||
)} ${command}`,
|
||||
{
|
||||
async: true,
|
||||
nopipe: true,
|
||||
}
|
||||
);
|
||||
}
|
28
build/script/build.ts
Normal file
28
build/script/build.ts
Normal file
@ -0,0 +1,28 @@
|
||||
// #!/usr/bin/env node
|
||||
|
||||
import { sh } from 'tasksfile';
|
||||
import { argv } from 'yargs';
|
||||
import { runBuildConfig } from './buildConf';
|
||||
import { runUpdateHtml } from './updateHtml';
|
||||
import { errorConsole, successConsole } from '../utils';
|
||||
|
||||
export const runBuild = async () => {
|
||||
try {
|
||||
const argvList = argv._;
|
||||
let cmd = `cross-env NODE_ENV=production vite build`;
|
||||
await sh(cmd, {
|
||||
async: true,
|
||||
nopipe: true,
|
||||
});
|
||||
|
||||
// Generate configuration file
|
||||
if (!argvList.includes('no-conf')) {
|
||||
await runBuildConfig();
|
||||
}
|
||||
await runUpdateHtml();
|
||||
successConsole('Vite Build successfully!');
|
||||
} catch (error) {
|
||||
errorConsole('Vite Build Error\n' + error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
44
build/script/buildConf.ts
Normal file
44
build/script/buildConf.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../constant';
|
||||
import fs, { writeFileSync } from 'fs-extra';
|
||||
|
||||
import viteConfig from '../../vite.config';
|
||||
import { errorConsole, successConsole, getCwdPath, getEnvConfig } from '../utils';
|
||||
|
||||
const getShortName = (env: any) => {
|
||||
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
|
||||
.toUpperCase()
|
||||
.replace(/\s/g, '');
|
||||
};
|
||||
|
||||
function createConfig(
|
||||
{
|
||||
configName,
|
||||
config,
|
||||
configFileName = GLOB_CONFIG_FILE_NAME,
|
||||
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} }
|
||||
) {
|
||||
try {
|
||||
const windowConf = `window.${configName}`;
|
||||
const outDir = viteConfig.outDir || 'dist';
|
||||
const configStr = `${windowConf}=${JSON.stringify(config)};
|
||||
|
||||
Object.freeze(${windowConf});
|
||||
Object.defineProperty(window, "${configName}", {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
`;
|
||||
fs.mkdirp(getCwdPath(outDir));
|
||||
writeFileSync(getCwdPath(`${outDir}/${configFileName}`), configStr);
|
||||
|
||||
successConsole('The configuration file is build successfully!');
|
||||
} catch (error) {
|
||||
errorConsole('Configuration file configuration file failed to package\n' + error);
|
||||
}
|
||||
}
|
||||
|
||||
export function runBuildConfig() {
|
||||
const config = getEnvConfig();
|
||||
const configFileName = getShortName(config);
|
||||
createConfig({ config, configName: configFileName });
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
// #!/usr/bin/env node
|
||||
|
||||
import { sh } from 'tasksfile';
|
||||
import chalk from 'chalk';
|
||||
import { errorConsole, successConsole } from '../utils';
|
||||
|
||||
const createChangeLog = async () => {
|
||||
export const runChangeLog = async () => {
|
||||
try {
|
||||
let cmd = `conventional-changelog -p custom-config -i CHANGELOG.md -s -r 0 `;
|
||||
// if (shell.which('git')) {
|
||||
// cmd += '&& git add CHANGELOG.md';
|
||||
// }
|
||||
await sh(cmd, {
|
||||
async: true,
|
||||
nopipe: true,
|
||||
@ -18,21 +15,10 @@ const createChangeLog = async () => {
|
||||
async: true,
|
||||
nopipe: true,
|
||||
});
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.green.bold('CHANGE_LOG generated successfully!') +
|
||||
chalk.blue.bold(' ****************')
|
||||
);
|
||||
successConsole('CHANGE_LOG.md generated successfully!');
|
||||
} catch (error) {
|
||||
console.log(
|
||||
chalk.blue.red('**************** ') +
|
||||
chalk.green.red('CHANGE_LOG generated error\n' + error) +
|
||||
chalk.blue.red(' ****************')
|
||||
);
|
||||
errorConsole('CHANGE_LOG.md generated error\n' + error);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
createChangeLog();
|
||||
module.exports = {
|
||||
createChangeLog,
|
||||
};
|
||||
|
45
build/script/cli.ts
Normal file
45
build/script/cli.ts
Normal file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { argv } from 'yargs';
|
||||
|
||||
import { runChangeLog } from './changelog';
|
||||
import { runPostInstall } from './postinstall';
|
||||
import { runPreview } from './preview';
|
||||
import { runPreserve } from './preserve';
|
||||
import { runBuild } from './build';
|
||||
|
||||
const task = (argv._ || [])[0];
|
||||
|
||||
console.log('Run Task: ' + chalk.cyan(task));
|
||||
|
||||
switch (task) {
|
||||
// change log
|
||||
case 'log':
|
||||
runChangeLog();
|
||||
break;
|
||||
|
||||
case 'build':
|
||||
runBuild();
|
||||
break;
|
||||
|
||||
case 'preserve':
|
||||
runPreserve();
|
||||
break;
|
||||
|
||||
case 'postinstall':
|
||||
runPostInstall();
|
||||
break;
|
||||
|
||||
case 'preview':
|
||||
runPreview();
|
||||
break;
|
||||
|
||||
// TODO
|
||||
case 'gzip':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
export default {};
|
12
build/script/hm.ts
Normal file
12
build/script/hm.ts
Normal file
@ -0,0 +1,12 @@
|
||||
// 百度统计代码 用于站点部署
|
||||
// 只在build:site开启
|
||||
export const hmScript = `<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?384d6046e02f6ac4ea075357bd0e9b43";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
`;
|
@ -2,9 +2,14 @@ import { exec, which } from 'shelljs';
|
||||
|
||||
function ignoreCaseGit() {
|
||||
try {
|
||||
if (which('git')) {
|
||||
if (which('git').code === 0) {
|
||||
exec('git config core.ignorecase false ');
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
export function runPostInstall() {
|
||||
ignoreCaseGit();
|
||||
}
|
||||
ignoreCaseGit();
|
||||
|
@ -1,53 +1,57 @@
|
||||
// 是否需要更新依赖,防止package.json更新了依赖,其他人获取代码后没有install
|
||||
// Do you need to update the dependencies to prevent package.json from updating the dependencies, and no install after others get the code
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { isEqual } from 'lodash';
|
||||
import chalk from 'chalk';
|
||||
import { sh } from 'tasksfile';
|
||||
import { successConsole, errorConsole } from '../utils';
|
||||
|
||||
const resolve = (dir: string) => {
|
||||
return path.resolve(process.cwd(), dir);
|
||||
};
|
||||
|
||||
const reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/;
|
||||
|
||||
let NEED_INSTALL = false;
|
||||
|
||||
fs.mkdirp(resolve('build/.cache'));
|
||||
function checkPkgUpdate() {
|
||||
const pkg = require('../../package.json');
|
||||
const { dependencies, devDependencies } = pkg;
|
||||
const depsFile = resolve('build/.cache/deps.json');
|
||||
if (!fs.pathExistsSync(depsFile)) {
|
||||
NEED_INSTALL = true;
|
||||
return;
|
||||
export async function runPreserve() {
|
||||
const cwdPath = process.cwd();
|
||||
if (reg.test(cwdPath)) {
|
||||
errorConsole(
|
||||
'Do not include Chinese, Japanese or Korean in the full path of the project directory, please modify the directory name and run again!'
|
||||
);
|
||||
errorConsole('项目目录全路径请勿包含中文、日文、韩文,请修改目录名后再次重新运行!');
|
||||
process.exit(1);
|
||||
}
|
||||
const depsJson = require('../.cache/deps.json');
|
||||
|
||||
if (!isEqual(depsJson, { dependencies, devDependencies })) {
|
||||
NEED_INSTALL = true;
|
||||
fs.mkdirp(resolve('build/.cache'));
|
||||
function checkPkgUpdate() {
|
||||
const pkg = require('../../package.json');
|
||||
const { dependencies, devDependencies } = pkg;
|
||||
const depsFile = resolve('build/.cache/deps.json');
|
||||
if (!fs.pathExistsSync(depsFile)) {
|
||||
NEED_INSTALL = true;
|
||||
return;
|
||||
}
|
||||
const depsJson = require('../.cache/deps.json');
|
||||
|
||||
if (!isEqual(depsJson, { dependencies, devDependencies })) {
|
||||
NEED_INSTALL = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkPkgUpdate();
|
||||
|
||||
(async () => {
|
||||
checkPkgUpdate();
|
||||
if (NEED_INSTALL) {
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.red.bold('检测到依赖变化,正在安装依赖(Tip: 项目首次运行也会执行)!') +
|
||||
chalk.blue.bold(' ****************')
|
||||
// no error
|
||||
successConsole(
|
||||
'A dependency change is detected, and the dependency is being installed to ensure that the dependency is consistent! (Tip: The project will be executed for the first time)!'
|
||||
);
|
||||
try {
|
||||
// 从代码执行貌似不会自动读取.npmrc 所以手动加上源地址
|
||||
// await run('yarn install --registry=https://registry.npm.taobao.org ', {
|
||||
await sh('yarn install ', {
|
||||
await sh('npm run bootstrap ', {
|
||||
async: true,
|
||||
nopipe: true,
|
||||
});
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.green.bold('依赖安装成功,正在运行!') +
|
||||
chalk.blue.bold(' ****************')
|
||||
);
|
||||
|
||||
successConsole('Dependency installation is successful, start running the project!');
|
||||
|
||||
const pkg = require('../../package.json');
|
||||
const { dependencies, devDependencies } = pkg;
|
||||
@ -64,4 +68,4 @@ checkPkgUpdate();
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import { getIPAddress } from '../utils';
|
||||
const BUILD = 1;
|
||||
const NO_BUILD = 2;
|
||||
|
||||
// 启动服务器
|
||||
// start server
|
||||
const startApp = () => {
|
||||
const port = 9680;
|
||||
portfinder.basePort = port;
|
||||
@ -23,7 +23,6 @@ const startApp = () => {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
// const publicPath = process.env.BASE_URL;
|
||||
app.listen(port, function () {
|
||||
const empty = ' ';
|
||||
const common = `The preview program is already running:
|
||||
@ -36,7 +35,7 @@ const startApp = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const preview = async () => {
|
||||
export const runPreview = async () => {
|
||||
const prompt = inquirer.prompt({
|
||||
type: 'list',
|
||||
message: 'Please select a preview method',
|
||||
@ -61,7 +60,3 @@ const preview = async () => {
|
||||
}
|
||||
startApp();
|
||||
};
|
||||
|
||||
(() => {
|
||||
preview();
|
||||
})();
|
||||
|
98
build/script/updateHtml.ts
Normal file
98
build/script/updateHtml.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { readFileSync, writeFileSync, existsSync } from 'fs-extra';
|
||||
import viteConfig, { htmlConfig } from '../../vite.config';
|
||||
import { getCwdPath, successConsole, errorConsole } from '../utils';
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../constant';
|
||||
import { hmScript } from './hm';
|
||||
const pkg = require('../../package.json');
|
||||
|
||||
const { title, addHm, cdnConf, useCdn } = htmlConfig;
|
||||
|
||||
function injectTitle(html: string, htmlTitle: string) {
|
||||
if (/<\/title>/.test(html)) {
|
||||
return html.replace(/<\/title>/, `${htmlTitle}</title>`);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function injectConfigScript(html: string) {
|
||||
const tag = `\t\t<script src='${viteConfig.base || './'}${GLOB_CONFIG_FILE_NAME}?v=${
|
||||
pkg.version
|
||||
}-${new Date().getTime()}'></script>`;
|
||||
|
||||
if (/<\/head>/.test(html)) {
|
||||
return html.replace(/<\/head>/, `${tag}\n\t\t</head>`);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function injectHmScript(html: string) {
|
||||
if (/<head>/.test(html)) {
|
||||
return html.replace(/<head>/, `<head>\n${hmScript}`);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function injectCdnCss(html: string) {
|
||||
if (!cdnConf) return html;
|
||||
const { css } = cdnConf;
|
||||
if (!css || css.length === 0) return html;
|
||||
|
||||
let cdnCssTag = '';
|
||||
for (const cssLink of css) {
|
||||
cdnCssTag += `<link rel="stylesheet" href="${cssLink}">`;
|
||||
}
|
||||
if (/<\/head>/.test(html)) {
|
||||
return html.replace(/<\/head>/, `${cdnCssTag}\n\t\t</head>`);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function injectCdnjs(html: string) {
|
||||
if (!cdnConf) return html;
|
||||
const { js } = cdnConf;
|
||||
if (!js || js.length === 0) return html;
|
||||
|
||||
let cdnJsTag = '';
|
||||
for (const src of js) {
|
||||
// TODO
|
||||
// <script type="importmap">
|
||||
// { "imports": {
|
||||
// "vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.esm-browser.js",
|
||||
// "vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.0-alpha.13/vue-router.esm.js",
|
||||
// "vuex": "https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.0-beta.2/vuex.esm-browser.js"
|
||||
// } }
|
||||
// </script>
|
||||
cdnJsTag += `\t<script type="text/javascript" src="${src}"></script>\n`;
|
||||
}
|
||||
if (/<\/body>/.test(html)) {
|
||||
return html.replace(/<\/body>/, `${cdnJsTag}\n</body>`);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
export async function runUpdateHtml() {
|
||||
const outDir = viteConfig.outDir || 'dist';
|
||||
const indexPath = getCwdPath(outDir, 'index.html');
|
||||
if (!existsSync(`${indexPath}`)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let processedHtml = '';
|
||||
const rawHtml = readFileSync(indexPath, 'utf-8');
|
||||
processedHtml = rawHtml;
|
||||
processedHtml = injectTitle(processedHtml, title);
|
||||
processedHtml = injectConfigScript(processedHtml);
|
||||
if (addHm) {
|
||||
processedHtml = injectHmScript(processedHtml);
|
||||
}
|
||||
if (useCdn) {
|
||||
processedHtml = injectCdnCss(processedHtml);
|
||||
processedHtml = injectCdnjs(processedHtml);
|
||||
}
|
||||
|
||||
writeFileSync(indexPath, processedHtml);
|
||||
successConsole('Update Html Successfully!');
|
||||
} catch (error) {
|
||||
errorConsole('Update Html Error\n' + error);
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { networkInterfaces } from 'os';
|
||||
import dotenv from 'dotenv';
|
||||
import chalk from 'chalk';
|
||||
|
||||
export const isFunction = (arg: unknown): arg is (...args: any[]) => any =>
|
||||
typeof arg === 'function';
|
||||
export const isRegExp = (arg: unknown): arg is RegExp =>
|
||||
@ -72,6 +75,8 @@ export interface ViteEnv {
|
||||
VITE_USE_MOCK: boolean;
|
||||
VITE_PUBLIC_PATH: string;
|
||||
VITE_PROXY: [string, string][];
|
||||
VITE_GLOB_APP_TITLE: string;
|
||||
VITE_USE_CDN: boolean;
|
||||
}
|
||||
|
||||
export function loadEnv(): ViteEnv {
|
||||
@ -100,3 +105,49 @@ export function loadEnv(): ViteEnv {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = ['.env', '.env.production']) {
|
||||
let envConfig = {};
|
||||
confFiles.forEach((item) => {
|
||||
try {
|
||||
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
|
||||
|
||||
envConfig = { ...envConfig, ...env };
|
||||
} catch (error) {}
|
||||
});
|
||||
Object.keys(envConfig).forEach((key) => {
|
||||
const reg = new RegExp(`^(${match})`);
|
||||
if (!reg.test(key)) {
|
||||
Reflect.deleteProperty(envConfig, key);
|
||||
}
|
||||
});
|
||||
return envConfig;
|
||||
}
|
||||
|
||||
export function successConsole(message: any) {
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.green.bold('✨ ' + message) +
|
||||
chalk.blue.bold(' ****************')
|
||||
);
|
||||
}
|
||||
|
||||
export function errorConsole(message: any) {
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.red.bold('✨ ' + message) +
|
||||
chalk.blue.bold(' ****************')
|
||||
);
|
||||
}
|
||||
|
||||
export function warnConsole(message: any) {
|
||||
console.log(
|
||||
chalk.blue.bold('**************** ') +
|
||||
chalk.yellow.bold('✨ ' + message) +
|
||||
chalk.blue.bold(' ****************')
|
||||
);
|
||||
}
|
||||
|
||||
export function getCwdPath(...dir: string[]) {
|
||||
return path.resolve(process.cwd(), ...dir);
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
import type { GlobEnvConfig } from './src/types/config';
|
||||
|
||||
export const getGlobEnvConfig = (): GlobEnvConfig => {
|
||||
const env = import.meta.env;
|
||||
return (env as unknown) as GlobEnvConfig;
|
||||
};
|
11
index.html
11
index.html
@ -2,9 +2,14 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vue Vben admin 2.0</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
@ -43,7 +48,7 @@
|
||||
.app-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0, 3);
|
||||
background: rgba(255, 255, 255, 0, 1);
|
||||
}
|
||||
|
||||
.app-loading .app-loading-wrap {
|
||||
|
27
package.json
27
package.json
@ -3,21 +3,22 @@
|
||||
"version": "2.0.0-beta.6",
|
||||
"scripts": {
|
||||
"bootstrap": "yarn install",
|
||||
"serve": "ts-node --project ./build/tsconfig.json ./build/script/preserve && cross-env NODE_ENV=development vite",
|
||||
"build": "cross-env NODE_ENV=production vite build ",
|
||||
"report": "cross-env REPORT=true yarn build ",
|
||||
"build:no-cache": "yarn clean:cache && yarn build",
|
||||
"preview": "ts-node --project ./build/tsconfig.json ./build/script/preview",
|
||||
"log": "ts-node --project ./build/tsconfig.json ./build/script/changelog",
|
||||
"gen:gz": "ts-node --project build/tsconfig.build.json ./build/gzip/index.ts ",
|
||||
"clean:cache": "npx rimraf node_modules/.cache/ && npx rimraf node_modules/.vite_opt_cache",
|
||||
"serve": "node ./build/jsc.js preserve && cross-env NODE_ENV=development vite",
|
||||
"build": "node ./build/jsc.js build",
|
||||
"build:site": "cross-env SITE=true npm run build ",
|
||||
"build:no-cache": "yarn clean:cache && npm run build",
|
||||
"report": "cross-env REPORT=true npm run build ",
|
||||
"preview": "node ./build/jsc.js preview",
|
||||
"log": "node ./build/jsc.js log",
|
||||
"gen:gz": "node ./build/jsc.js gzip",
|
||||
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite_opt_cache",
|
||||
"clean:lib": "npx rimraf node_modules",
|
||||
"ls-lint": "npx ls-lint",
|
||||
"lint:eslint": "eslint --fix --ext \"src/**/*.{vue,less,css,scss}\"",
|
||||
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"reinstall": "npx rimraf node_modules && npx rimraf yarn.lock && npx rimraf package.lock.json && yarn run bootstrap",
|
||||
"postinstall": "ts-node --project ./build/tsconfig.json ./build/script/postinstall"
|
||||
"lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"reinstall": "rimraf node_modules && rimraf yarn.lock && rimraf package.lock.json && npm run bootstrap",
|
||||
"postinstall": "node ./build/jsc.js postinstall"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^2.0.0-rc.1",
|
||||
@ -53,6 +54,7 @@
|
||||
"@types/qrcode": "^1.3.5",
|
||||
"@types/rollup-plugin-visualizer": "^2.6.0",
|
||||
"@types/shelljs": "^0.8.8",
|
||||
"@types/yargs": "^15.0.8",
|
||||
"@types/zxcvbn": "^4.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.0",
|
||||
"@typescript-eslint/parser": "^4.4.0",
|
||||
@ -90,7 +92,8 @@
|
||||
"vite": "^1.0.0-rc.4",
|
||||
"vite-plugin-mock": "^1.0.2",
|
||||
"vite-plugin-purge-icons": "^0.4.1",
|
||||
"vue-eslint-parser": "^7.1.0"
|
||||
"vue-eslint-parser": "^7.1.0",
|
||||
"yargs": "^16.0.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -283,7 +283,19 @@
|
||||
const element = values[key];
|
||||
if (fields.includes(key) && element !== undefined && element !== null) {
|
||||
// 时间
|
||||
(formModel as any)[key] = itemIsDateType(key) ? moment(element) : element;
|
||||
if (itemIsDateType(key)) {
|
||||
if (Array.isArray(element)) {
|
||||
const arr: any[] = [];
|
||||
for (const ele of element) {
|
||||
arr.push(moment(ele));
|
||||
}
|
||||
(formModel as any)[key] = arr;
|
||||
} else {
|
||||
(formModel as any)[key] = moment(element);
|
||||
}
|
||||
} else {
|
||||
(formModel as any)[key] = element;
|
||||
}
|
||||
if (formEl) {
|
||||
formEl.validateFields([key]);
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ export default defineComponent({
|
||||
: {};
|
||||
return (
|
||||
<Menu
|
||||
forceSubMenuRender={props.isAppMenu}
|
||||
// forceSubMenuRender={props.isAppMenu}
|
||||
selectedKeys={selectedKeys}
|
||||
defaultSelectedKeys={defaultSelectedKeys}
|
||||
mode={mode}
|
||||
|
@ -77,7 +77,7 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
|
||||
if (el) {
|
||||
headerHeight = (el as HTMLElement).offsetHeight;
|
||||
}
|
||||
tableHeightRef.value =
|
||||
const tHeight =
|
||||
bottomIncludeBody -
|
||||
(resizeHeightOffset || 0) -
|
||||
paddingHeight -
|
||||
@ -86,8 +86,7 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
|
||||
footerHeight -
|
||||
headerHeight;
|
||||
useTimeout(() => {
|
||||
tableHeightRef.value =
|
||||
tableHeightRef.value! > maxHeight! ? (maxHeight as number) : tableHeightRef.value;
|
||||
tableHeightRef.value = tHeight > maxHeight! ? (maxHeight as number) : tableHeightRef.value;
|
||||
cb && cb();
|
||||
}, 0);
|
||||
}
|
||||
|
@ -1,14 +1,20 @@
|
||||
import type { ProjectConfig, GlobConfig, SettingWrap } from '/@/types/config';
|
||||
import type { ProjectConfig, GlobConfig, SettingWrap, GlobEnvConfig } from '/@/types/config';
|
||||
|
||||
import getProjectSetting from '/@/settings/projectSetting';
|
||||
|
||||
import { getGlobEnvConfig } from '../../../getEnvConfig';
|
||||
import { getGlobEnvConfig, isDevMode } from '/@/utils/env';
|
||||
import { getShortName } from '../../../build/getShortName';
|
||||
|
||||
const ENV_NAME = getShortName(import.meta.env);
|
||||
const ENV = ((isDevMode()
|
||||
? getGlobEnvConfig()
|
||||
: window[ENV_NAME as any]) as unknown) as GlobEnvConfig;
|
||||
const {
|
||||
VITE_GLOB_APP_TITLE,
|
||||
VITE_GLOB_API_URL,
|
||||
VITE_GLOB_APP_SHORT_NAME,
|
||||
VITE_GLOB_APP_TITLE,
|
||||
VITE_GLOB_API_URL_PREFIX,
|
||||
} = getGlobEnvConfig();
|
||||
} = ENV;
|
||||
|
||||
export const useSetting = (): SettingWrap => {
|
||||
// Take global configuration
|
||||
@ -19,7 +25,9 @@ export const useSetting = (): SettingWrap => {
|
||||
urlPrefix: VITE_GLOB_API_URL_PREFIX,
|
||||
};
|
||||
const projectSetting: Readonly<ProjectConfig> = getProjectSetting;
|
||||
|
||||
console.log('======================');
|
||||
console.log(glob);
|
||||
console.log('======================');
|
||||
return {
|
||||
globSetting: glob as Readonly<GlobConfig>,
|
||||
projectSetting,
|
||||
|
@ -59,19 +59,17 @@ export function useECharts(
|
||||
|
||||
function resize() {
|
||||
const chartInstance = unref(chartInstanceRef);
|
||||
if (!chartInstance) {
|
||||
return;
|
||||
}
|
||||
if (!chartInstance) return;
|
||||
chartInstance.resize();
|
||||
}
|
||||
|
||||
tryOnUnmounted(() => {
|
||||
const chartInstance = unref(chartInstanceRef);
|
||||
if (!chartInstance) {
|
||||
return;
|
||||
}
|
||||
if (!chartInstance) return;
|
||||
chartInstance.dispose();
|
||||
chartInstanceRef.value = null;
|
||||
});
|
||||
|
||||
return {
|
||||
setOptions,
|
||||
echarts,
|
||||
|
@ -1,3 +1,10 @@
|
||||
import type { GlobEnvConfig } from '/@/types/config';
|
||||
|
||||
export const getGlobEnvConfig = (): GlobEnvConfig => {
|
||||
const env = import.meta.env;
|
||||
return (env as unknown) as GlobEnvConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 开发模式
|
||||
*/
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { isDevMode, getEnv } from '/@/utils/env';
|
||||
import { useSetting } from '/@/hooks/core/useSetting';
|
||||
|
||||
import moment from 'moment';
|
||||
import pkg from '../../../package.json';
|
||||
const { globSetting } = useSetting();
|
||||
|
||||
// Generate cache key according to version
|
||||
export const getStorageShortName = () => {
|
||||
const shortTime = moment().format('MMDDHHmmss');
|
||||
return `${globSetting.shortName}__${getEnv()}${
|
||||
isDevMode() ? `__${(pkg as any).version}` : '__' + process.env.VITE_BUILD_SHORT_TIME
|
||||
`__${pkg.version}` + (isDevMode() ? '' : `__${shortTime}`)
|
||||
}__`.toUpperCase();
|
||||
};
|
||||
|
@ -4,14 +4,26 @@ import type { UserConfig, Plugin as VitePlugin } from 'vite';
|
||||
|
||||
import visualizer from 'rollup-plugin-visualizer';
|
||||
import { modifyVars } from './build/config/glob/lessModifyVars';
|
||||
import { setupBasicEnv } from './build/config/vite/env';
|
||||
import {
|
||||
// externals,
|
||||
cdnConf,
|
||||
} from './build/config/vite/cdn';
|
||||
|
||||
import { createProxy } from './build/config/vite/proxy';
|
||||
import { createMockServer } from 'vite-plugin-mock';
|
||||
import PurgeIcons from 'vite-plugin-purge-icons';
|
||||
import { isDevFn, isReportMode, isProdFn, loadEnv } from './build/utils';
|
||||
|
||||
setupBasicEnv();
|
||||
const { VITE_USE_MOCK, VITE_PORT, VITE_PUBLIC_PATH, VITE_PROXY } = loadEnv();
|
||||
import { isDevFn, isReportMode, isProdFn, loadEnv } from './build/utils';
|
||||
const pkg = require('./package.json');
|
||||
|
||||
const {
|
||||
VITE_USE_MOCK,
|
||||
VITE_PORT,
|
||||
VITE_PUBLIC_PATH,
|
||||
VITE_PROXY,
|
||||
VITE_GLOB_APP_TITLE,
|
||||
// VITE_USE_CDN,
|
||||
} = loadEnv();
|
||||
|
||||
function pathResolve(dir: string) {
|
||||
return resolve(__dirname, '.', dir);
|
||||
@ -95,9 +107,9 @@ const viteConfig: UserConfig = {
|
||||
alias: {
|
||||
'/@/': pathResolve('src'),
|
||||
},
|
||||
// define: {
|
||||
// __ENV__: 'value',
|
||||
// },
|
||||
define: {
|
||||
__VERSION__: pkg.version,
|
||||
},
|
||||
// css预处理
|
||||
cssPreprocessOptions: {
|
||||
less: {
|
||||
@ -122,8 +134,35 @@ const viteConfig: UserConfig = {
|
||||
plugins: [PurgeIcons(), ...vitePlugins],
|
||||
rollupOutputOptions: {},
|
||||
rollupInputOptions: {
|
||||
// TODO
|
||||
// external: VITE_USE_CDN ? externals : [],
|
||||
plugins: rollupPlugins,
|
||||
},
|
||||
};
|
||||
|
||||
// 用于打包部署站点使用。实际项目可以删除
|
||||
const isSite = process.env.SITE === 'true';
|
||||
// 扩展配置, 往打包后的html注入内容
|
||||
// 只针对生产环境
|
||||
// TODO 目前只是简单手动注入实现,后续vite应该会提供配置项
|
||||
export const htmlConfig: {
|
||||
title: string;
|
||||
addHm?: boolean;
|
||||
cdnConf?: {
|
||||
css?: string[];
|
||||
js?: string[];
|
||||
};
|
||||
useCdn: boolean;
|
||||
} = {
|
||||
// html title
|
||||
title: VITE_GLOB_APP_TITLE,
|
||||
// 百度统计,不需要可以删除
|
||||
addHm: isSite,
|
||||
// 使用cdn打包
|
||||
// TODO Cdn esm使用方式需要只能支持google,暂时关闭,后续查询更好的方式
|
||||
useCdn: false,
|
||||
// useCdn: VITE_USE_CDN,
|
||||
// cdn列表
|
||||
cdnConf,
|
||||
};
|
||||
export default viteConfig;
|
||||
|
57
yarn.lock
57
yarn.lock
@ -801,6 +801,18 @@
|
||||
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
|
||||
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "15.0.0"
|
||||
resolved "https://registry.npm.taobao.org/@types/yargs-parser/download/@types/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
|
||||
integrity sha1-yz+fdBhp4gzOMw/765JxWQSDiC0=
|
||||
|
||||
"@types/yargs@^15.0.8":
|
||||
version "15.0.8"
|
||||
resolved "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-15.0.8.tgz?cache=0&sync_timestamp=1602182032636&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.8.tgz#7644904cad7427eb704331ea9bf1ee5499b82e23"
|
||||
integrity sha1-dkSQTK10J+twQzHqm/HuVJm4LiM=
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@types/zrender@*":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/@types/zrender/-/zrender-4.0.0.tgz#a6806f12ec4eccaaebd9b0d816f049aca6188fbd"
|
||||
@ -1634,6 +1646,15 @@ cliui@^6.0.0:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
cliui@^7.0.0:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.npm.taobao.org/cliui/download/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3"
|
||||
integrity sha1-pMtnqtRc2D2NBRKPyfTY+7iH5rM=
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clone-regexp@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
|
||||
@ -2406,7 +2427,7 @@ esbuild@^0.7.1:
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.7.14.tgz#9de555e75669187c2315317fbf489b229b1a4cbb"
|
||||
integrity sha512-w2CEVeRcUhCGYMHnNNwb8q+9w42scL7RcNzJm85gZVzNBE3AF0sLq5YP/IdaTBJIFBphIKG3bGbwRH+zsgH/ig==
|
||||
|
||||
escalade@^3.1.0:
|
||||
escalade@^3.0.2, escalade@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e"
|
||||
integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==
|
||||
@ -2912,7 +2933,7 @@ gensync@^1.0.0-beta.1:
|
||||
resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
|
||||
integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
|
||||
|
||||
get-caller-file@^2.0.1:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -7004,6 +7025,15 @@ wrap-ansi@^6.2.0:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-7.0.0.tgz?cache=0&sync_timestamp=1587574502741&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwrap-ansi%2Fdownload%2Fwrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
@ -7041,6 +7071,11 @@ y18n@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
|
||||
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
|
||||
|
||||
y18n@^5.0.1:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.npm.taobao.org/y18n/download/y18n-5.0.2.tgz?cache=0&sync_timestamp=1601576683926&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fy18n%2Fdownload%2Fy18n-5.0.2.tgz#48218df5da2731b4403115c39a1af709c873f829"
|
||||
integrity sha1-SCGN9donMbRAMRXDmhr3Cchz+Ck=
|
||||
|
||||
yallist@^3.0.2:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
@ -7067,6 +7102,11 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^20.0.0:
|
||||
version "20.2.1"
|
||||
resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-20.2.1.tgz?cache=0&sync_timestamp=1601576684570&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-20.2.1.tgz#28f3773c546cdd8a69ddae68116b48a5da328e77"
|
||||
integrity sha1-KPN3PFRs3Ypp3a5oEWtIpdoyjnc=
|
||||
|
||||
yargs@^13.2.4:
|
||||
version "13.3.2"
|
||||
resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||
@ -7100,6 +7140,19 @@ yargs@^15.0.0, yargs@^15.1.0:
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^16.0.3:
|
||||
version "16.0.3"
|
||||
resolved "https://registry.npm.taobao.org/yargs/download/yargs-16.0.3.tgz?cache=0&sync_timestamp=1600660006050&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c"
|
||||
integrity sha1-epGbnkPJD4DUoUKol5XoU5mn5Uw=
|
||||
dependencies:
|
||||
cliui "^7.0.0"
|
||||
escalade "^3.0.2"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.1"
|
||||
yargs-parser "^20.0.0"
|
||||
|
||||
ylru@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f"
|
||||
|
Loading…
Reference in New Issue
Block a user