react-client 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli/commands/dev.js +32 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ npm install
|
|
|
35
35
|
npm run dev
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
This launches the **custom dev server** —
|
|
38
|
+
This launches the **custom dev server** — built on **Connect + WebSocket + esbuild**, featuring:
|
|
39
39
|
- Instant rebuilds
|
|
40
40
|
- React Fast Refresh (HMR)
|
|
41
41
|
- Auto port detection & confirmation prompt
|
|
@@ -85,9 +85,9 @@ Each template is pre-configured for esbuild, HMR, and fast bootstrapping.
|
|
|
85
85
|
|
|
86
86
|
## 💎 Core Features
|
|
87
87
|
|
|
88
|
-
- ⚡ **Custom Dev Server
|
|
88
|
+
- ⚡ **Custom Dev Server** — Connect + WebSocket + esbuild
|
|
89
89
|
- 🔁 **React Fast Refresh (HMR)** — State-preserving reloads
|
|
90
|
-
- 💥 **
|
|
90
|
+
- 💥 **Overlay** — Syntax-highlighted stack frames, clickable file links (`vscode://file`)
|
|
91
91
|
- 🔍 **Source Map Stack Mapping** — Maps runtime errors to original TS/JS source lines
|
|
92
92
|
- 💬 **Auto Port Detection** — Prompts when default port 5173 is occupied
|
|
93
93
|
- 🧠 **Smart Config Loader** — Detects project root, compiles `.ts` configs dynamically
|
package/dist/cli/commands/dev.js
CHANGED
|
@@ -19,7 +19,7 @@ const child_process_1 = require("child_process");
|
|
|
19
19
|
const chalk_1 = __importDefault(require("chalk"));
|
|
20
20
|
async function dev() {
|
|
21
21
|
const root = process.cwd();
|
|
22
|
-
// 🧩 Load config
|
|
22
|
+
// 🧩 Load user config
|
|
23
23
|
const userConfig = await (0, loadConfig_1.loadReactClientConfig)(root);
|
|
24
24
|
const appRoot = path_1.default.resolve(root, userConfig.root || '.');
|
|
25
25
|
const defaultPort = userConfig.server?.port || 5173;
|
|
@@ -33,7 +33,7 @@ async function dev() {
|
|
|
33
33
|
}
|
|
34
34
|
const indexHtml = path_1.default.join(appRoot, 'index.html');
|
|
35
35
|
await fs_extra_1.default.ensureDir(outDir);
|
|
36
|
-
//
|
|
36
|
+
// ⚙️ Detect open port
|
|
37
37
|
const availablePort = await (0, detect_port_1.default)(defaultPort);
|
|
38
38
|
const port = availablePort;
|
|
39
39
|
if (availablePort !== defaultPort) {
|
|
@@ -73,7 +73,7 @@ async function dev() {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
const reactRefreshRuntime = safeResolveReactRefresh();
|
|
76
|
-
// 🏗️ esbuild context
|
|
76
|
+
// 🏗️ Create esbuild context
|
|
77
77
|
const ctx = await esbuild_1.default.context({
|
|
78
78
|
entryPoints: [entry],
|
|
79
79
|
bundle: true,
|
|
@@ -88,7 +88,7 @@ async function dev() {
|
|
|
88
88
|
console.log(chalk_1.default.gray('📦 Watching and building dev bundle...'));
|
|
89
89
|
console.log(chalk_1.default.gray(' Output dir:'), chalk_1.default.blue(outDir));
|
|
90
90
|
console.log(chalk_1.default.gray(' Entry file:'), chalk_1.default.yellow(entry));
|
|
91
|
-
// 🌐
|
|
91
|
+
// 🌐 Connect server setup
|
|
92
92
|
const app = (0, connect_1.default)();
|
|
93
93
|
// 🛡 Security headers
|
|
94
94
|
app.use((_req, res, next) => {
|
|
@@ -96,11 +96,12 @@ async function dev() {
|
|
|
96
96
|
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
|
|
97
97
|
next();
|
|
98
98
|
});
|
|
99
|
+
// 🧠 In-memory cache for /@modules
|
|
100
|
+
const moduleCache = new Map();
|
|
99
101
|
// 1️⃣ Serve react-refresh runtime with safe browser shim
|
|
100
102
|
app.use('/@react-refresh', async (_req, res) => {
|
|
101
103
|
const runtime = await fs_extra_1.default.readFile(reactRefreshRuntime, 'utf8');
|
|
102
104
|
const shim = `
|
|
103
|
-
// React Refresh browser shims
|
|
104
105
|
window.process = window.process || { env: { NODE_ENV: 'development' } };
|
|
105
106
|
window.module = { exports: {} };
|
|
106
107
|
window.global = window;
|
|
@@ -109,31 +110,43 @@ async function dev() {
|
|
|
109
110
|
res.setHeader('Content-Type', 'application/javascript');
|
|
110
111
|
res.end(shim + '\n' + runtime);
|
|
111
112
|
});
|
|
112
|
-
// 2️⃣
|
|
113
|
+
// 2️⃣ Bare module resolver with memory cache
|
|
113
114
|
app.use('/@modules/', async (req, res, next) => {
|
|
114
|
-
|
|
115
|
+
let id = req.url?.replace(/^\/@modules\//, '');
|
|
115
116
|
if (!id)
|
|
116
117
|
return next();
|
|
118
|
+
// 🧩 Normalize: remove leading slashes that may appear (e.g. "/react")
|
|
119
|
+
id = id.replace(/^\/+/, '');
|
|
120
|
+
if (!id)
|
|
121
|
+
return next();
|
|
122
|
+
if (moduleCache.has(id)) {
|
|
123
|
+
res.setHeader('Content-Type', 'application/javascript');
|
|
124
|
+
res.end(moduleCache.get(id));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
117
127
|
try {
|
|
118
|
-
const
|
|
128
|
+
const entryPath = require.resolve(id, { paths: [appRoot] });
|
|
119
129
|
const out = await esbuild_1.default.build({
|
|
120
|
-
entryPoints: [
|
|
130
|
+
entryPoints: [entryPath],
|
|
121
131
|
bundle: true,
|
|
122
132
|
write: false,
|
|
123
133
|
platform: 'browser',
|
|
124
134
|
format: 'esm',
|
|
125
135
|
target: 'es2020',
|
|
126
136
|
});
|
|
137
|
+
const code = out.outputFiles[0].text;
|
|
138
|
+
moduleCache.set(id, code); // ✅ cache module
|
|
127
139
|
res.setHeader('Content-Type', 'application/javascript');
|
|
128
|
-
res.end(
|
|
140
|
+
res.end(code);
|
|
129
141
|
}
|
|
130
142
|
catch (err) {
|
|
131
|
-
|
|
143
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
144
|
+
console.error(chalk_1.default.red(`Failed to resolve module ${id}: ${msg}`));
|
|
132
145
|
res.writeHead(500);
|
|
133
146
|
res.end(`// Could not resolve module ${id}`);
|
|
134
147
|
}
|
|
135
148
|
});
|
|
136
|
-
// 3️⃣ Serve /src/* files
|
|
149
|
+
// 3️⃣ Serve /src/* files — on-the-fly transform + bare import rewrite
|
|
137
150
|
app.use(async (req, res, next) => {
|
|
138
151
|
if (!req.url || !req.url.startsWith('/src/'))
|
|
139
152
|
return next();
|
|
@@ -141,8 +154,11 @@ async function dev() {
|
|
|
141
154
|
const filePath = path_1.default.join(appRoot, decodeURIComponent(req.url.split('?')[0]));
|
|
142
155
|
if (!(await fs_extra_1.default.pathExists(filePath)))
|
|
143
156
|
return next();
|
|
144
|
-
|
|
157
|
+
let code = await fs_extra_1.default.readFile(filePath, 'utf8');
|
|
145
158
|
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
159
|
+
// 🪄 Rewrite bare imports → /@modules/
|
|
160
|
+
// 🧩 Rewrite *only bare imports* like "react", not "./" or "/" or "../"
|
|
161
|
+
code = code.replace(/from\s+['"]((?![\.\/])[a-zA-Z0-9@/_-]+)['"]/g, (_match, dep) => `from "/@modules/${dep}"`);
|
|
146
162
|
let loader = 'js';
|
|
147
163
|
if (ext === '.ts')
|
|
148
164
|
loader = 'ts';
|
|
@@ -163,7 +179,7 @@ async function dev() {
|
|
|
163
179
|
}
|
|
164
180
|
catch (err) {
|
|
165
181
|
const msg = err instanceof Error ? err.message : String(err);
|
|
166
|
-
console.error('Error serving src file:', msg);
|
|
182
|
+
console.error('Error serving /src file:', msg);
|
|
167
183
|
res.writeHead(500);
|
|
168
184
|
res.end(`// Error: ${msg}`);
|
|
169
185
|
}
|
|
@@ -214,7 +230,7 @@ async function dev() {
|
|
|
214
230
|
next();
|
|
215
231
|
}
|
|
216
232
|
});
|
|
217
|
-
// 🔁 HMR
|
|
233
|
+
// 🔁 HMR WebSocket server
|
|
218
234
|
const server = http_1.default.createServer(app);
|
|
219
235
|
const wss = new ws_1.WebSocketServer({ server });
|
|
220
236
|
const broadcast = (data) => {
|
|
@@ -236,6 +252,7 @@ async function dev() {
|
|
|
236
252
|
}
|
|
237
253
|
}
|
|
238
254
|
});
|
|
255
|
+
// 🟢 Start server
|
|
239
256
|
server.listen(port, async () => {
|
|
240
257
|
const url = `http://localhost:${port}`;
|
|
241
258
|
console.log(chalk_1.default.cyan.bold(`\n🚀 React Client Dev Server`));
|