@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
265 lines (236 loc) • 7.48 kB
JavaScript
const fs = require("fs-extra");
const paths = require("./paths");
const execa = require("execa");
const path = require("path");
const { reddirResolveFile, progressBarHandle } = require("./common");
const escape = require("escape-string-regexp");
const isEnvDevelopment = process.env.NODE_ENV === "development";
// 转换commonjs模块通用部分命令
const commandArgs = [
"--module",
"commonjs",
"--allowJs",
"--resolveJsonModule",
"--esModuleInterop",
"--outDir",
];
/**
* 初始化 meta.json
*
* @returns {boolean}
*/
function initRequireFileHandle() {
return new Promise((resolve, reject) => {
try {
// 首次进入应用清除所有缓存
fs.existsSync(paths.appTempPath) && fs.removeSync(paths.appTempPath);
// 初始化appTempMetaJs文件
fs.ensureFileSync(paths.appTempMetaJs);
if (isEnvDevelopment) {
fs.writeJSONSync(
paths.appTempMetaJs,
{ cacheListenPaths: [] },
{
spaces: 2,
},
);
} else {
fs.writeJSONSync(paths.appTempMetaJs, {});
}
resolve(true);
} catch (error) {
reject(error);
}
});
}
/**
* 缓存自定义配置文件。
* mock、config
*
* @param {RegExp} envFileReg 匹配环境变量文件
* @param {string[]} cacheListenPaths 所有被监听的路径
* @param {boolean} changeMock mock被改变
* @param {boolean} changeConfig config被改变
* @return {*}
*/
async function initTempHandle(
envFileReg,
cacheListenPaths = [],
changeMock = false,
changeConfig = false,
) {
try {
const filterPathReg = new RegExp(`^${escape(paths.appMockPath)}/.+$`);
// 在 `meta.json` 中缓存部分路径数据
const metaJson = fs.readJSONSync(paths.appTempMetaJs);
// 获取config及深度依赖路径
const cacheConfigFilePaths = changeConfig
? cacheListenPaths
// 过滤所有非文件路径
.filter((cacheListenPath) => {
try {
const pathStats = fs.statSync(cacheListenPath);
if (pathStats.isFile()) {
return true;
} else {
return false;
}
} catch (error) {
return false;
}
})
// 过滤mock文件路径
.filter((cacheListenPath) => !filterPathReg.test(cacheListenPath))
: [];
let mockResolveFiles = [];
// 仅在测试环境生效
// 当mock文件存在时,将mock文件转换为commonjs模块内容
if (
fs.existsSync(paths.appMockPath) &&
!!fs.readdirSync(paths.appMockPath).length &&
isEnvDevelopment &&
changeMock
) {
mockResolveFiles = reddirResolveFile(paths.appMockPath);
let mockTempIndexJsContent = "";
let mockBasenameNoExtnames = [];
mockResolveFiles.forEach((mockResolveFile) => {
const mockExtname = path.extname(mockResolveFile);
const mockBasename = path.basename(mockResolveFile);
const mockBasenameNoExtname = mockBasename.slice(
0,
-mockExtname.length,
);
mockBasenameNoExtnames.push(mockBasenameNoExtname);
mockTempIndexJsContent += `
const ${mockBasenameNoExtname} = require('${path.join(
paths.appMockTempPath,
mockBasenameNoExtname,
)}').default;`;
});
mockTempIndexJsContent += `
module.exports = {
${mockBasenameNoExtnames.join(",\n")}
}
`;
// 为mock缓存文件提供一个入口文件
fs.ensureFileSync(paths.appMockTempIndexJs);
fs.writeFileSync(paths.appMockTempIndexJs, mockTempIndexJsContent);
}
const tempInfo = await progressBarHandle(
cacheConfigFilePaths,
mockResolveFiles,
async () => await initConfigTemp(envFileReg),
// const res = await (() => {
// return new Promise(resolve => {
// setTimeout(() => {
// resolve({
// appConfigIndexDirTempPath: '/Users/00513436/Desktop/code/cur/aniyajs-app/src/.aniya/aniya-config/config',
// appConfigTempIndexJs: '/Users/00513436/Desktop/code/cur/aniyajs-app/src/.aniya/aniya-config/config/config.js'
// });
// }, 5000);
// });
// })();
(mockResolveFile) => {
const mockCommandArgs = [
...commandArgs,
paths.appMockTempPath,
mockResolveFile,
];
execa.sync("tsc", mockCommandArgs, {
cwd: process.cwd(),
});
},
);
if (changeConfig) {
return Promise.resolve(tempInfo);
} else {
return Promise.resolve(metaJson.paths);
}
} catch (error) {
return Promise.reject(error);
}
}
/**
* 缓存config及深度依赖为commonjs文件
*
* @param {*} envFileReg 多环境配置文件匹配规则
* @returns
*/
async function initConfigTemp(envFileReg) {
try {
if (fs.pathExistsSync(paths.appConfigTempPath)) {
fs.removeSync(paths.appConfigTempPath);
}
// 生成配置文件缓存
const configCommandArgs = [
...commandArgs,
paths.appConfigTempPath,
paths.appConfigJs,
];
execa.sync("tsc", configCommandArgs, {
cwd: process.cwd(),
});
// 因为TSC命令生成的文件目录是不确定的。
// 获取生成的缓存文件目录。
const commandEnvConfigArgs = [...commandArgs];
const appConfigTempPath1 = paths.appConfigTempPath;
const appConfigTempIndexJs1 = path.join(appConfigTempPath1, "config.js");
const appConfigTempPath2 = path.join(paths.appConfigTempPath, "config");
const appConfigTempIndexJs2 = path.join(appConfigTempPath2, "config.js");
let appConfigTempIndexJs = appConfigTempIndexJs1;
let appConfigIndexDirTempPath = appConfigTempPath1;
if (fs.existsSync(appConfigTempIndexJs1)) {
commandEnvConfigArgs.push(appConfigTempPath1);
} else {
commandEnvConfigArgs.push(appConfigTempPath2);
appConfigIndexDirTempPath = appConfigTempPath2;
appConfigTempIndexJs = appConfigTempIndexJs2;
}
let envResolveFiles = [];
if (envFileReg) {
const configFiles = fs.readdirSync(paths.appConfigPath);
const envFiles = configFiles.filter((configFile) =>
envFileReg.test(configFile),
);
envFiles.forEach((envFile) => {
commandEnvConfigArgs.push(path.resolve(paths.appConfigPath, envFile));
});
envResolveFiles = envFiles.map((envFile) => {
const envFileSuffix = path.extname(envFile);
const envFileFine = envFile.replace(envFileSuffix, "");
return path.join(appConfigIndexDirTempPath, `${envFileFine}.js`);
});
if (envFiles && envFiles.length) {
// 生成环境配置文件缓存。
execa.sync("tsc", commandEnvConfigArgs, {
cwd: process.cwd(),
});
}
}
// 所需的文件已创建。
let exists = [];
[appConfigTempIndexJs, ...envResolveFiles].forEach((xxPath) => {
if (fs.existsSync(xxPath)) {
exists.push(true);
} else {
exists.push(false);
}
});
if (exists.find((exist) => !exist) != null) {
return Promise.resolve(false);
} else {
return Promise.resolve({
appConfigIndexDirTempPath,
appConfigTempIndexJs,
});
}
} catch (error) {
return Promise.reject(error);
}
}
module.exports = {
initRequireFileHandle,
initTempHandle,
initConfigTemp,
};