@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
261 lines (222 loc) • 7.58 kB
JavaScript
;
const fs = require("fs-extra");
const paths = require("./paths");
const execa = require("execa");
const path = require("path");
const escape = require("escape-string-regexp");
const { reddirResolveFile, progressBarHandle } = require("./common");
const compileWithTempConfig = require("./compileTempFile");
const { cleanupTempConfig } = require("./compileTempFile");
const isEnvDevelopment = process.env.NODE_ENV === "development";
/**
* 初始化 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 (fs.pathExistsSync(paths.appTempCachePath)) {
fs.removeSync(paths.appTempCachePath);
}
if (fs.pathExistsSync(paths.appConfigTempPath)) {
fs.removeSync(paths.appConfigTempPath);
}
if (fs.pathExistsSync(paths.appEnvConfigTempPath)) {
fs.removeSync(paths.appEnvConfigTempPath);
}
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} isFirstStart 是否是首次启动
* @return {*}
*/
async function initTempHandle(envFileReg, cacheListenPaths = [], isFirstStart) {
if (!fs.existsSync(paths.appConfigJs)) {
return Promise.resolve(false);
}
fs.ensureDirSync(paths.appTempCachePath);
try {
// // 在 `meta.json` 中缓存部分路径数据
// const metaJson = fs.readJSONSync(paths.appTempMetaJs);
// 获取config及深度依赖路径
const cacheConfigFilePaths = cacheListenPaths
// 过滤所有非文件路径
.filter((cacheListenPath) => {
try {
const pathStats = fs.statSync(cacheListenPath);
if (pathStats.isFile()) {
return true;
} else {
return false;
}
} catch (error) {
return false;
}
});
let mockResolveFiles = [];
// 仅在测试环境生效
// 当mock文件存在时,将mock文件转换为commonjs模块内容
if (isFirstStart || !fs.pathExistsSync(paths.appMockTempPath)) {
if (fs.pathExistsSync(paths.appMockTempPath)) {
fs.removeSync(paths.appMockTempPath);
}
if (
fs.existsSync(paths.appMockPath) &&
!!fs.readdirSync(paths.appMockPath).length
) {
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);
const mockFilePath = path.join(
paths.appMockTempPath,
mockBasenameNoExtname
);
// 转为 POSIX 路径(正斜杠)
const posixMockPath = mockFilePath.replace(/\\/g, "/");
mockTempIndexJsContent += `
const ${mockBasenameNoExtname} = require('${posixMockPath}').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),
(mockResolveFile) => {
compileWithTempConfig(
mockResolveFile, // 支持数组
paths.appMockTempPath
);
}
);
// 所有编译完成后清理临时 tsconfig
cleanupTempConfig();
console.log();
return Promise.resolve(tempInfo);
} 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);
}
if (fs.pathExistsSync(paths.appEnvConfigTempPath)) {
fs.removeSync(paths.appEnvConfigTempPath);
}
let appConfigTempIndexJs = path.join(paths.appConfigTempPath, "config.js");
let appConfigTemp = paths.appConfigTempPath;
let appEnvConfigTemp = paths.appEnvConfigTempPath;
let appEnvConfigTempJs = "";
compileWithTempConfig(paths.appConfigJs, paths.appConfigTempPath);
if (!fs.existsSync(appConfigTempIndexJs)) {
appConfigTempIndexJs = path.join(
paths.appConfigTempPath,
"config/config.js"
);
appConfigTemp = path.join(paths.appConfigTempPath, "config");
}
// 生成环境配置文件缓存
let envResolveFiles = [];
let envFilePaths = [];
if (envFileReg) {
const configFiles = fs.readdirSync(paths.appConfigPath);
const envFiles = configFiles.filter((configFile) =>
envFileReg.test(configFile)
);
envFiles.forEach((envFile) => {
const envFileBaseName = path.basename(envFile, path.extname(envFile));
appEnvConfigTempJs = path.join(
paths.appEnvConfigTempPath,
`${envFileBaseName}.js`
);
envFilePaths.push(path.resolve(paths.appConfigPath, envFile));
});
if (envFiles && envFiles.length) {
// 生成环境配置文件缓存。
compileWithTempConfig(envFilePaths, paths.appEnvConfigTempPath);
}
if (!fs.existsSync(appEnvConfigTempJs)) {
appEnvConfigTemp = path.join(paths.appEnvConfigTempPath, `config`);
}
envResolveFiles = envFiles.map((envFile) => {
const envFileSuffix = path.extname(envFile);
const envFileFine = envFile.replace(envFileSuffix, "");
return path.join(appEnvConfigTemp, `${envFileFine}.js`);
});
}
// 所需的文件已创建。
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({
appConfigTemp,
appEnvConfigTemp,
appConfigTempIndexJs,
});
}
} catch (error) {
return Promise.reject(error);
}
}
module.exports = {
initRequireFileHandle,
initTempHandle,
initConfigTemp,
};