hadars 0.1.26 → 0.1.27
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/dist/cli.js +27 -5
- package/dist/index.d.ts +18 -0
- package/dist/ssr-watch.js +25 -5
- package/package.json +1 -1
- package/src/build.ts +3 -1
- package/src/ssr-watch.ts +1 -1
- package/src/types/hadars.ts +18 -0
- package/src/utils/rspack.ts +37 -6
package/dist/cli.js
CHANGED
|
@@ -1138,13 +1138,33 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1138
1138
|
// and does not call React hooks, so it is safe to leave as external.
|
|
1139
1139
|
"@emotion/server"
|
|
1140
1140
|
] : void 0;
|
|
1141
|
+
const effectiveReactDev = isServerBuild ? false : opts.reactMode === "development" ? true : opts.reactMode === "production" ? false : isDev;
|
|
1142
|
+
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
1143
|
+
const rules = localConfig.module?.rules ?? [];
|
|
1144
|
+
for (const rule of rules) {
|
|
1145
|
+
if (!rule?.use || !Array.isArray(rule.use))
|
|
1146
|
+
continue;
|
|
1147
|
+
for (const entry2 of rule.use) {
|
|
1148
|
+
if (entry2?.loader?.includes("swc-loader")) {
|
|
1149
|
+
entry2.options = entry2.options ?? {};
|
|
1150
|
+
entry2.options.jsc = entry2.options.jsc ?? {};
|
|
1151
|
+
entry2.options.jsc.transform = entry2.options.jsc.transform ?? {};
|
|
1152
|
+
entry2.options.jsc.transform.react = entry2.options.jsc.transform.react ?? {};
|
|
1153
|
+
entry2.options.jsc.transform.react.development = effectiveReactDev;
|
|
1154
|
+
entry2.options.jsc.transform.react.refresh = effectiveReactDev && isDev;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1141
1159
|
const extraPlugins = [];
|
|
1142
|
-
|
|
1160
|
+
const defineValues = { ...opts.define ?? {} };
|
|
1161
|
+
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
1162
|
+
defineValues["process.env.NODE_ENV"] = JSON.stringify(opts.reactMode);
|
|
1163
|
+
}
|
|
1164
|
+
if (Object.keys(defineValues).length > 0) {
|
|
1143
1165
|
const DefinePlugin = rspack.DefinePlugin || rspack.plugins?.DefinePlugin;
|
|
1144
1166
|
if (DefinePlugin) {
|
|
1145
|
-
extraPlugins.push(new DefinePlugin(
|
|
1146
|
-
} else {
|
|
1147
|
-
extraPlugins.push({ name: "DefinePlugin", value: opts.define });
|
|
1167
|
+
extraPlugins.push(new DefinePlugin(defineValues));
|
|
1148
1168
|
}
|
|
1149
1169
|
}
|
|
1150
1170
|
const resolveConfig = {
|
|
@@ -1875,6 +1895,7 @@ var dev = async (options) => {
|
|
|
1875
1895
|
swcPlugins: options.swcPlugins,
|
|
1876
1896
|
define: options.define,
|
|
1877
1897
|
moduleRules: options.moduleRules,
|
|
1898
|
+
reactMode: options.reactMode,
|
|
1878
1899
|
htmlTemplate: resolvedHtmlTemplate
|
|
1879
1900
|
});
|
|
1880
1901
|
const devServer = new RspackDevServer({
|
|
@@ -1912,7 +1933,7 @@ var dev = async (options) => {
|
|
|
1912
1933
|
`--base=${baseURL}`,
|
|
1913
1934
|
...options.swcPlugins ? [`--swcPlugins=${JSON.stringify(options.swcPlugins)}`] : [],
|
|
1914
1935
|
...options.define ? [`--define=${JSON.stringify(options.define)}`] : [],
|
|
1915
|
-
...options.moduleRules ? [`--moduleRules=${JSON.stringify(options.moduleRules)}`] : []
|
|
1936
|
+
...options.moduleRules ? [`--moduleRules=${JSON.stringify(options.moduleRules, (_k, v) => v instanceof RegExp ? { __re: v.source, __flags: v.flags } : v)}`] : []
|
|
1916
1937
|
], { stdio: "pipe" });
|
|
1917
1938
|
child.stdin?.end();
|
|
1918
1939
|
const cleanupChild = () => {
|
|
@@ -2094,6 +2115,7 @@ var build = async (options) => {
|
|
|
2094
2115
|
define: options.define,
|
|
2095
2116
|
moduleRules: options.moduleRules,
|
|
2096
2117
|
optimization: options.optimization,
|
|
2118
|
+
reactMode: options.reactMode,
|
|
2097
2119
|
htmlTemplate: resolvedHtmlTemplate
|
|
2098
2120
|
}),
|
|
2099
2121
|
compileEntry(pathMod2.resolve(__dirname2, options.entry), {
|
package/dist/index.d.ts
CHANGED
|
@@ -111,6 +111,24 @@ interface HadarsOptions {
|
|
|
111
111
|
* Note: inline styles are processed once at startup and are not live-reloaded.
|
|
112
112
|
*/
|
|
113
113
|
htmlTemplate?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Force the React runtime mode independently of the build mode.
|
|
116
|
+
* Useful when you need production build optimizations (minification, tree-shaking)
|
|
117
|
+
* but want React's development build for debugging hydration mismatches or
|
|
118
|
+
* component stack traces.
|
|
119
|
+
*
|
|
120
|
+
* - `'development'` — forces `process.env.NODE_ENV = "development"` and enables
|
|
121
|
+
* JSX source info even in `hadars build`. React prints detailed hydration error
|
|
122
|
+
* messages and component stacks.
|
|
123
|
+
* - `'production'` — the default; React uses the optimised production bundle.
|
|
124
|
+
*
|
|
125
|
+
* Only affects the **client** bundle. The SSR bundle always uses slim-react.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* // hadars.config.ts — debug hydration errors in a production build
|
|
129
|
+
* reactMode: 'development'
|
|
130
|
+
*/
|
|
131
|
+
reactMode?: 'development' | 'production';
|
|
114
132
|
/**
|
|
115
133
|
* Additional rspack module rules appended to the built-in rule set.
|
|
116
134
|
* Applied to both the client and the SSR bundle.
|
package/dist/ssr-watch.js
CHANGED
|
@@ -188,13 +188,33 @@ var buildCompilerConfig = (entry2, opts, includeHotPlugin) => {
|
|
|
188
188
|
// and does not call React hooks, so it is safe to leave as external.
|
|
189
189
|
"@emotion/server"
|
|
190
190
|
] : void 0;
|
|
191
|
+
const effectiveReactDev = isServerBuild ? false : opts.reactMode === "development" ? true : opts.reactMode === "production" ? false : isDev;
|
|
192
|
+
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
193
|
+
const rules = localConfig.module?.rules ?? [];
|
|
194
|
+
for (const rule of rules) {
|
|
195
|
+
if (!rule?.use || !Array.isArray(rule.use))
|
|
196
|
+
continue;
|
|
197
|
+
for (const entry3 of rule.use) {
|
|
198
|
+
if (entry3?.loader?.includes("swc-loader")) {
|
|
199
|
+
entry3.options = entry3.options ?? {};
|
|
200
|
+
entry3.options.jsc = entry3.options.jsc ?? {};
|
|
201
|
+
entry3.options.jsc.transform = entry3.options.jsc.transform ?? {};
|
|
202
|
+
entry3.options.jsc.transform.react = entry3.options.jsc.transform.react ?? {};
|
|
203
|
+
entry3.options.jsc.transform.react.development = effectiveReactDev;
|
|
204
|
+
entry3.options.jsc.transform.react.refresh = effectiveReactDev && isDev;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
191
209
|
const extraPlugins = [];
|
|
192
|
-
|
|
210
|
+
const defineValues = { ...opts.define ?? {} };
|
|
211
|
+
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
212
|
+
defineValues["process.env.NODE_ENV"] = JSON.stringify(opts.reactMode);
|
|
213
|
+
}
|
|
214
|
+
if (Object.keys(defineValues).length > 0) {
|
|
193
215
|
const DefinePlugin = rspack.DefinePlugin || rspack.plugins?.DefinePlugin;
|
|
194
216
|
if (DefinePlugin) {
|
|
195
|
-
extraPlugins.push(new DefinePlugin(
|
|
196
|
-
} else {
|
|
197
|
-
extraPlugins.push({ name: "DefinePlugin", value: opts.define });
|
|
217
|
+
extraPlugins.push(new DefinePlugin(defineValues));
|
|
198
218
|
}
|
|
199
219
|
}
|
|
200
220
|
const resolveConfig = {
|
|
@@ -354,7 +374,7 @@ var outFile = argv["outFile"] || "index.ssr.js";
|
|
|
354
374
|
var base = argv["base"] || "";
|
|
355
375
|
var swcPlugins = argv["swcPlugins"] ? JSON.parse(argv["swcPlugins"]) : void 0;
|
|
356
376
|
var define = argv["define"] ? JSON.parse(argv["define"]) : void 0;
|
|
357
|
-
var moduleRules = argv["moduleRules"] ? JSON.parse(argv["moduleRules"]) : void 0;
|
|
377
|
+
var moduleRules = argv["moduleRules"] ? JSON.parse(argv["moduleRules"], (_k, v) => v && typeof v === "object" && "__re" in v ? new RegExp(v.__re, v.__flags) : v) : void 0;
|
|
358
378
|
if (!entry) {
|
|
359
379
|
console.error("ssr-watch: missing --entry argument");
|
|
360
380
|
process.exit(1);
|
package/package.json
CHANGED
package/src/build.ts
CHANGED
|
@@ -508,6 +508,7 @@ export const dev = async (options: HadarsRuntimeOptions) => {
|
|
|
508
508
|
swcPlugins: options.swcPlugins,
|
|
509
509
|
define: options.define,
|
|
510
510
|
moduleRules: options.moduleRules,
|
|
511
|
+
reactMode: options.reactMode,
|
|
511
512
|
htmlTemplate: resolvedHtmlTemplate,
|
|
512
513
|
});
|
|
513
514
|
|
|
@@ -555,7 +556,7 @@ export const dev = async (options: HadarsRuntimeOptions) => {
|
|
|
555
556
|
`--base=${baseURL}`,
|
|
556
557
|
...(options.swcPlugins ? [`--swcPlugins=${JSON.stringify(options.swcPlugins)}`] : []),
|
|
557
558
|
...(options.define ? [`--define=${JSON.stringify(options.define)}`] : []),
|
|
558
|
-
...(options.moduleRules ? [`--moduleRules=${JSON.stringify(options.moduleRules)}`] : []),
|
|
559
|
+
...(options.moduleRules ? [`--moduleRules=${JSON.stringify(options.moduleRules, (_k, v) => v instanceof RegExp ? { __re: v.source, __flags: v.flags } : v)}`] : []),
|
|
559
560
|
], { stdio: 'pipe' });
|
|
560
561
|
child.stdin?.end();
|
|
561
562
|
|
|
@@ -751,6 +752,7 @@ export const build = async (options: HadarsRuntimeOptions) => {
|
|
|
751
752
|
define: options.define,
|
|
752
753
|
moduleRules: options.moduleRules,
|
|
753
754
|
optimization: options.optimization,
|
|
755
|
+
reactMode: options.reactMode,
|
|
754
756
|
htmlTemplate: resolvedHtmlTemplate,
|
|
755
757
|
}),
|
|
756
758
|
compileEntry(pathMod.resolve(__dirname, options.entry), {
|
package/src/ssr-watch.ts
CHANGED
|
@@ -21,7 +21,7 @@ const outFile = argv['outFile'] || 'index.ssr.js';
|
|
|
21
21
|
const base = argv['base'] || '';
|
|
22
22
|
const swcPlugins = argv['swcPlugins'] ? JSON.parse(argv['swcPlugins']) : undefined;
|
|
23
23
|
const define = argv['define'] ? JSON.parse(argv['define']) : undefined;
|
|
24
|
-
const moduleRules = argv['moduleRules'] ? JSON.parse(argv['moduleRules']) : undefined;
|
|
24
|
+
const moduleRules = argv['moduleRules'] ? JSON.parse(argv['moduleRules'], (_k, v) => (v && typeof v === 'object' && '__re' in v) ? new RegExp(v.__re, v.__flags) : v) : undefined;
|
|
25
25
|
|
|
26
26
|
if (!entry) {
|
|
27
27
|
console.error('ssr-watch: missing --entry argument');
|
package/src/types/hadars.ts
CHANGED
|
@@ -111,6 +111,24 @@ export interface HadarsOptions {
|
|
|
111
111
|
* Note: inline styles are processed once at startup and are not live-reloaded.
|
|
112
112
|
*/
|
|
113
113
|
htmlTemplate?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Force the React runtime mode independently of the build mode.
|
|
116
|
+
* Useful when you need production build optimizations (minification, tree-shaking)
|
|
117
|
+
* but want React's development build for debugging hydration mismatches or
|
|
118
|
+
* component stack traces.
|
|
119
|
+
*
|
|
120
|
+
* - `'development'` — forces `process.env.NODE_ENV = "development"` and enables
|
|
121
|
+
* JSX source info even in `hadars build`. React prints detailed hydration error
|
|
122
|
+
* messages and component stacks.
|
|
123
|
+
* - `'production'` — the default; React uses the optimised production bundle.
|
|
124
|
+
*
|
|
125
|
+
* Only affects the **client** bundle. The SSR bundle always uses slim-react.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* // hadars.config.ts — debug hydration errors in a production build
|
|
129
|
+
* reactMode: 'development'
|
|
130
|
+
*/
|
|
131
|
+
reactMode?: 'development' | 'production';
|
|
114
132
|
/**
|
|
115
133
|
* Additional rspack module rules appended to the built-in rule set.
|
|
116
134
|
* Applied to both the client and the SSR bundle.
|
package/src/utils/rspack.ts
CHANGED
|
@@ -134,6 +134,8 @@ interface EntryOptions {
|
|
|
134
134
|
optimization?: Record<string, unknown>;
|
|
135
135
|
// additional module rules appended after the built-in rules
|
|
136
136
|
moduleRules?: Record<string, any>[];
|
|
137
|
+
// force React runtime mode independently of build mode (client only)
|
|
138
|
+
reactMode?: 'development' | 'production';
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
const buildCompilerConfig = (
|
|
@@ -232,15 +234,44 @@ const buildCompilerConfig = (
|
|
|
232
234
|
'@emotion/server',
|
|
233
235
|
] : undefined;
|
|
234
236
|
|
|
237
|
+
// reactMode lets the caller force React's dev/prod runtime independently of
|
|
238
|
+
// the webpack build mode. Only applies to the client bundle (SSR uses slim-react).
|
|
239
|
+
// 'development' → process.env.NODE_ENV = "development" + JSX dev transform.
|
|
240
|
+
const effectiveReactDev = isServerBuild
|
|
241
|
+
? false // slim-react doesn't use NODE_ENV
|
|
242
|
+
: opts.reactMode === 'development' ? true
|
|
243
|
+
: opts.reactMode === 'production' ? false
|
|
244
|
+
: isDev; // default: follow build mode
|
|
245
|
+
|
|
246
|
+
if (!isServerBuild && opts.reactMode !== undefined) {
|
|
247
|
+
// Override the SWC JSX development flag for all js/ts rules already built
|
|
248
|
+
const rules = localConfig.module?.rules ?? [];
|
|
249
|
+
for (const rule of rules) {
|
|
250
|
+
if (!rule?.use || !Array.isArray(rule.use)) continue;
|
|
251
|
+
for (const entry of rule.use) {
|
|
252
|
+
if (entry?.loader?.includes('swc-loader')) {
|
|
253
|
+
entry.options = entry.options ?? {};
|
|
254
|
+
entry.options.jsc = entry.options.jsc ?? {};
|
|
255
|
+
entry.options.jsc.transform = entry.options.jsc.transform ?? {};
|
|
256
|
+
entry.options.jsc.transform.react = entry.options.jsc.transform.react ?? {};
|
|
257
|
+
entry.options.jsc.transform.react.development = effectiveReactDev;
|
|
258
|
+
entry.options.jsc.transform.react.refresh = effectiveReactDev && isDev;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
235
264
|
const extraPlugins: any[] = [];
|
|
236
|
-
|
|
237
|
-
|
|
265
|
+
const defineValues: Record<string, string> = { ...(opts.define ?? {}) };
|
|
266
|
+
// When reactMode overrides the React runtime we must also set process.env.NODE_ENV
|
|
267
|
+
// so React picks its dev/prod bundle, independently of the rspack build mode.
|
|
268
|
+
if (!isServerBuild && opts.reactMode !== undefined) {
|
|
269
|
+
defineValues['process.env.NODE_ENV'] = JSON.stringify(opts.reactMode);
|
|
270
|
+
}
|
|
271
|
+
if (Object.keys(defineValues).length > 0) {
|
|
238
272
|
const DefinePlugin = (rspack as any).DefinePlugin || (rspack as any).plugins?.DefinePlugin;
|
|
239
273
|
if (DefinePlugin) {
|
|
240
|
-
extraPlugins.push(new DefinePlugin(
|
|
241
|
-
} else {
|
|
242
|
-
// fallback: try to inject via plugin API name
|
|
243
|
-
extraPlugins.push({ name: 'DefinePlugin', value: opts.define });
|
|
274
|
+
extraPlugins.push(new DefinePlugin(defineValues));
|
|
244
275
|
}
|
|
245
276
|
}
|
|
246
277
|
|