UNPKG

@aniyajs/rotor

Version:

基于webpack5开发的一款专注于打包、运行的工具

206 lines (179 loc) 6.09 kB
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 };