@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
206 lines (179 loc) • 6.09 kB
JavaScript
const path = require("path");
const { fork } = require('child_process');
const paths = require('./paths');
const fs = require('fs-extra');
const {
aRecursive,
clearConfigFilesCache,
depthCompareObject,
funcOrStr,
isFileExists,
} = require('../utils/common.js');
const PluginGenerator = require("../utils/pluginGenerator");
const chalk = require("chalk");
const pluginMainSuffixs = [".ts", ".js"];
/**
* 项目启动
*
* @param {any} webpackProcess
* @param {any} initSuccessPaths
* @param {any} isChangeEnv
*/
async function runWebpack(webpackProcess, initSuccessPaths, isChangeEnv) {
if (!initSuccessPaths) {
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);
}
}
// 在 `meta.json` 中缓存部分路径数据
const metaJson = fs.readJSONSync(paths.appTempMetaJs);
const configCacheFiles = await aRecursive(paths.appConfigTempPath);
// 清除缓存避免出现修改前的数据
const isDelCache = await clearConfigFilesCache(configCacheFiles);
if (isDelCache) {
let pluginInfos = [];
let pluginGenertor = {};
delete require.cache[require.resolve("../webpack/defaultConfig")];
const memoConfig = require("../webpack/defaultConfig")(
initSuccessPaths.appConfigTempIndexJs,
);
if (memoConfig.aniyaPlugins && memoConfig.aniyaPlugins.length) {
const pluginPaths = memoConfig.aniyaPlugins.map(pluginRelativePath => path.join(
paths.appNodeModules,
pluginRelativePath,
));
// 检查插件文件是否存在
const pluginFileExist = isFileExists(pluginPaths);
if (pluginFileExist) {
memoConfig.aniyaPlugins.forEach((pluginRelativePath) => {
const pluginResolvePath = path.join(
paths.appNodeModules,
pluginRelativePath,
"lib",
);
const extension = pluginMainSuffixs.find((extension) =>
fs.existsSync(`${pluginResolvePath}${extension}`),
);
if (extension) {
pluginGenertor = new PluginGenerator({
pluginIndex: `${pluginResolvePath}${extension}`,
memoConfig,
});
pluginGenertor.initialize();
// 使用局部变量避免污染全局 require
const esmRequire = require("esm")(module);
pluginGenertor.use(
esmRequire(`${pluginResolvePath}${extension}`).default,
);
pluginInfos.push(pluginGenertor.describeParams);
pluginGenertor.ending();
}
});
}
}
const strConfig = funcOrStr({
...pluginInfos.reduce((pre, cur) => {
if (cur.config && cur.config.default !== undefined) {
pre[cur.key] = cur.config.default;
}
return pre;
}, {}),
...memoConfig,
});
// 判断config是否更改
const isStart =
metaJson.lastConfig == null
? true
: depthCompareObject(metaJson.lastConfig, strConfig, [
"publicPath",
"proxy",
"devtool",
"alias",
"define",
"devServer",
"open",
"outputPath",
"routes",
"chainWebpack",
"aniyaPlugins",
"disableESLintPlugin",
"fastRefresh",
"useTailwindcss",
...pluginInfos.map((pluginInfo) => pluginInfo.key),
].filter(Boolean));
fs.writeJsonSync(
paths.appTempMetaJs,
{
...metaJson,
paths: initSuccessPaths,
lastConfig: strConfig,
},
{ spaces: 2 },
);
// 检查所需文件是否存在入口文件
const appIndexJsExist = isFileExists([paths.appIndexJs], paths.appPath, true);
const appConfigTempIndexJsExist = isFileExists([paths.appTempRouterIndexJs], paths.appPath, true);
if (!appIndexJsExist && !appConfigTempIndexJsExist) {
console.log(` ${chalk.gray('--')} ${chalk.red(path.relative(paths.appPath, paths.appIndexJs))}`);
console.log(` ${chalk.gray('--')} ${chalk.red(path.relative(paths.appPath, paths.appTempRouterIndexJs))}`);
console.log();
console.log(` ${chalk.yellow('缺少以上入口文件其一,请检查!')}`);
webpackProcess && webpackProcess.send('close');
webpackProcess && webpackProcess.kill && webpackProcess.kill();
process.exit(1);
}
// 启动webpack
// 首次启动、config指定配置变更
// 我们只有在确定项目需要启动或重启才检测插件
else if (isStart || isChangeEnv) {
return await startWebpack(webpackProcess);
}
}
}
/**
* 启动webpack
* 等待旧进程完全退出后再启动新进程,避免端口冲突
*
* @param {any} webpackProcess
*/
async function startWebpack(webpackProcess) {
if (webpackProcess) {
// 等待旧进程完全退出,确保端口释放
await new Promise((resolve) => {
const timeout = setTimeout(() => {
// 超时强制杀掉
webpackProcess.kill && webpackProcess.kill('SIGKILL');
resolve();
}, 5000);
webpackProcess.on('exit', () => {
clearTimeout(timeout);
resolve();
});
try {
webpackProcess.send('close');
} catch (e) {
// 进程可能已经退出
clearTimeout(timeout);
resolve();
}
});
}
webpackProcess = fork(
path.resolve(__dirname, "../webpack/webpackStartServer.js"),
{
cwd: process.cwd(),
stdio: "inherit",
},
);
return webpackProcess;
}
module.exports = {
runWebpack,
startWebpack
};