initial commit

This commit is contained in:
陈文彬
2020-09-28 20:19:10 +08:00
commit 2f6253cfb6
436 changed files with 26843 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
/**
* less global variable
*/
const primaryColor = '#018ffb';
//{
const modifyVars = {
'primary-color': primaryColor, // Global dominant color
'info-color': primaryColor, // Default color
'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color
'link-color': primaryColor, // Link color
'disabled-color': '#C2C2CC', // Failure color
'heading-color': '#2C3A61', // Title color
'text-color': '#2C3A61', // Main text color
'text-color-secondary ': '#606266', // Subtext color
'background-color-base': '#F0F2F5', // background color
'font-size-base': '14px', // Main font size
'box-shadow-base': '0 2px 8px rgba(0, 0, 0, 0.15)', // Floating shadow
'border-color-base': '#cececd', // Border color,
'border-color-split': '#cececd', // Border color,
'border-radius-base': '2px', // Component/float fillet
};
//}
export { modifyVars, primaryColor };

10
build/config/vite/env.ts Normal file
View File

@@ -0,0 +1,10 @@
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');
}

View File

@@ -0,0 +1,15 @@
type ProxyItem = [string, string];
type ProxyList = ProxyItem[];
export function createProxy(list: ProxyList) {
const ret: any = {};
for (const [prefix, target] of list) {
ret[prefix] = {
target: target,
changeOrigin: true,
rewrite: (path: string) => path.replace(new RegExp(`^${prefix}`), ''),
};
}
return ret;
}

22
build/gzip/index.ts Normal file
View File

@@ -0,0 +1,22 @@
// Build gzip after packaging
// import { readFile, writeFile } from 'fs';
import viteConfig from '../../vite.config';
import {
// basename,
join,
} from 'path';
// import { promisify } from 'util';
// import { gzip, ZlibOptions } from 'zlib';
import { readAllFile } from '../utils';
// const readFilePromise = promisify(readFile);
// const writeFilePromise = promisify(writeFile);
// function createGzip() {}
const FILE_REG = /\.(js|mjs|json|css|html)$/;
const OUT_DIR = viteConfig.outDir || 'dist';
// TODO 待开发
const files = readAllFile(join(process.cwd(), OUT_DIR), FILE_REG);

56
build/gzip/types.ts Normal file
View File

@@ -0,0 +1,56 @@
import type { ZlibOptions } from 'zlib';
export type StringMappingOption = (originalString: string) => string;
export type CustomCompressionOption = (
content: string | Buffer
) => string | Buffer | Promise<string | Buffer>;
export interface GzipPluginOptions {
/**
* Control which of the output files to compress
*
* Defaults to `/\.(js|mjs|json|css|html)$/`
*/
filter?: RegExp | ((fileName: string) => boolean);
/**
* GZIP compression options, see https://nodejs.org/api/zlib.html#zlib_class_options
*/
gzipOptions?: ZlibOptions;
/**
* Specified the minimum size in Bytes for a file to get compressed.
* Files that are smaller than this threshold will not be compressed.
* This does not apply to the files specified through `additionalFiles`!
*/
minSize?: number;
/**
* This option allows you to compress additional files outside of the main rollup bundling process.
* The processing is delayed to make sure the files are written on disk; the delay is controlled
* through `additionalFilesDelay`.
*/
additionalFiles?: string[];
/**
* This options sets a delay (ms) before the plugin compresses the files specified through `additionalFiles`.
* Increase this value if your artifacts take a long time to generate.
*
* Defaults to `2000`
*/
additionalFilesDelay?: number;
/**
* Set a custom compression algorithm. The function can either return the compressed contents synchronously,
* or otherwise return a promise for asynchronous processing.
*/
customCompression?: CustomCompressionOption;
/**
* Set a custom file name convention for the compressed files. Can be a suffix string or a function
* returning the file name.
*
* Defaults to `.gz`
*/
fileName?: string | StringMappingOption;
}

39
build/script/changelog.ts Normal file
View File

@@ -0,0 +1,39 @@
// #!/usr/bin/env node
import { sh } from 'tasksfile';
import chalk from 'chalk';
const createChangeLog = async () => {
try {
let cmd = `conventional-changelog -p angular -i CHANGELOG.md -s -r 0 `;
// let cmd = `conventional-changelog -p angular -i CHANGELOG.md -s -r 0 `;
// if (shell.which('git')) {
// cmd += '&& git add CHANGELOG.md';
// }
await sh(cmd, {
async: true,
nopipe: true,
});
await sh('prettier --write **/CHANGELOG.md ', {
async: true,
nopipe: true,
});
console.log(
chalk.blue.bold('**************** ') +
chalk.green.bold('CHANGE_LOG generated successfully') +
chalk.blue.bold(' ****************')
);
} catch (error) {
console.log(
chalk.blue.red('**************** ') +
chalk.green.red('CHANGE_LOG generated error\n' + error) +
chalk.blue.red(' ****************')
);
process.exit(1);
}
};
createChangeLog();
module.exports = {
createChangeLog,
};

View File

@@ -0,0 +1,10 @@
import { exec, which } from 'shelljs';
function ignoreCaseGit() {
try {
if (which('git')) {
exec('git config core.ignorecase false ');
}
} catch (error) {}
}
ignoreCaseGit();

67
build/script/preserve.ts Normal file
View File

