支持了打包web项目
This commit is contained in:
parent
36f2ae82c2
commit
0b521a16c6
|
|
@ -35,11 +35,21 @@ function parseCliArgs() {
|
|||
},
|
||||
port: {
|
||||
type: "string",
|
||||
default: "3001"
|
||||
default: ["3001", "8080"],
|
||||
multiple: true
|
||||
},
|
||||
"node-version": {
|
||||
type: "string",
|
||||
default: "20"
|
||||
},
|
||||
// 打包web还是后端
|
||||
"build-type": {
|
||||
type: "string",
|
||||
default: "backend"
|
||||
},
|
||||
"web-source": {
|
||||
type: "string",
|
||||
default: "web"
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
|
|
@ -57,6 +67,7 @@ function parseCliArgs() {
|
|||
--registry=<url> npm \u955C\u50CF\u7AD9\u5730\u5740\uFF0C\u9ED8\u8BA4: https://registry.npmmirror.com
|
||||
--port=<port> \u66B4\u9732\u7684\u7AEF\u53E3\u53F7\uFF0C\u9ED8\u8BA4: 3001
|
||||
--node-version=<ver> Node.js \u7248\u672C\uFF0C\u9ED8\u8BA4: 20
|
||||
--build-type=<type> \u6784\u5EFA\u7C7B\u578B (native|wechatMp|web|backend)\uFF0C\u9ED8\u8BA4: backend
|
||||
-h, --help \u663E\u793A\u6B64\u5E2E\u52A9\u4FE1\u606F
|
||||
|
||||
\u793A\u4F8B:
|
||||
|
|
@ -78,6 +89,11 @@ function parseCliArgs() {
|
|||
console.error(" \u652F\u6301\u7684\u73AF\u5883: dev, prod, staging");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!["native", "wechatMp", "web", "backend"].includes(values["build-type"])) {
|
||||
console.error(`\u274C \u65E0\u6548\u7684\u6784\u5EFA\u7C7B\u578B: ${values["build-type"]}`);
|
||||
console.error(" \u652F\u6301\u7684\u7C7B\u578B: native, wechatMp, web, backend");
|
||||
process.exit(1);
|
||||
}
|
||||
return {
|
||||
projectDir,
|
||||
options: {
|
||||
|
|
@ -85,7 +101,9 @@ function parseCliArgs() {
|
|||
extra: values.extra,
|
||||
registry: values.registry,
|
||||
port: values.port,
|
||||
nodeVersion: values["node-version"]
|
||||
nodeVersion: values["node-version"],
|
||||
buildType: values["build-type"],
|
||||
webSource: values["web-source"]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -195,7 +213,7 @@ RUN rm -rf src \\
|
|||
# \u5207\u6362\u56DE\u4E3B\u9879\u76EE\u76EE\u5F55
|
||||
WORKDIR /app/${projectName}
|
||||
|
||||
EXPOSE ${port}
|
||||
EXPOSE ${port.join(" ")}
|
||||
|
||||
CMD ["pm2-runtime", "start", "pm2.${env}.json"]
|
||||
`;
|
||||
|
|
@ -262,6 +280,7 @@ function main() {
|
|||
console.log(`-> \u914D\u7F6E\u4FE1\u606F:`);
|
||||
console.log(` \u9879\u76EE\u76EE\u5F55: ${projectDir}`);
|
||||
console.log(` \u73AF\u5883: ${options.env}`);
|
||||
console.log(` \u6784\u5EFA\u7C7B\u578B: ${options.buildType}`);
|
||||
console.log(
|
||||
` \u989D\u5916\u4F9D\u8D56: ${options.extra.length > 0 ? options.extra.join(", ") : "\u65E0"}`
|
||||
);
|
||||
|
|
@ -272,6 +291,19 @@ function main() {
|
|||
console.error(`\u274C \u9879\u76EE\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${projectDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
switch (options.buildType) {
|
||||
case "backend":
|
||||
packageBackend(projectDir, options);
|
||||
break;
|
||||
case "web":
|
||||
packageWeb(projectDir, options);
|
||||
break;
|
||||
default:
|
||||
console.error(`\u274C \u4E0D\u652F\u6301\u7684\u6784\u5EFA\u7C7B\u578B: ${options.buildType}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
function packageBackend(projectDir, options) {
|
||||
let skipConfigReplace = false;
|
||||
const configDir = path.join(projectDir, "configurations");
|
||||
if (!fs.existsSync(configDir)) {
|
||||
|
|
@ -284,8 +316,8 @@ function main() {
|
|||
const projectName = path.basename(projectDir);
|
||||
const dockerfileContent = generateDockerfile(projectName, options);
|
||||
const dockerignoreContent = generateDockerignore();
|
||||
fs.writeFileSync(path.join(pwd2, "Dockerfile"), dockerfileContent);
|
||||
fs.writeFileSync(path.join(pwd2, ".dockerignore"), dockerignoreContent);
|
||||
fs.writeFileSync(path.join(pwd, "Dockerfile"), dockerfileContent);
|
||||
fs.writeFileSync(path.join(pwd, ".dockerignore"), dockerignoreContent);
|
||||
console.log("\n\u{1F4DD} \u5DF2\u751F\u6210 Dockerfile \u548C .dockerignore");
|
||||
try {
|
||||
if (!skipConfigReplace) {
|
||||
|
|
@ -299,23 +331,55 @@ function main() {
|
|||
configPath,
|
||||
path.join(projectDir, "configuration/mysql.json")
|
||||
);
|
||||
buildDockerImage(imageBase, name, pwd2);
|
||||
saveDockerImage(imageBase, name, pwd2);
|
||||
buildDockerImage(imageBase, name, pwd);
|
||||
saveDockerImage(imageBase, name, pwd);
|
||||
}
|
||||
} else {
|
||||
const name = `default-${options.env}`;
|
||||
console.log(`
|
||||
\u{1F527} \u6784\u5EFA\u9ED8\u8BA4\u955C\u50CF ${name}...`);
|
||||
buildDockerImage(imageBase, name, pwd2);
|
||||
saveDockerImage(imageBase, name, pwd2);
|
||||
buildDockerImage(imageBase, name, pwd);
|
||||
saveDockerImage(imageBase, name, pwd);
|
||||
}
|
||||
console.log("\n\u2705 \u6240\u6709\u955C\u50CF\u6784\u5EFA\u6210\u529F\uFF01");
|
||||
} finally {
|
||||
fs.rmSync(path.join(projectDir, "configuration/mysql.json"), {
|
||||
force: true
|
||||
});
|
||||
fs.rmSync(path.join(pwd2, "Dockerfile"), { force: true });
|
||||
fs.rmSync(path.join(pwd2, ".dockerignore"), { force: true });
|
||||
fs.rmSync(path.join(pwd, "Dockerfile"), { force: true });
|
||||
fs.rmSync(path.join(pwd, ".dockerignore"), { force: true });
|
||||
}
|
||||
}
|
||||
function packageWeb(projectDir, options) {
|
||||
console.log(`
|
||||
\u{1F527} \u6253\u5305 Web \u9879\u76EE...`);
|
||||
const distDir = path.join(pwd, "dist");
|
||||
if (!fs.existsSync(distDir)) {
|
||||
fs.mkdirSync(distDir);
|
||||
}
|
||||
execSync(`npm install`, {
|
||||
stdio: "inherit",
|
||||
cwd: projectDir
|
||||
});
|
||||
execSync(`npm run build:${options.webSource}${options.env === "staging" ? ":staging" : ""}`, {
|
||||
stdio: "inherit",
|
||||
cwd: projectDir
|
||||
});
|
||||
const webDistDir = path.join(projectDir, options.webSource, "build");
|
||||
if (!fs.existsSync(webDistDir)) {
|
||||
console.error(`\u274C \u6784\u5EFA\u5931\u8D25\uFF0C\u627E\u4E0D\u5230 Web \u6784\u5EFA\u4EA7\u7269\u76EE\u5F55: ${webDistDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const projectName = path.basename(projectDir);
|
||||
const outputWebDir = path.join(distDir, "html", projectName, options.webSource);
|
||||
if (!fs.existsSync(path.join(distDir, "html", projectName))) {
|
||||
fs.mkdirSync(path.join(distDir, "html", projectName));
|
||||
}
|
||||
fs.rmSync(outputWebDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(outputWebDir);
|
||||
execSync(`cp -r ${webDistDir}/* ${outputWebDir}/`, {
|
||||
stdio: "inherit"
|
||||
});
|
||||
console.log(`\u2705 Web \u9879\u76EE\u6253\u5305\u6210\u529F\uFF0C\u4EA7\u7269\u4F4D\u4E8E: ${outputWebDir}`);
|
||||
}
|
||||
main();
|
||||
|
|
|
|||
88
src/cli.ts
88
src/cli.ts
|
|
@ -9,8 +9,10 @@ interface BuildOptions {
|
|||
env: string;
|
||||
extra: string[];
|
||||
registry: string;
|
||||
port: string;
|
||||
port: string[];
|
||||
nodeVersion: string;
|
||||
buildType: string;
|
||||
webSource: string;
|
||||
}
|
||||
|
||||
interface ParsedArgs {
|
||||
|
|
@ -52,12 +54,22 @@ function parseCliArgs(): ParsedArgs | null {
|
|||
},
|
||||
port: {
|
||||
type: "string",
|
||||
default: "3001",
|
||||
default: ["3001", "8080"],
|
||||
multiple: true,
|
||||
},
|
||||
"node-version": {
|
||||
type: "string",
|
||||
default: "20",
|
||||
},
|
||||
// 打包web还是后端
|
||||
"build-type": {
|
||||
type: "string",
|
||||
default: "backend",
|
||||
},
|
||||
"web-source": {
|
||||
type: "string",
|
||||
default: "web",
|
||||
}
|
||||
},
|
||||
allowPositionals: true,
|
||||
});
|
||||
|
|
@ -76,6 +88,7 @@ function parseCliArgs(): ParsedArgs | null {
|
|||
--registry=<url> npm 镜像站地址,默认: https://registry.npmmirror.com
|
||||
--port=<port> 暴露的端口号,默认: 3001
|
||||
--node-version=<ver> Node.js 版本,默认: 20
|
||||
--build-type=<type> 构建类型 (native|wechatMp|web|backend),默认: backend
|
||||
-h, --help 显示此帮助信息
|
||||
|
||||
示例:
|
||||
|
|
@ -103,14 +116,22 @@ function parseCliArgs(): ParsedArgs | null {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!["native", "wechatMp", "web", "backend"].includes(values["build-type"] as string)) {
|
||||
console.error(`❌ 无效的构建类型: ${values["build-type"]}`);
|
||||
console.error(" 支持的类型: native, wechatMp, web, backend");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return {
|
||||
projectDir,
|
||||
options: {
|
||||
env,
|
||||
extra: values.extra as string[],
|
||||
registry: values.registry as string,
|
||||
port: values.port as string,
|
||||
port: values.port as string[],
|
||||
nodeVersion: values["node-version"] as string,
|
||||
buildType: values["build-type"] as string,
|
||||
webSource: values["web-source"] as string,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -241,7 +262,7 @@ RUN rm -rf src \\
|
|||
# 切换回主项目目录
|
||||
WORKDIR /app/${projectName}
|
||||
|
||||
EXPOSE ${port}
|
||||
EXPOSE ${port.join(" ")}
|
||||
|
||||
CMD ["pm2-runtime", "start", "pm2.${env}.json"]
|
||||
`;
|
||||
|
|
@ -334,6 +355,7 @@ function main(): void {
|
|||
console.log(`-> 配置信息:`);
|
||||
console.log(` 项目目录: ${projectDir}`);
|
||||
console.log(` 环境: ${options.env}`);
|
||||
console.log(` 构建类型: ${options.buildType}`);
|
||||
console.log(
|
||||
` 额外依赖: ${options.extra.length > 0 ? options.extra.join(", ") : "无"}`
|
||||
);
|
||||
|
|
@ -346,6 +368,21 @@ function main(): void {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
switch (options.buildType) {
|
||||
case "backend":
|
||||
packageBackend(projectDir, options);
|
||||
break;
|
||||
case "web":
|
||||
packageWeb(projectDir, options);
|
||||
break;
|
||||
default:
|
||||
console.error(`❌ 不支持的构建类型: ${options.buildType}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function packageBackend(projectDir: string, options: BuildOptions): void {
|
||||
let skipConfigReplace = false;
|
||||
const configDir = path.join(projectDir, "configurations");
|
||||
if (!fs.existsSync(configDir)) {
|
||||
|
|
@ -408,5 +445,48 @@ function main(): void {
|
|||
}
|
||||
}
|
||||
|
||||
function packageWeb(projectDir: string, options: BuildOptions): void {
|
||||
// Web 项目的打包逻辑:
|
||||
// 1. 进入项目目录,执行 npm install 和 npm run build:web
|
||||
// 2. 将web/build目录下的内容压缩后复制到pwd/dist目录下
|
||||
console.log(`\n🔧 打包 Web 项目...`);
|
||||
const distDir = path.join(pwd, "dist");
|
||||
if (!fs.existsSync(distDir)) {
|
||||
fs.mkdirSync(distDir);
|
||||
}
|
||||
|
||||
// 进入项目目录执行构建命令
|
||||
execSync(`npm install`, {
|
||||
stdio: "inherit",
|
||||
cwd: projectDir,
|
||||
});
|
||||
execSync(`npm run build:${options.webSource}${options.env === 'staging' ? ':staging' : ''}`, {
|
||||
stdio: "inherit",
|
||||
cwd: projectDir,
|
||||
});
|
||||
const webDistDir = path.join(projectDir, options.webSource, "build");
|
||||
if (!fs.existsSync(webDistDir)) {
|
||||
console.error(`❌ 构建失败,找不到 Web 构建产物目录: ${webDistDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const projectName = path.basename(projectDir);
|
||||
|
||||
// 复制构建产物到 dist 目录
|
||||
const outputWebDir = path.join(distDir, "html", projectName, options.webSource);
|
||||
|
||||
if (!fs.existsSync(path.join(distDir, "html", projectName))) {
|
||||
fs.mkdirSync(path.join(distDir, "html", projectName));
|
||||
}
|
||||
|
||||
fs.rmSync(outputWebDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(outputWebDir);
|
||||
execSync(`cp -r ${webDistDir}/* ${outputWebDir}/`, {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
console.log(`✅ Web 项目打包成功,产物位于: ${outputWebDir}`);
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
main();
|
||||
|
|
|
|||
Loading…
Reference in New Issue