@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
163 lines (141 loc) • 4.85 kB
JavaScript
;
// 抛出所有未被捕获的错误
process.on("unhandledRejection", (error) => {
throw error;
});
const chalk = require("chalk");
const fs = require('fs-extra');
const { checkBrowsers } = require("../utils/browsHelper");
const webpack = require("webpack");
const semver = require("semver");
const WebpackDevServer = require("webpack-dev-server");
const paths = require("../utils/paths");
const { clearConsole, reviveFunctions } = require("../utils/common");
const openBrowser = require("../utils/openBrowser");
const {
choosePort,
prepareUrls,
createCompiler,
} = require("../utils/webpackDevServerUtils");
const clientEnv = require("./env")();
delete require.cache[require.resolve(paths.appTempMetaJs)];
const appTempMetaJson = require(paths.appTempMetaJs);
const defaultConfig = reviveFunctions(
require(paths.appTempMetaJs).lastConfig,
);
const WebpackDevServerConfig = require("./webpackDevServer.config");
const isInteractive = process.stdout.isTTY;
const HOST = defaultConfig?.devServer?.host ? defaultConfig?.devServer?.host: 'localhost';
const DEFAULT_PORT = defaultConfig?.devServer?.port ? defaultConfig?.devServer?.port: 8000;
const PROTOCOL = defaultConfig?.devServer?.https ? "https" : "http";
const fastRefresh = defaultConfig.fastRefresh;
const open = defaultConfig.open;
const useTypeScript = fs.existsSync(paths.appTsConfig);
const packageJson = require(paths.appPackageJson);
const appName = packageJson.name;
const appVersion = packageJson.version;
const existReact = packageJson.dependencies?.react || packageJson.devDependencies?.react;
const useYarn = fs.existsSync(paths.yarnLockFile);
const react = existReact ? require(require.resolve("react", { paths: [paths.appPath] })) : false;
let mockData = {};
let devServer = null;
if (fs.existsSync(paths.appMockTempIndexJs)) {
mockData = Object.values(require(paths.appMockTempIndexJs)).reduce(
(pre, cur) => Object.assign(pre, { ...cur }),
{},
);
}
if (HOST != "0.0.0.0" && HOST != "localhost") {
console.log();
console.log(chalk.cyan(`尝试绑定到当前主机:${chalk.yellow.bold(HOST)}。`));
console.log(
`如果不是故意的,检查你的 ${chalk.bold("devServer.host")} 配置。`,
);
console.log(
`详细信息请参考:${chalk.yellow(
"https://webpack.docschina.org/configuration/dev-server/#devserverhost",
)}.`,
);
console.log();
}
// 指定browserslist配置
checkBrowsers(paths.appPath, isInteractive)
.then(() => {
if (isInteractive) {
clearConsole();
}
// 监听父进程消息
process.on('message', (msg) => {
if (msg === 'close') {
devServer && devServer.stopCallback && devServer.stopCallback(() => {
process.exit(0);
});
}
});
// 获取端口
return choosePort(HOST, DEFAULT_PORT);
})
.then((port) => {
// 端口不存在
if (port == null) {
return;
}
fs.writeJsonSync(
paths.appTempMetaJs,
{ ...appTempMetaJson, lastConfig: { ...appTempMetaJson?.lastConfig, devServer: { ...(appTempMetaJson?.lastConfig?.devServer ?? {}), port } } },
{ spaces: 2 },
);
console.log(chalk.cyan("Start development server..."));
const newBasename = appTempMetaJson?.lastConfig?.basename?.endsWith('/')
? appTempMetaJson?.lastConfig?.basename.slice(0, -1)
: appTempMetaJson?.lastConfig?.basename;
const urls = prepareUrls(
PROTOCOL,
HOST,
port,
newBasename,
appTempMetaJson?.lastConfig?.hash
);
// 创建自定义消息的编译器
const compiler = createCompiler({
webpack,
latestConfig: clientEnv.latestConfig,
useTypeScript,
appName,
appVersion,
urls,
useYarn,
});
const serverConfig = {
...WebpackDevServerConfig(HOST, defaultConfig.proxy, mockData),
host: HOST,
port,
};
/** @type { import('webpack-dev-server') } */
devServer = new WebpackDevServer(serverConfig, compiler);
devServer.startCallback(() => {
if (isInteractive) {
clearConsole();
}
if (fastRefresh && existReact && semver.lt(react.version, "16.9.0")) {
console.log(
chalk.yellow(
`快速刷新需要React 16.9或更高版本。你在使用React${react.version}.`,
),
);
console.log();
}
open && openBrowser(urls.localUrlForBrowser);
});
["SIGINT", "SIGTERM"].forEach(function (sig) {
process.on(sig, function () {
devServer.close();
process.exit();
});
});
})
.catch((err) => {
console.log();
console.log(err);
process.exit(1);
})