@@ -0,0 +1,67 @@
// 是否需要更新依赖防止package.json更新了依赖其他人获取代码后没有install
import path from 'path';
import fs from 'fs-extra';
import { isEqual } from 'lodash';
import chalk from 'chalk';
import { sh } from 'tasksfile';
const resolve = (dir: string) => {
return path.resolve(process.cwd(), dir);
};
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;
}
const depsJson = require('../.cache/deps.json');
if (!isEqual(depsJson, { dependencies, devDependencies })) {
NEED_INSTALL = true;
}
}
checkPkgUpdate();
(async () => {
if (NEED_INSTALL) {
console.log(
chalk.blue.bold('**************** ') +
chalk.red.bold('检测到依赖变化,正在安装依赖(Tip: 项目首次运行也会执行)') +
chalk.blue.bold(' ****************')
);
try {
// 从代码执行貌似不会自动读取.npmrc 所以手动加上源地址
// await run('yarn install --registry=https://registry.npm.taobao.org ', {
await sh('yarn install ', {
async: true,
nopipe: true,
});
console.log(
chalk.blue.bold('**************** ') +
chalk.green.bold('依赖安装成功,正在运行!') +
chalk.blue.bold(' ****************')
);
const pkg = require('../../package.json');
const { dependencies, devDependencies } = pkg;
const depsFile = resolve('build/.cache/deps.json');
const deps = { dependencies, devDependencies };
if (!fs.pathExistsSync(depsFile)) {
fs.writeFileSync(depsFile, JSON.stringify(deps));
} else {
const depsFile = resolve('build/.cache/deps.json');
const depsJson = require('../.cache/deps.json');
if (!isEqual(depsJson, deps)) {
fs.writeFileSync(depsFile, JSON.stringify(deps));
}
}
} catch (error) {}
}
})();

70
build/script/preview.ts Normal file
View File

@@ -0,0 +1,70 @@
import chalk from 'chalk';
import Koa from 'koa';
import inquirer from 'inquirer';
import { sh } from 'tasksfile';
import staticServer from 'koa-static';
import portfinder from 'portfinder';
import { resolve } from 'path';
import viteConfig from '../../vite.config';
import { getIPAddress } from '../utils';
const BUILD = 1;
const NO_BUILD = 2;
// 启动服务器
const startApp = () => {
const port = 9680;
portfinder.basePort = port;
const app = new Koa();
// const connect = require('connect');
// const serveStatic = require('serve-static');
// const app = connect();
app.use(staticServer(resolve(process.cwd(), viteConfig.outDir || 'dist')));
portfinder.getPort(async (err, port) => {
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:
- LOCAL: http://localhost:${port}/
- NETWORK: http://${getIPAddress()}:${port}/
`;
console.log(chalk.cyan('\n' + empty + common));
});
}
});
};
const preview = async () => {
const prompt = inquirer.prompt({
type: 'list',
message: 'Please select a preview method',
name: 'type',
choices: [
{
name: 'Preview after packaging',
value: BUILD,
},
{
name: `No packaging, preview directly (need to have dist file after packaging)`,
value: NO_BUILD,
},
],
});
const { type } = await prompt;
if (type === BUILD) {
await sh('npm run build', {
async: true,
nopipe: true,
});
}
startApp();
};
(() => {
preview();
})();

18
build/tsconfig.json Normal file
View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"baseUrl": ".",
"esModuleInterop": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"experimentalDecorators": true,
"lib": ["dom", "esnext"],
"incremental": true,
"skipLibCheck": true
}
}

87
build/utils.ts Normal file
View File

@@ -0,0 +1,87 @@
import fs from 'fs';
import { networkInterfaces } from 'os';
import dotenv from 'dotenv';
export const isFunction = (arg: unknown): arg is (...args: any[]) => any =>
typeof arg === 'function';
export const isRegExp = (arg: unknown): arg is RegExp =>
Object.prototype.toString.call(arg) === '[object RegExp]';
/*
* Read all files in the specified folder, filter through regular rules, and return file path array
* @param root Specify the folder path
* [@param] reg Regular expression for filtering files, optional parameters
* Note: It can also be deformed to check whether the file path conforms to regular rules. The path can be a folder or a file. The path that does not exist is also fault-tolerant.
*/
export function readAllFile(root: string, reg: RegExp) {
let resultArr: string[] = [];
try {
if (fs.existsSync(root)) {
const stat = fs.lstatSync(root);
if (stat.isDirectory()) {
// dir
const files = fs.readdirSync(root);
files.forEach(function (file) {
const t = readAllFile(root + '/' + file, reg);
resultArr = resultArr.concat(t);
});
} else {
if (reg !== undefined) {
if (isFunction(reg.test) && reg.test(root)) {
resultArr.push(root);
}
} else {
resultArr.push(root);
}
}
}
} catch (error) {}
return resultArr;
}
export function getIPAddress() {
let interfaces = networkInterfaces();
for (let devName in interfaces) {
let iFace = interfaces[devName];
if (!iFace) return;
for (let i = 0; i < iFace.length; i++) {
let alias = iFace[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
return '';
}
export function isDevFn(): boolean {
return process.env.NODE_ENV === 'development';
}
export function isProdFn(): boolean {
return process.env.NODE_ENV === 'production';
}
export function isReportMode(): boolean {
return process.env.REPORT === 'true';
}
export function loadEnv() {
const env = process.env.NODE_ENV;
const ret: any = {};
const envList = [`.env.${env}.local`, `.env.${env}`, '.env.local', '.env', ,];
envList.forEach((e) => {
dotenv.config({
path: e,
});
});
for (const envName of Object.keys(process.env)) {
const realName = (process.env as any)[envName].replace(/\\n/g, '\n');
ret[envName] = realName;
process.env[envName] = realName;
}
return ret;
}