Skip to content

Commit d0a95ea

Browse files
committed
chore: update build script and release script
1 parent 09e3d5f commit d0a95ea

File tree

16 files changed

+394
-319
lines changed

16 files changed

+394
-319
lines changed

client/bin/reactpress-client.js

Lines changed: 44 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
/**
44
* ReactPress Client CLI Entry Point
55
* This script allows starting the ReactPress client via npx
6+
* Supports both regular and PM2 startup modes
67
*/
78

89
const path = require('path');
910
const fs = require('fs');
1011
const { spawn, spawnSync } = require('child_process');
11-
const url = require('url');
12+
13+
// Capture the original working directory where npx was executed
14+
// BUT prioritize the REACTPRESS_ORIGINAL_CWD environment variable if it exists
15+
// This ensures consistency when running via pnpm dev from root directory
16+
const originalCwd = process.env.REACTPRESS_ORIGINAL_CWD || process.cwd();
1217

1318
// Get command line arguments
1419
const args = process.argv.slice(2);
@@ -28,7 +33,7 @@ Options:
2833
--help, -h Show this help message
2934
3035
Examples:
31-
npx @fecommunity/reactpress-client # Start client in development mode
36+
npx @fecommunity/reactpress-client # Start client normally
3237
npx @fecommunity/reactpress-client --pm2 # Start client with PM2
3338
npx @fecommunity/reactpress-client --help # Show this help message
3439
`);
@@ -38,38 +43,7 @@ Examples:
3843
// Get the directory where this script is located
3944
const binDir = __dirname;
4045
const clientDir = path.join(binDir, '..');
41-
42-
// Change to the client directory
43-
process.chdir(clientDir);
44-
45-
// Try to load configuration
46-
let port = 3001;
47-
let clientSiteUrl = 'http://localhost:3001';
48-
49-
try {
50-
const { config } = require('@fecommunity/reactpress-config');
51-
52-
// Extract port from CLIENT_SITE_URL or use CLIENT_PORT
53-
if (config.CLIENT_SITE_URL) {
54-
try {
55-
const parsedUrl = url.parse(config.CLIENT_SITE_URL);
56-
if (parsedUrl.port) {
57-
port = parseInt(parsedUrl.port, 10);
58-
} else if (parsedUrl.protocol === 'https:') {
59-
port = 443;
60-
} else {
61-
port = 80;
62-
}
63-
clientSiteUrl = config.CLIENT_SITE_URL;
64-
} catch (err) {
65-
console.warn('[ReactPress Client] Failed to parse CLIENT_SITE_URL, using default port 3001');
66-
}
67-
} else if (config.CLIENT_PORT) {
68-
port = parseInt(config.CLIENT_PORT, 10);
69-
}
70-
} catch (err) {
71-
console.warn('[ReactPress Client] Failed to load configuration, using default settings');
72-
}
46+
const nextDir = path.join(clientDir, '.next');
7347

7448
// Function to check if PM2 is installed
7549
function isPM2Installed() {
@@ -115,7 +89,6 @@ function startWithPM2() {
11589
}
11690

11791
// Check if the client is built
118-
const nextDir = path.join(clientDir, '.next');
11992
if (!fs.existsSync(nextDir)) {
12093
console.log('[ReactPress Client] Client not built yet. Building...');
12194

@@ -162,85 +135,56 @@ function startWithPM2() {
162135
});
163136
}
164137

165-
// Function to start with regular Node.js
138+
// Function to start with regular Node.js (npm start)
166139
function startWithNode() {
167-
// Check if we're in development or production mode
168-
const isDev = process.env.NODE_ENV !== 'production';
169-
170-
if (isDev) {
171-
// In development mode, start Next.js dev server
172-
console.log('[ReactPress Client] Starting Next.js development server...');
140+
// Check if the app is built
141+
if (!fs.existsSync(nextDir)) {
142+
console.log('[ReactPress Client] Client not built yet. Building...');
173143

174-
// Use Next.js CLI directly
175-
const nextDev = spawn('npx', ['next', 'dev', '-p', port.toString()], {
144+
// Try to build the client
145+
const buildResult = spawnSync('npm', ['run', 'build'], {
176146
stdio: 'inherit',
177147
cwd: clientDir
178148
});
179149

180-
nextDev.on('close', (code) => {
181-
console.log(`[ReactPress Client] Next.js dev server exited with code ${code}`);
182-
process.exit(code);
183-
});
184-
185-
nextDev.on('error', (error) => {
186-
console.error('[ReactPress Client] Failed to start Next.js dev server:', error);
150+
if (buildResult.status !== 0) {
151+
console.error('[ReactPress Client] Failed to build client');
187152
process.exit(1);
188-
});
189-
} else {
190-
// In production mode, check if the app is built and start it
191-
const nextDir = path.join(clientDir, '.next');
192-
193-
if (!fs.existsSync(nextDir)) {
194-
console.log('[ReactPress Client] Client not built yet. Building...');
195-
196-
// Try to build the client
197-
const buildResult = spawnSync('npm', ['run', 'build'], {
198-
stdio: 'inherit',
199-
cwd: clientDir
200-
});
201-
202-
if (buildResult.status !== 0) {
203-
console.error('[ReactPress Client] Failed to build client');
204-
process.exit(1);
205-
}
206153
}
207-
208-
console.log('[ReactPress Client] Starting Next.js production server...');
209-
210-
// Start Next.js production server
211-
const nextStart = spawn('npx', ['next', 'start', '-p', port.toString()], {
212-
stdio: 'inherit',
213-
cwd: clientDir
214-
});
215-
216-
nextStart.on('close', (code) => {
217-
console.log(`[ReactPress Client] Next.js production server exited with code ${code}`);
218-
process.exit(code);
219-
});
220-
221-
nextStart.on('error', (error) => {
222-
console.error('[ReactPress Client] Failed to start Next.js production server:', error);
223-
process.exit(1);
224-
});
225154
}
226-
}
227155

228-
console.log(`[ReactPress Client] Starting client on port ${port}...`);
156+
// ONLY set the environment variable if it's not already set
157+
// This preserves the value set by set-env.js when running pnpm dev from root
158+
if (!process.env.REACTPRESS_ORIGINAL_CWD) {
159+
process.env.REACTPRESS_ORIGINAL_CWD = originalCwd;
160+
} else {
161+
console.log(`[ReactPress Client] Using existing REACTPRESS_ORIGINAL_CWD: ${process.env.REACTPRESS_ORIGINAL_CWD}`);
162+
}
163+
164+
// Change to the client directory
165+
process.chdir(clientDir);
166+
167+
// Start with npm start
168+
console.log('[ReactPress Client] Starting with npm start...');
169+
const npmStart = spawn('npm', ['start'], {
170+
stdio: 'inherit',
171+
cwd: clientDir
172+
});
173+
174+
npmStart.on('close', (code) => {
175+
console.log(`[ReactPress Client] npm start process exited with code ${code}`);
176+
process.exit(code);
177+
});
178+
179+
npmStart.on('error', (error) => {
180+
console.error('[ReactPress Client] Failed to start with npm start:', error);
181+
process.exit(1);
182+
});
183+
}
229184

230185
// Main execution
231186
if (usePM2) {
232187
startWithPM2();
233188
} else {
234189
startWithNode();
235-
}
236-
237-
// Try to automatically open browser after a short delay (only in dev mode and not with PM2)
238-
if (!usePM2 && process.env.NODE_ENV !== 'production') {
239-
setTimeout(() => {
240-
try {
241-
require('open')(clientSiteUrl);
242-
} catch (err) {
243-
console.warn('[ReactPress Client] Failed to open browser automatically');
244-
}
245-
}, 3000);
246190
}

client/next.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ const getServerApiUrl = () => {
1818
const nextConfig = {
1919
assetPrefix: config.CLIENT_ASSET_PREFIX || '/',
2020
i18n: {
21-
locales,
22-
defaultLocale,
21+
locales: locales && locales.length > 0 ? locales : ['zh', 'en'],
22+
defaultLocale: defaultLocale || 'zh',
2323
},
2424
env: {
2525
SERVER_API_URL: getServerApiUrl(),

client/package.json

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
{
22
"name": "@fecommunity/reactpress-client",
3-
"version": "1.0.0-beta.3",
3+
"version": "1.0.0-beta.21",
44
"bin": {
55
"reactpress-client": "./bin/reactpress-client.js"
66
},
77
"files": [
88
".next/**/*",
99
"bin/**/*",
10-
"pages/**/*",
11-
"public/**/*",
12-
"src/**/*",
13-
"types/**/*",
1410
"next.config.js",
15-
"next-sitemap.js",
16-
"server.js",
17-
"tsconfig.json"
11+
"server.js"
1812
],
1913
"scripts": {
2014
"prebuild": "rimraf .next",

client/public/sitemap.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
3-
<url><loc>http://localhost:3001</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
4-
<url><loc>http://localhost:3001/archives</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
5-
<url><loc>http://localhost:3001/knowledge</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
6-
<url><loc>http://localhost:3001/login</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
7-
<url><loc>http://localhost:3001/nav</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
8-
<url><loc>http://localhost:3001/rss</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T05:25:49.206Z</lastmod></url>
3+
<url><loc>http://localhost:3001</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
4+
<url><loc>http://localhost:3001/archives</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
5+
<url><loc>http://localhost:3001/knowledge</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
6+
<url><loc>http://localhost:3001/login</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
7+
<url><loc>http://localhost:3001/nav</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
8+
<url><loc>http://localhost:3001/rss</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T11:48:06.840Z</lastmod></url>
99
</urlset>

client/server.js

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,11 @@
11
const { config } = require('@fecommunity/reactpress-config');
2-
const cli = require('next/dist/cli/next-dev');
3-
const { spawn } = require('child_process');
2+
const cli = require('next/dist/cli/next-start');
43

5-
// Extract port from CLIENT_SITE_URL or default to 3001
6-
let port = 3001;
7-
if (config.CLIENT_SITE_URL) {
8-
try {
9-
const url = require('url');
10-
const parsedUrl = url.parse(config.CLIENT_SITE_URL);
11-
if (parsedUrl.port) {
12-
port = parseInt(parsedUrl.port, 10);
13-
} else if (parsedUrl.protocol === 'https:') {
14-
port = 443;
15-
} else {
16-
port = 80;
17-
}
18-
} catch (err) {
19-
console.warn('[ReactPress] Failed to parse CLIENT_SITE_URL, using default port 3001');
20-
}
21-
}
4+
const port = config.CLIENT_PORT || 3001;
225

23-
// Get command line arguments
24-
const args = process.argv.slice(2);
25-
const usePM2 = args.includes('--pm2');
26-
27-
if (usePM2) {
28-
// Check if PM2 is installed
29-
try {
30-
require.resolve('pm2');
31-
} catch (e) {
32-
// Check if PM2 is installed globally
33-
try {
34-
const { spawnSync } = require('child_process');
35-
spawnSync('pm2', ['--version'], { stdio: 'ignore' });
36-
} catch (e) {
37-
console.log('[ReactPress] PM2 not found. Installing PM2...');
38-
const { spawnSync } = require('child_process');
39-
const installResult = spawnSync('npm', ['install', 'pm2', '--no-save'], {
40-
stdio: 'inherit'
41-
});
42-
43-
if (installResult.status !== 0) {
44-
console.error('[ReactPress] Failed to install PM2');
45-
process.exit(1);
46-
}
47-
}
48-
}
49-
50-
// Use PM2 to start the Next.js development server
51-
console.log('[ReactPress] Starting client with PM2...');
52-
const pm2 = spawn('pm2', ['start', 'npm', '--name', 'reactpress-client', '--', 'run', 'dev'], {
53-
stdio: 'inherit'
54-
});
55-
56-
pm2.on('close', (code) => {
57-
console.log(`[ReactPress] PM2 process exited with code ${code}`);
58-
process.exit(code);
59-
});
60-
61-
pm2.on('error', (error) => {
62-
console.error('[ReactPress] Failed to start with PM2:', error);
63-
process.exit(1);
64-
});
65-
} else {
66-
try {
67-
cli.nextDev(['-p', port.toString());
68-
console.log(`[ReactPress] 客户端已启动,端口:${port}`);
69-
// 自动打开
70-
require('open')(`http://localhost:${port}`);
71-
} catch (err) {
72-
console.log(`[ReactPress] 客户端启动失败!${err.message || err}`);
73-
}
6+
try {
7+
cli.nextStart(['-p', port]);
8+
console.log(`[reactpress] 客户端已启动,端口:${port}`);
9+
} catch (err) {
10+
console.log(`[reactpress] 客户端启动失败!${err.message || err}`);
7411
}

config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fecommunity/reactpress-config",
3-
"version": "1.0.0-beta.22",
3+
"version": "1.0.0-beta.33",
44
"description": "ReactPress Configuration - Environment and i18n configuration for ReactPress",
55
"author": "fecommunity",
66
"main": "./lib/index.js",

config/src/env.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,23 @@ interface EnvConfig {
99
config: Record<string, string>;
1010
}
1111

12+
// 获取项目根目录的函数
13+
function getProjectRoot(): string {
14+
// 优先使用通过环境变量传递的原始工作目录
15+
// 这是在 bin/reactpress-server.js 中设置的,表示用户执行 npx 命令的目录
16+
if (process.env.REACTPRESS_ORIGINAL_CWD) {
17+
return process.env.REACTPRESS_ORIGINAL_CWD;
18+
}
19+
20+
// 如果没有设置环境变量,则回退到当前工作目录
21+
return process.cwd();
22+
}
23+
1224
function parseEnv(): EnvConfig {
13-
// Try multiple possible paths for environment files
25+
// 使用改进的项目根目录查找
26+
const projectRoot = getProjectRoot();
1427
const possibleBasePaths = [
28+
projectRoot, // Project root directory
1529
path.resolve(__dirname, '../../'), // From config/lib to project root
1630
path.resolve(__dirname, '../../../'), // From node_modules to project root
1731
path.resolve(__dirname, '../'), // From client directory to project root

config/src/i18n.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,10 @@ function parseI18n(): I18nResult {
5858
}
5959

6060
function findProjectRoot(): string {
61-
// 查找项目根目录(包含package.json的目录)
62-
let currentDir = __dirname;
63-
64-
// 向上查找最多10层目录
65-
for (let i = 0; i < 10; i++) {
66-
const packageJsonPath = path.join(currentDir, 'package.json');
67-
if (fs.existsSync(packageJsonPath)) {
68-
try {
69-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
70-
// 检查是否是主项目package.json
71-
if (packageJson.name === 'reactpress' || packageJson.workspaces) {
72-
return currentDir;
73-
}
74-
} catch (e) {
75-
// 解析失败,继续向上查找
76-
}
77-
}
78-
const parentDir = path.dirname(currentDir);
79-
// 如果已经到达文件系统根目录,停止查找
80-
if (parentDir === currentDir) {
81-
break;
82-
}
83-
currentDir = parentDir;
61+
// 优先使用通过环境变量传递的原始工作目录
62+
// 这是在 bin/reactpress-server.js 或 client/server.js 中设置的,表示用户执行命令的目录
63+
if (process.env.REACTPRESS_ORIGINAL_CWD) {
64+
return process.env.REACTPRESS_ORIGINAL_CWD;
8465
}
8566

8667
// 如果找不到项目根目录,返回当前工作目录

0 commit comments

Comments
 (0)