hadars 0.1.36 → 0.1.38
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/cli-lib.ts +18 -10
- package/dist/{chunk-OID7K4D3.js → chunk-F7IIMM3J.js} +7 -7
- package/dist/{chunk-OZUZS2PD.js → chunk-OS3V4CPN.js} +4 -4
- package/dist/cli.js +44 -13
- package/dist/{hadars-ScRgKezP.d.cts → hadars-B3b_6sj2.d.cts} +12 -0
- package/dist/{hadars-ScRgKezP.d.ts → hadars-B3b_6sj2.d.ts} +12 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/lambda.cjs +28 -28
- package/dist/lambda.d.cts +1 -1
- package/dist/lambda.d.ts +1 -1
- package/dist/lambda.js +24 -24
- package/dist/slim-react/index.cjs +10 -10
- package/dist/slim-react/index.js +2 -2
- package/dist/slim-react/jsx-runtime.cjs +4 -2
- package/dist/slim-react/jsx-runtime.js +1 -1
- package/dist/ssr-watch.js +25 -1
- package/package.json +2 -2
- package/src/build.ts +3 -0
- package/src/lambda.ts +24 -5
- package/src/types/hadars.ts +10 -0
- package/src/utils/rspack.ts +36 -0
- package/src/utils/ssrHandler.ts +21 -0
package/cli-lib.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
2
|
import { mkdir, writeFile, unlink } from 'node:fs/promises'
|
|
3
3
|
import { resolve, join, dirname } from 'node:path'
|
|
4
|
-
import {
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
5
|
import * as Hadars from './src/build'
|
|
6
6
|
import type { HadarsOptions } from './src/types/hadars'
|
|
7
7
|
|
|
@@ -70,11 +70,16 @@ async function bundleLambda(
|
|
|
70
70
|
|
|
71
71
|
// 3. Write a temporary entry shim that statically imports the SSR module
|
|
72
72
|
// and the HTML template so esbuild can inline both.
|
|
73
|
-
|
|
73
|
+
// Write the shim inside cwd so esbuild's module resolution finds local
|
|
74
|
+
// node_modules when walking up from the shim's directory.
|
|
75
|
+
// Use the absolute path to lambda.js (sibling of the CLI in dist/) so the
|
|
76
|
+
// shim doesn't depend on package name resolution at all.
|
|
77
|
+
const lambdaModule = resolve(dirname(fileURLToPath(import.meta.url)), 'lambda.js')
|
|
78
|
+
const shimPath = join(cwd, `.hadars-lambda-shim-${Date.now()}.ts`)
|
|
74
79
|
const shim = [
|
|
75
80
|
`import * as ssrModule from ${JSON.stringify(ssrBundle)};`,
|
|
76
81
|
`import outHtml from ${JSON.stringify(outHtml)};`,
|
|
77
|
-
`import { createLambdaHandler } from
|
|
82
|
+
`import { createLambdaHandler } from ${JSON.stringify(lambdaModule)};`,
|
|
78
83
|
`import config from ${JSON.stringify(configPath)};`,
|
|
79
84
|
`export const handler = createLambdaHandler(config as any, { ssrModule: ssrModule as any, outHtml });`,
|
|
80
85
|
].join('\n') + '\n'
|
|
@@ -93,16 +98,19 @@ async function bundleLambda(
|
|
|
93
98
|
outfile: outputFile,
|
|
94
99
|
sourcemap: false,
|
|
95
100
|
loader: { '.html': 'text', '.tsx': 'tsx', '.ts': 'ts' },
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
//
|
|
99
|
-
|
|
101
|
+
// @rspack/* contains native binaries and is build-time only —
|
|
102
|
+
// it is never imported at Lambda runtime, so mark it external.
|
|
103
|
+
// Everything else (React, hadars runtime, etc.) is bundled in to
|
|
104
|
+
// produce a truly self-contained single-file deployment.
|
|
105
|
+
external: ['@rspack/*'],
|
|
100
106
|
})
|
|
101
107
|
console.log(`Lambda bundle written to ${outputFile}`)
|
|
102
108
|
console.log(`\nDeploy instructions:`)
|
|
103
|
-
console.log(` 1.
|
|
104
|
-
console.log(`
|
|
105
|
-
console.log(`
|
|
109
|
+
console.log(` 1. Create a staging directory with just this file:`)
|
|
110
|
+
console.log(` mkdir -p lambda-deploy && cp ${outputFile} lambda-deploy/lambda.mjs`)
|
|
111
|
+
console.log(` 2. Upload lambda-deploy/ as your Lambda function code`)
|
|
112
|
+
console.log(` 3. Set handler to: lambda.handler (runtime: Node.js 20.x)`)
|
|
113
|
+
console.log(` 4. Upload .hadars/static/ assets to S3 and serve via CloudFront`)
|
|
106
114
|
console.log(` (the Lambda handler does not serve static JS/CSS — route those to S3)`)
|
|
107
115
|
} finally {
|
|
108
116
|
await unlink(shimPath).catch(() => {})
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
SLIM_ELEMENT,
|
|
6
6
|
SUSPENSE_TYPE,
|
|
7
7
|
createElement
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-OS3V4CPN.js";
|
|
9
9
|
|
|
10
10
|
// src/slim-react/renderContext.ts
|
|
11
11
|
var MAP_KEY = "__slimReactContextMap";
|
|
@@ -577,12 +577,12 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
577
577
|
}
|
|
578
578
|
writer.write(`</${tag}>`);
|
|
579
579
|
}
|
|
580
|
-
var REACT_MEMO =
|
|
581
|
-
var REACT_FORWARD_REF =
|
|
582
|
-
var REACT_PROVIDER =
|
|
583
|
-
var REACT_CONTEXT =
|
|
584
|
-
var REACT_CONSUMER =
|
|
585
|
-
var REACT_LAZY =
|
|
580
|
+
var REACT_MEMO = Symbol.for("react.memo");
|
|
581
|
+
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
582
|
+
var REACT_PROVIDER = Symbol.for("react.provider");
|
|
583
|
+
var REACT_CONTEXT = Symbol.for("react.context");
|
|
584
|
+
var REACT_CONSUMER = Symbol.for("react.consumer");
|
|
585
|
+
var REACT_LAZY = Symbol.for("react.lazy");
|
|
586
586
|
function renderComponent(type, props, writer, isSvg) {
|
|
587
587
|
const typeOf = type?.$$typeof;
|
|
588
588
|
if (typeOf === REACT_MEMO) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/slim-react/types.ts
|
|
2
|
-
var SLIM_ELEMENT =
|
|
3
|
-
var REACT19_ELEMENT =
|
|
4
|
-
var FRAGMENT_TYPE =
|
|
5
|
-
var SUSPENSE_TYPE =
|
|
2
|
+
var SLIM_ELEMENT = Symbol.for("react.element");
|
|
3
|
+
var REACT19_ELEMENT = Symbol.for("react.transitional.element");
|
|
4
|
+
var FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
5
|
+
var SUSPENSE_TYPE = Symbol.for("react.suspense");
|
|
6
6
|
|
|
7
7
|
// src/slim-react/jsx.ts
|
|
8
8
|
var Fragment = FRAGMENT_TYPE;
|
package/dist/cli.js
CHANGED
|
@@ -6,8 +6,8 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
6
6
|
// cli-lib.ts
|
|
7
7
|
import { existsSync as existsSync3 } from "node:fs";
|
|
8
8
|
import { mkdir, writeFile, unlink } from "node:fs/promises";
|
|
9
|
-
import { resolve, join } from "node:path";
|
|
10
|
-
import {
|
|
9
|
+
import { resolve, join, dirname } from "node:path";
|
|
10
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
11
11
|
|
|
12
12
|
// src/utils/proxyHandler.tsx
|
|
13
13
|
var cloneHeaders = (headers) => {
|
|
@@ -1307,6 +1307,29 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1307
1307
|
}
|
|
1308
1308
|
}
|
|
1309
1309
|
const extraPlugins = [];
|
|
1310
|
+
if (!isServerBuild) {
|
|
1311
|
+
extraPlugins.push({
|
|
1312
|
+
apply(compiler) {
|
|
1313
|
+
compiler.hooks.compilation.tap("HadarsWorkerChunkLoading", (compilation) => {
|
|
1314
|
+
compilation.hooks.childCompiler.tap(
|
|
1315
|
+
"HadarsWorkerChunkLoading",
|
|
1316
|
+
(childCompiler) => {
|
|
1317
|
+
const libType = childCompiler.options?.output?.library?.type;
|
|
1318
|
+
if (libType === "module" || libType === "commonjs" || libType === "commonjs2") {
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
if (childCompiler.options?.output) {
|
|
1322
|
+
childCompiler.options.output.chunkLoading = "import-scripts";
|
|
1323
|
+
}
|
|
1324
|
+
if (childCompiler.options?.experiments) {
|
|
1325
|
+
childCompiler.options.experiments.outputModule = false;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
);
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1310
1333
|
const defineValues = { ...opts.define ?? {} };
|
|
1311
1334
|
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
1312
1335
|
defineValues["process.env.NODE_ENV"] = JSON.stringify(opts.reactMode);
|
|
@@ -1383,7 +1406,8 @@ var buildCompilerConfig = (entry, opts, includeHotPlugin) => {
|
|
|
1383
1406
|
},
|
|
1384
1407
|
isDev && !isServerBuild && new ReactRefreshPlugin(),
|
|
1385
1408
|
includeHotPlugin && isDev && !isServerBuild && new rspack.HotModuleReplacementPlugin(),
|
|
1386
|
-
...extraPlugins
|
|
1409
|
+
...extraPlugins,
|
|
1410
|
+
...opts.plugins ?? []
|
|
1387
1411
|
],
|
|
1388
1412
|
...localConfig,
|
|
1389
1413
|
// Merge base resolve (modules, tsConfig, extensions) with per-build resolve
|
|
@@ -1983,6 +2007,7 @@ var dev = async (options) => {
|
|
|
1983
2007
|
swcPlugins: options.swcPlugins,
|
|
1984
2008
|
define: options.define,
|
|
1985
2009
|
moduleRules: options.moduleRules,
|
|
2010
|
+
plugins: options.plugins,
|
|
1986
2011
|
reactMode: options.reactMode,
|
|
1987
2012
|
htmlTemplate: resolvedHtmlTemplate
|
|
1988
2013
|
});
|
|
@@ -2201,6 +2226,7 @@ var build = async (options) => {
|
|
|
2201
2226
|
swcPlugins: options.swcPlugins,
|
|
2202
2227
|
define: options.define,
|
|
2203
2228
|
moduleRules: options.moduleRules,
|
|
2229
|
+
plugins: options.plugins,
|
|
2204
2230
|
optimization: options.optimization,
|
|
2205
2231
|
reactMode: options.reactMode,
|
|
2206
2232
|
htmlTemplate: resolvedHtmlTemplate
|
|
@@ -2218,7 +2244,8 @@ var build = async (options) => {
|
|
|
2218
2244
|
mode: "production",
|
|
2219
2245
|
swcPlugins: options.swcPlugins,
|
|
2220
2246
|
define: options.define,
|
|
2221
|
-
moduleRules: options.moduleRules
|
|
2247
|
+
moduleRules: options.moduleRules,
|
|
2248
|
+
plugins: options.plugins
|
|
2222
2249
|
})
|
|
2223
2250
|
]);
|
|
2224
2251
|
await fs.rm(tmpFilePath);
|
|
@@ -2374,11 +2401,12 @@ async function bundleLambda(config, configPath, outputFile, cwd) {
|
|
|
2374
2401
|
console.error(`HTML template not found: ${outHtml}`);
|
|
2375
2402
|
process.exit(1);
|
|
2376
2403
|
}
|
|
2377
|
-
const
|
|
2404
|
+
const lambdaModule = resolve(dirname(fileURLToPath3(import.meta.url)), "lambda.js");
|
|
2405
|
+
const shimPath = join(cwd, `.hadars-lambda-shim-${Date.now()}.ts`);
|
|
2378
2406
|
const shim = [
|
|
2379
2407
|
`import * as ssrModule from ${JSON.stringify(ssrBundle)};`,
|
|
2380
2408
|
`import outHtml from ${JSON.stringify(outHtml)};`,
|
|
2381
|
-
`import { createLambdaHandler } from
|
|
2409
|
+
`import { createLambdaHandler } from ${JSON.stringify(lambdaModule)};`,
|
|
2382
2410
|
`import config from ${JSON.stringify(configPath)};`,
|
|
2383
2411
|
`export const handler = createLambdaHandler(config as any, { ssrModule: ssrModule as any, outHtml });`
|
|
2384
2412
|
].join("\n") + "\n";
|
|
@@ -2395,17 +2423,20 @@ async function bundleLambda(config, configPath, outputFile, cwd) {
|
|
|
2395
2423
|
outfile: outputFile,
|
|
2396
2424
|
sourcemap: false,
|
|
2397
2425
|
loader: { ".html": "text", ".tsx": "tsx", ".ts": "ts" },
|
|
2398
|
-
//
|
|
2399
|
-
|
|
2400
|
-
//
|
|
2401
|
-
|
|
2426
|
+
// @rspack/* contains native binaries and is build-time only —
|
|
2427
|
+
// it is never imported at Lambda runtime, so mark it external.
|
|
2428
|
+
// Everything else (React, hadars runtime, etc.) is bundled in to
|
|
2429
|
+
// produce a truly self-contained single-file deployment.
|
|
2430
|
+
external: ["@rspack/*"]
|
|
2402
2431
|
});
|
|
2403
2432
|
console.log(`Lambda bundle written to ${outputFile}`);
|
|
2404
2433
|
console.log(`
|
|
2405
2434
|
Deploy instructions:`);
|
|
2406
|
-
console.log(` 1.
|
|
2407
|
-
console.log(`
|
|
2408
|
-
console.log(`
|
|
2435
|
+
console.log(` 1. Create a staging directory with just this file:`);
|
|
2436
|
+
console.log(` mkdir -p lambda-deploy && cp ${outputFile} lambda-deploy/lambda.mjs`);
|
|
2437
|
+
console.log(` 2. Upload lambda-deploy/ as your Lambda function code`);
|
|
2438
|
+
console.log(` 3. Set handler to: lambda.handler (runtime: Node.js 20.x)`);
|
|
2439
|
+
console.log(` 4. Upload .hadars/static/ assets to S3 and serve via CloudFront`);
|
|
2409
2440
|
console.log(` (the Lambda handler does not serve static JS/CSS \u2014 route those to S3)`);
|
|
2410
2441
|
} finally {
|
|
2411
2442
|
await unlink(shimPath).catch(() => {
|
|
@@ -137,6 +137,18 @@ interface HadarsOptions {
|
|
|
137
137
|
* ]
|
|
138
138
|
*/
|
|
139
139
|
moduleRules?: Record<string, any>[];
|
|
140
|
+
/**
|
|
141
|
+
* Additional rspack/webpack-compatible plugins applied to both the client
|
|
142
|
+
* and SSR bundles. Any object that implements the `apply(compiler)` method
|
|
143
|
+
* (the standard webpack/rspack plugin interface) is accepted.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* import { SubresourceIntegrityPlugin } from 'webpack-subresource-integrity';
|
|
147
|
+
* plugins: [new SubresourceIntegrityPlugin()]
|
|
148
|
+
*/
|
|
149
|
+
plugins?: Array<{
|
|
150
|
+
apply(compiler: any): void;
|
|
151
|
+
}>;
|
|
140
152
|
/**
|
|
141
153
|
* SSR response cache for `run()` mode. Has no effect in `dev()` mode.
|
|
142
154
|
*
|
|
@@ -137,6 +137,18 @@ interface HadarsOptions {
|
|
|
137
137
|
* ]
|
|
138
138
|
*/
|
|
139
139
|
moduleRules?: Record<string, any>[];
|
|
140
|
+
/**
|
|
141
|
+
* Additional rspack/webpack-compatible plugins applied to both the client
|
|
142
|
+
* and SSR bundles. Any object that implements the `apply(compiler)` method
|
|
143
|
+
* (the standard webpack/rspack plugin interface) is accepted.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* import { SubresourceIntegrityPlugin } from 'webpack-subresource-integrity';
|
|
147
|
+
* plugins: [new SubresourceIntegrityPlugin()]
|
|
148
|
+
*/
|
|
149
|
+
plugins?: Array<{
|
|
150
|
+
apply(compiler: any): void;
|
|
151
|
+
}>;
|
|
140
152
|
/**
|
|
141
153
|
* SSR response cache for `run()` mode. Has no effect in `dev()` mode.
|
|
142
154
|
*
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import { A as AppContext } from './hadars-
|
|
4
|
-
export { b as HadarsApp, H as HadarsEntryModule, c as HadarsGetAfterRenderProps, d as HadarsGetClientProps, e as HadarsGetFinalProps, f as HadarsGetInitialProps, a as HadarsOptions, g as HadarsProps, h as HadarsRequest } from './hadars-
|
|
3
|
+
import { A as AppContext } from './hadars-B3b_6sj2.cjs';
|
|
4
|
+
export { b as HadarsApp, H as HadarsEntryModule, c as HadarsGetAfterRenderProps, d as HadarsGetClientProps, e as HadarsGetFinalProps, f as HadarsGetInitialProps, a as HadarsOptions, g as HadarsProps, h as HadarsRequest } from './hadars-B3b_6sj2.cjs';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/** Call this before hydrating to seed the client cache from the server's data.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import { A as AppContext } from './hadars-
|
|
4
|
-
export { b as HadarsApp, H as HadarsEntryModule, c as HadarsGetAfterRenderProps, d as HadarsGetClientProps, e as HadarsGetFinalProps, f as HadarsGetInitialProps, a as HadarsOptions, g as HadarsProps, h as HadarsRequest } from './hadars-
|
|
3
|
+
import { A as AppContext } from './hadars-B3b_6sj2.js';
|
|
4
|
+
export { b as HadarsApp, H as HadarsEntryModule, c as HadarsGetAfterRenderProps, d as HadarsGetClientProps, e as HadarsGetFinalProps, f as HadarsGetInitialProps, a as HadarsOptions, g as HadarsProps, h as HadarsRequest } from './hadars-B3b_6sj2.js';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/** Call this before hydrating to seed the client cache from the server's data.
|
package/dist/lambda.cjs
CHANGED
|
@@ -193,10 +193,10 @@ async function tryServeFile(filePath) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// src/slim-react/types.ts
|
|
196
|
-
var SLIM_ELEMENT =
|
|
197
|
-
var REACT19_ELEMENT =
|
|
198
|
-
var FRAGMENT_TYPE =
|
|
199
|
-
var SUSPENSE_TYPE =
|
|
196
|
+
var SLIM_ELEMENT = Symbol.for("react.element");
|
|
197
|
+
var REACT19_ELEMENT = Symbol.for("react.transitional.element");
|
|
198
|
+
var FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
199
|
+
var SUSPENSE_TYPE = Symbol.for("react.suspense");
|
|
200
200
|
|
|
201
201
|
// src/slim-react/jsx.ts
|
|
202
202
|
function createElement(type, props, ...children) {
|
|
@@ -754,12 +754,12 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
754
754
|
}
|
|
755
755
|
writer.write(`</${tag}>`);
|
|
756
756
|
}
|
|
757
|
-
var REACT_MEMO =
|
|
758
|
-
var REACT_FORWARD_REF =
|
|
759
|
-
var REACT_PROVIDER =
|
|
760
|
-
var REACT_CONTEXT =
|
|
761
|
-
var REACT_CONSUMER =
|
|
762
|
-
var REACT_LAZY =
|
|
757
|
+
var REACT_MEMO = Symbol.for("react.memo");
|
|
758
|
+
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
759
|
+
var REACT_PROVIDER = Symbol.for("react.provider");
|
|
760
|
+
var REACT_CONTEXT = Symbol.for("react.context");
|
|
761
|
+
var REACT_CONSUMER = Symbol.for("react.consumer");
|
|
762
|
+
var REACT_LAZY = Symbol.for("react.lazy");
|
|
763
763
|
function renderComponent(type, props, writer, isSvg) {
|
|
764
764
|
const typeOf = type?.$$typeof;
|
|
765
765
|
if (typeOf === REACT_MEMO) {
|
|
@@ -1161,22 +1161,10 @@ var getReactResponse = async (req, opts) => {
|
|
|
1161
1161
|
var HEAD_MARKER = '<meta name="HADARS_HEAD">';
|
|
1162
1162
|
var BODY_MARKER = '<meta name="HADARS_BODY">';
|
|
1163
1163
|
var encoder = new TextEncoder();
|
|
1164
|
-
async function
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
controller.enqueue(encoder.encode(precontentHtml));
|
|
1169
|
-
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1170
|
-
controller.enqueue(encoder.encode(
|
|
1171
|
-
`<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent
|
|
1172
|
-
));
|
|
1173
|
-
controller.close();
|
|
1174
|
-
}
|
|
1175
|
-
});
|
|
1176
|
-
return new Response(responseStream, {
|
|
1177
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
1178
|
-
status
|
|
1179
|
-
});
|
|
1164
|
+
async function buildSsrHtml(bodyHtml, clientProps, headHtml, getPrecontentHtml) {
|
|
1165
|
+
const [precontentHtml, postContent] = await getPrecontentHtml(headHtml);
|
|
1166
|
+
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
1167
|
+
return precontentHtml + `<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent;
|
|
1180
1168
|
}
|
|
1181
1169
|
var makePrecontentHtmlGetter = (htmlFilePromise) => {
|
|
1182
1170
|
let preHead = null;
|
|
@@ -1340,6 +1328,14 @@ function createLambdaHandler(options, bundled) {
|
|
|
1340
1328
|
const fetchHandler = options.fetch;
|
|
1341
1329
|
const handleProxy = createProxyHandler(options);
|
|
1342
1330
|
const getPrecontentHtml = bundled ? makePrecontentHtmlGetter(Promise.resolve(bundled.outHtml)) : makePrecontentHtmlGetter(import_promises2.default.readFile(import_node_path.default.join(cwd, StaticPath, "out.html"), "utf-8"));
|
|
1331
|
+
let ssrModulePromise = null;
|
|
1332
|
+
const getSsrModule = () => {
|
|
1333
|
+
if (bundled) return Promise.resolve(bundled.ssrModule);
|
|
1334
|
+
if (!ssrModulePromise) {
|
|
1335
|
+
ssrModulePromise = import((0, import_node_url.pathToFileURL)(import_node_path.default.resolve(cwd, HadarsFolder, SSR_FILENAME)).href);
|
|
1336
|
+
}
|
|
1337
|
+
return ssrModulePromise;
|
|
1338
|
+
};
|
|
1343
1339
|
const runHandler = async (req) => {
|
|
1344
1340
|
const request = parseRequest(req);
|
|
1345
1341
|
if (fetchHandler) {
|
|
@@ -1369,7 +1365,7 @@ function createLambdaHandler(options, bundled) {
|
|
|
1369
1365
|
getInitProps,
|
|
1370
1366
|
getAfterRenderProps,
|
|
1371
1367
|
getFinalProps
|
|
1372
|
-
} =
|
|
1368
|
+
} = await getSsrModule();
|
|
1373
1369
|
const { bodyHtml, clientProps, status, headHtml } = await getReactResponse(request, {
|
|
1374
1370
|
document: {
|
|
1375
1371
|
body: Component,
|
|
@@ -1386,7 +1382,11 @@ function createLambdaHandler(options, bundled) {
|
|
|
1386
1382
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
1387
1383
|
});
|
|
1388
1384
|
}
|
|
1389
|
-
|
|
1385
|
+
const html = await buildSsrHtml(bodyHtml, clientProps, headHtml, getPrecontentHtml);
|
|
1386
|
+
return new Response(html, {
|
|
1387
|
+
status,
|
|
1388
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
1389
|
+
});
|
|
1390
1390
|
} catch (err) {
|
|
1391
1391
|
console.error("[hadars] SSR render error:", err);
|
|
1392
1392
|
return new Response("Internal Server Error", { status: 500 });
|
package/dist/lambda.d.cts
CHANGED
package/dist/lambda.d.ts
CHANGED
package/dist/lambda.js
CHANGED
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
} from "./chunk-UNQSQIOO.js";
|
|
4
4
|
import {
|
|
5
5
|
renderToString
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-F7IIMM3J.js";
|
|
7
7
|
import {
|
|
8
8
|
createElement
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OS3V4CPN.js";
|
|
10
10
|
|
|
11
11
|
// src/lambda.ts
|
|
12
12
|
import "react";
|
|
13
|
-
import pathMod from "path";
|
|
14
|
-
import { pathToFileURL } from "url";
|
|
15
|
-
import fs from "fs/promises";
|
|
13
|
+
import pathMod from "node:path";
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
15
|
+
import fs from "node:fs/promises";
|
|
16
16
|
|
|
17
17
|
// src/utils/proxyHandler.tsx
|
|
18
18
|
var cloneHeaders = (headers) => {
|
|
@@ -127,7 +127,7 @@ var parseRequest = (request) => {
|
|
|
127
127
|
};
|
|
128
128
|
|
|
129
129
|
// src/utils/staticFile.ts
|
|
130
|
-
import { readFile, stat } from "fs/promises";
|
|
130
|
+
import { readFile, stat } from "node:fs/promises";
|
|
131
131
|
var MIME = {
|
|
132
132
|
html: "text/html; charset=utf-8",
|
|
133
133
|
htm: "text/html; charset=utf-8",
|
|
@@ -256,22 +256,10 @@ var getReactResponse = async (req, opts) => {
|
|
|
256
256
|
var HEAD_MARKER = '<meta name="HADARS_HEAD">';
|
|
257
257
|
var BODY_MARKER = '<meta name="HADARS_BODY">';
|
|
258
258
|
var encoder = new TextEncoder();
|
|
259
|
-
async function
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
controller.enqueue(encoder.encode(precontentHtml));
|
|
264
|
-
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
265
|
-
controller.enqueue(encoder.encode(
|
|
266
|
-
`<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent
|
|
267
|
-
));
|
|
268
|
-
controller.close();
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
return new Response(responseStream, {
|
|
272
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
273
|
-
status
|
|
274
|
-
});
|
|
259
|
+
async function buildSsrHtml(bodyHtml, clientProps, headHtml, getPrecontentHtml) {
|
|
260
|
+
const [precontentHtml, postContent] = await getPrecontentHtml(headHtml);
|
|
261
|
+
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, "\\u003c");
|
|
262
|
+
return precontentHtml + `<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` + postContent;
|
|
275
263
|
}
|
|
276
264
|
var makePrecontentHtmlGetter = (htmlFilePromise) => {
|
|
277
265
|
let preHead = null;
|
|
@@ -435,6 +423,14 @@ function createLambdaHandler(options, bundled) {
|
|
|
435
423
|
const fetchHandler = options.fetch;
|
|
436
424
|
const handleProxy = createProxyHandler(options);
|
|
437
425
|
const getPrecontentHtml = bundled ? makePrecontentHtmlGetter(Promise.resolve(bundled.outHtml)) : makePrecontentHtmlGetter(fs.readFile(pathMod.join(cwd, StaticPath, "out.html"), "utf-8"));
|
|
426
|
+
let ssrModulePromise = null;
|
|
427
|
+
const getSsrModule = () => {
|
|
428
|
+
if (bundled) return Promise.resolve(bundled.ssrModule);
|
|
429
|
+
if (!ssrModulePromise) {
|
|
430
|
+
ssrModulePromise = import(pathToFileURL(pathMod.resolve(cwd, HadarsFolder, SSR_FILENAME)).href);
|
|
431
|
+
}
|
|
432
|
+
return ssrModulePromise;
|
|
433
|
+
};
|
|
438
434
|
const runHandler = async (req) => {
|
|
439
435
|
const request = parseRequest(req);
|
|
440
436
|
if (fetchHandler) {
|
|
@@ -464,7 +460,7 @@ function createLambdaHandler(options, bundled) {
|
|
|
464
460
|
getInitProps,
|
|
465
461
|
getAfterRenderProps,
|
|
466
462
|
getFinalProps
|
|
467
|
-
} =
|
|
463
|
+
} = await getSsrModule();
|
|
468
464
|
const { bodyHtml, clientProps, status, headHtml } = await getReactResponse(request, {
|
|
469
465
|
document: {
|
|
470
466
|
body: Component,
|
|
@@ -481,7 +477,11 @@ function createLambdaHandler(options, bundled) {
|
|
|
481
477
|
headers: { "Content-Type": "application/json; charset=utf-8" }
|
|
482
478
|
});
|
|
483
479
|
}
|
|
484
|
-
|
|
480
|
+
const html = await buildSsrHtml(bodyHtml, clientProps, headHtml, getPrecontentHtml);
|
|
481
|
+
return new Response(html, {
|
|
482
|
+
status,
|
|
483
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
484
|
+
});
|
|
485
485
|
} catch (err) {
|
|
486
486
|
console.error("[hadars] SSR render error:", err);
|
|
487
487
|
return new Response("Internal Server Error", { status: 500 });
|
|
@@ -77,10 +77,10 @@ __export(slim_react_exports, {
|
|
|
77
77
|
module.exports = __toCommonJS(slim_react_exports);
|
|
78
78
|
|
|
79
79
|
// src/slim-react/types.ts
|
|
80
|
-
var SLIM_ELEMENT =
|
|
81
|
-
var REACT19_ELEMENT =
|
|
82
|
-
var FRAGMENT_TYPE =
|
|
83
|
-
var SUSPENSE_TYPE =
|
|
80
|
+
var SLIM_ELEMENT = Symbol.for("react.element");
|
|
81
|
+
var REACT19_ELEMENT = Symbol.for("react.transitional.element");
|
|
82
|
+
var FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
83
|
+
var SUSPENSE_TYPE = Symbol.for("react.suspense");
|
|
84
84
|
|
|
85
85
|
// src/slim-react/jsx.ts
|
|
86
86
|
var Fragment = FRAGMENT_TYPE;
|
|
@@ -679,12 +679,12 @@ function renderHostElement(tag, props, writer, isSvg) {
|
|
|
679
679
|
}
|
|
680
680
|
writer.write(`</${tag}>`);
|
|
681
681
|
}
|
|
682
|
-
var REACT_MEMO =
|
|
683
|
-
var REACT_FORWARD_REF =
|
|
684
|
-
var REACT_PROVIDER =
|
|
685
|
-
var REACT_CONTEXT =
|
|
686
|
-
var REACT_CONSUMER =
|
|
687
|
-
var REACT_LAZY =
|
|
682
|
+
var REACT_MEMO = Symbol.for("react.memo");
|
|
683
|
+
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
684
|
+
var REACT_PROVIDER = Symbol.for("react.provider");
|
|
685
|
+
var REACT_CONTEXT = Symbol.for("react.context");
|
|
686
|
+
var REACT_CONSUMER = Symbol.for("react.consumer");
|
|
687
|
+
var REACT_LAZY = Symbol.for("react.lazy");
|
|
688
688
|
function renderComponent(type, props, writer, isSvg) {
|
|
689
689
|
const typeOf = type?.$$typeof;
|
|
690
690
|
if (typeOf === REACT_MEMO) {
|
package/dist/slim-react/index.js
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
useSyncExternalStore,
|
|
34
34
|
useTransition,
|
|
35
35
|
version
|
|
36
|
-
} from "../chunk-
|
|
36
|
+
} from "../chunk-F7IIMM3J.js";
|
|
37
37
|
import {
|
|
38
38
|
FRAGMENT_TYPE,
|
|
39
39
|
Fragment,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
SUSPENSE_TYPE,
|
|
42
42
|
createElement,
|
|
43
43
|
jsx
|
|
44
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-OS3V4CPN.js";
|
|
45
45
|
export {
|
|
46
46
|
Children,
|
|
47
47
|
Component,
|
|
@@ -28,8 +28,10 @@ __export(jsx_runtime_exports, {
|
|
|
28
28
|
module.exports = __toCommonJS(jsx_runtime_exports);
|
|
29
29
|
|
|
30
30
|
// src/slim-react/types.ts
|
|
31
|
-
var SLIM_ELEMENT =
|
|
32
|
-
var
|
|
31
|
+
var SLIM_ELEMENT = Symbol.for("react.element");
|
|
32
|
+
var REACT19_ELEMENT = Symbol.for("react.transitional.element");
|
|
33
|
+
var FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
34
|
+
var SUSPENSE_TYPE = Symbol.for("react.suspense");
|
|
33
35
|
|
|
34
36
|
// src/slim-react/jsx.ts
|
|
35
37
|
var Fragment = FRAGMENT_TYPE;
|
package/dist/ssr-watch.js
CHANGED
|
@@ -208,6 +208,29 @@ var buildCompilerConfig = (entry2, opts, includeHotPlugin) => {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
const extraPlugins = [];
|
|
211
|
+
if (!isServerBuild) {
|
|
212
|
+
extraPlugins.push({
|
|
213
|
+
apply(compiler) {
|
|
214
|
+
compiler.hooks.compilation.tap("HadarsWorkerChunkLoading", (compilation) => {
|
|
215
|
+
compilation.hooks.childCompiler.tap(
|
|
216
|
+
"HadarsWorkerChunkLoading",
|
|
217
|
+
(childCompiler) => {
|
|
218
|
+
const libType = childCompiler.options?.output?.library?.type;
|
|
219
|
+
if (libType === "module" || libType === "commonjs" || libType === "commonjs2") {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (childCompiler.options?.output) {
|
|
223
|
+
childCompiler.options.output.chunkLoading = "import-scripts";
|
|
224
|
+
}
|
|
225
|
+
if (childCompiler.options?.experiments) {
|
|
226
|
+
childCompiler.options.experiments.outputModule = false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
211
234
|
const defineValues = { ...opts.define ?? {} };
|
|
212
235
|
if (!isServerBuild && opts.reactMode !== void 0) {
|
|
213
236
|
defineValues["process.env.NODE_ENV"] = JSON.stringify(opts.reactMode);
|
|
@@ -284,7 +307,8 @@ var buildCompilerConfig = (entry2, opts, includeHotPlugin) => {
|
|
|
284
307
|
},
|
|
285
308
|
isDev && !isServerBuild && new ReactRefreshPlugin(),
|
|
286
309
|
includeHotPlugin && isDev && !isServerBuild && new rspack.HotModuleReplacementPlugin(),
|
|
287
|
-
...extraPlugins
|
|
310
|
+
...extraPlugins,
|
|
311
|
+
...opts.plugins ?? []
|
|
288
312
|
],
|
|
289
313
|
...localConfig,
|
|
290
314
|
// Merge base resolve (modules, tsConfig, extensions) with per-build resolve
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hadars",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.38",
|
|
4
4
|
"description": "Minimal SSR framework for React — rspack, HMR, TypeScript, Bun/Node/Deno",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"@types/react-dom": "^19.2.3",
|
|
80
80
|
"react": "^19.2.4",
|
|
81
81
|
"react-dom": "^19.2.4",
|
|
82
|
-
"tsup": "^8.5
|
|
82
|
+
"tsup": "^8.3.5",
|
|
83
83
|
"typescript": "^5.9.3"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
package/src/build.ts
CHANGED
|
@@ -341,6 +341,7 @@ export const dev = async (options: HadarsRuntimeOptions) => {
|
|
|
341
341
|
swcPlugins: options.swcPlugins,
|
|
342
342
|
define: options.define,
|
|
343
343
|
moduleRules: options.moduleRules,
|
|
344
|
+
plugins: options.plugins,
|
|
344
345
|
reactMode: options.reactMode,
|
|
345
346
|
htmlTemplate: resolvedHtmlTemplate,
|
|
346
347
|
});
|
|
@@ -596,6 +597,7 @@ export const build = async (options: HadarsRuntimeOptions) => {
|
|
|
596
597
|
swcPlugins: options.swcPlugins,
|
|
597
598
|
define: options.define,
|
|
598
599
|
moduleRules: options.moduleRules,
|
|
600
|
+
plugins: options.plugins,
|
|
599
601
|
optimization: options.optimization,
|
|
600
602
|
reactMode: options.reactMode,
|
|
601
603
|
htmlTemplate: resolvedHtmlTemplate,
|
|
@@ -614,6 +616,7 @@ export const build = async (options: HadarsRuntimeOptions) => {
|
|
|
614
616
|
swcPlugins: options.swcPlugins,
|
|
615
617
|
define: options.define,
|
|
616
618
|
moduleRules: options.moduleRules,
|
|
619
|
+
plugins: options.plugins,
|
|
617
620
|
}),
|
|
618
621
|
]);
|
|
619
622
|
await fs.rm(tmpFilePath);
|
package/src/lambda.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { createProxyHandler } from './utils/proxyHandler';
|
|
|
24
24
|
import { parseRequest } from './utils/request';
|
|
25
25
|
import { tryServeFile } from './utils/staticFile';
|
|
26
26
|
import { getReactResponse } from './utils/response';
|
|
27
|
-
import { buildSsrResponse, makePrecontentHtmlGetter, createRenderCache } from './utils/ssrHandler';
|
|
27
|
+
import { buildSsrResponse, buildSsrHtml, makePrecontentHtmlGetter, createRenderCache } from './utils/ssrHandler';
|
|
28
28
|
import type { HadarsOptions, HadarsEntryModule, HadarsProps } from './types/hadars';
|
|
29
29
|
|
|
30
30
|
// ── Lambda event / response types ────────────────────────────────────────────
|
|
@@ -189,6 +189,21 @@ export function createLambdaHandler(options: HadarsOptions, bundled?: LambdaBund
|
|
|
189
189
|
? makePrecontentHtmlGetter(Promise.resolve(bundled.outHtml))
|
|
190
190
|
: makePrecontentHtmlGetter(fs.readFile(pathMod.join(cwd, StaticPath, 'out.html'), 'utf-8'));
|
|
191
191
|
|
|
192
|
+
// Hoist the SSR module reference so it is resolved once, not on every
|
|
193
|
+
// request. In bundled mode the module is already in-memory; in file-based
|
|
194
|
+
// mode we lazily import it and cache the promise so Node's module cache is
|
|
195
|
+
// only consulted once.
|
|
196
|
+
let ssrModulePromise: Promise<HadarsEntryModule<any>> | null = null;
|
|
197
|
+
const getSsrModule = (): Promise<HadarsEntryModule<any>> => {
|
|
198
|
+
if (bundled) return Promise.resolve(bundled.ssrModule);
|
|
199
|
+
if (!ssrModulePromise) {
|
|
200
|
+
ssrModulePromise = import(
|
|
201
|
+
pathToFileURL(pathMod.resolve(cwd, HadarsFolder, SSR_FILENAME)).href
|
|
202
|
+
) as Promise<HadarsEntryModule<any>>;
|
|
203
|
+
}
|
|
204
|
+
return ssrModulePromise;
|
|
205
|
+
};
|
|
206
|
+
|
|
192
207
|
const runHandler = async (req: Request): Promise<Response> => {
|
|
193
208
|
const request = parseRequest(req);
|
|
194
209
|
|
|
@@ -227,9 +242,7 @@ export function createLambdaHandler(options: HadarsOptions, bundled?: LambdaBund
|
|
|
227
242
|
getInitProps,
|
|
228
243
|
getAfterRenderProps,
|
|
229
244
|
getFinalProps,
|
|
230
|
-
} =
|
|
231
|
-
? bundled.ssrModule
|
|
232
|
-
: (await import(pathToFileURL(pathMod.resolve(cwd, HadarsFolder, SSR_FILENAME)).href)) as HadarsEntryModule<any>;
|
|
245
|
+
} = await getSsrModule();
|
|
233
246
|
|
|
234
247
|
const { bodyHtml, clientProps, status, headHtml } = await getReactResponse(request, {
|
|
235
248
|
document: {
|
|
@@ -249,7 +262,13 @@ export function createLambdaHandler(options: HadarsOptions, bundled?: LambdaBund
|
|
|
249
262
|
});
|
|
250
263
|
}
|
|
251
264
|
|
|
252
|
-
|
|
265
|
+
// Build the HTML string directly — avoids creating a ReadableStream
|
|
266
|
+
// that would immediately be drained by the Lambda response serialiser.
|
|
267
|
+
const html = await buildSsrHtml(bodyHtml, clientProps, headHtml, getPrecontentHtml);
|
|
268
|
+
return new Response(html, {
|
|
269
|
+
status,
|
|
270
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' },
|
|
271
|
+
});
|
|
253
272
|
} catch (err: any) {
|
|
254
273
|
console.error('[hadars] SSR render error:', err);
|
|
255
274
|
return new Response('Internal Server Error', { status: 500 });
|
package/src/types/hadars.ts
CHANGED
|
@@ -142,6 +142,16 @@ export interface HadarsOptions {
|
|
|
142
142
|
* ]
|
|
143
143
|
*/
|
|
144
144
|
moduleRules?: Record<string, any>[];
|
|
145
|
+
/**
|
|
146
|
+
* Additional rspack/webpack-compatible plugins applied to both the client
|
|
147
|
+
* and SSR bundles. Any object that implements the `apply(compiler)` method
|
|
148
|
+
* (the standard webpack/rspack plugin interface) is accepted.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* import { SubresourceIntegrityPlugin } from 'webpack-subresource-integrity';
|
|
152
|
+
* plugins: [new SubresourceIntegrityPlugin()]
|
|
153
|
+
*/
|
|
154
|
+
plugins?: Array<{ apply(compiler: any): void }>;
|
|
145
155
|
/**
|
|
146
156
|
* SSR response cache for `run()` mode. Has no effect in `dev()` mode.
|
|
147
157
|
*
|
package/src/utils/rspack.ts
CHANGED
|
@@ -136,6 +136,8 @@ interface EntryOptions {
|
|
|
136
136
|
optimization?: Record<string, unknown>;
|
|
137
137
|
// additional module rules appended after the built-in rules
|
|
138
138
|
moduleRules?: Record<string, any>[];
|
|
139
|
+
// additional rspack/webpack-compatible plugins (applied after built-in plugins)
|
|
140
|
+
plugins?: Array<{ apply(compiler: any): void }>;
|
|
139
141
|
// force React runtime mode independently of build mode (client only)
|
|
140
142
|
reactMode?: 'development' | 'production';
|
|
141
143
|
}
|
|
@@ -264,6 +266,39 @@ const buildCompilerConfig = (
|
|
|
264
266
|
}
|
|
265
267
|
|
|
266
268
|
const extraPlugins: any[] = [];
|
|
269
|
+
|
|
270
|
+
// Built-in plugin: force classic chunk loading for web worker sub-compilations.
|
|
271
|
+
// Without this, worker child compilers inherit the parent's outputModule:true context
|
|
272
|
+
// and may emit ES module chunks that cannot be loaded inside classic workers
|
|
273
|
+
// via importScripts. Applied to client builds only — SSR doesn't spawn workers.
|
|
274
|
+
if (!isServerBuild) {
|
|
275
|
+
extraPlugins.push({
|
|
276
|
+
apply(compiler: any) {
|
|
277
|
+
compiler.hooks.compilation.tap('HadarsWorkerChunkLoading', (compilation: any) => {
|
|
278
|
+
compilation.hooks.childCompiler.tap(
|
|
279
|
+
'HadarsWorkerChunkLoading',
|
|
280
|
+
(childCompiler: any) => {
|
|
281
|
+
// Skip internal rspack child compilers that already have an
|
|
282
|
+
// explicit library type (e.g. HtmlRspackPlugin template
|
|
283
|
+
// compilations use library: { type: 'module', name: '' }).
|
|
284
|
+
// Forcing outputModule:false on those triggers the rspack
|
|
285
|
+
// ModuleLibraryPlugin "name can't be empty" panic in production.
|
|
286
|
+
const libType = childCompiler.options?.output?.library?.type;
|
|
287
|
+
if (libType === 'module' || libType === 'commonjs' || libType === 'commonjs2') {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (childCompiler.options?.output) {
|
|
291
|
+
childCompiler.options.output.chunkLoading = 'import-scripts';
|
|
292
|
+
}
|
|
293
|
+
if (childCompiler.options?.experiments) {
|
|
294
|
+
childCompiler.options.experiments.outputModule = false;
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
);
|
|
298
|
+
});
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
}
|
|
267
302
|
const defineValues: Record<string, string> = { ...(opts.define ?? {}) };
|
|
268
303
|
// When reactMode overrides the React runtime we must also set process.env.NODE_ENV
|
|
269
304
|
// so React picks its dev/prod bundle, independently of the rspack build mode.
|
|
@@ -352,6 +387,7 @@ const buildCompilerConfig = (
|
|
|
352
387
|
isDev && !isServerBuild && new ReactRefreshPlugin(),
|
|
353
388
|
includeHotPlugin && isDev && !isServerBuild && new rspack.HotModuleReplacementPlugin(),
|
|
354
389
|
...extraPlugins,
|
|
390
|
+
...(opts.plugins ?? []),
|
|
355
391
|
],
|
|
356
392
|
...localConfig,
|
|
357
393
|
// Merge base resolve (modules, tsConfig, extensions) with per-build resolve
|
package/src/utils/ssrHandler.ts
CHANGED
|
@@ -36,6 +36,27 @@ export async function buildSsrResponse(
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Like {@link buildSsrResponse} but returns the complete HTML string directly
|
|
41
|
+
* instead of wrapping it in a streaming Response. Use this in environments
|
|
42
|
+
* where streaming is not beneficial (e.g. AWS Lambda) to avoid the
|
|
43
|
+
* ReadableStream allocation and the subsequent `.text()` drain overhead.
|
|
44
|
+
*/
|
|
45
|
+
export async function buildSsrHtml(
|
|
46
|
+
bodyHtml: string,
|
|
47
|
+
clientProps: Record<string, unknown>,
|
|
48
|
+
headHtml: string,
|
|
49
|
+
getPrecontentHtml: (headHtml: string) => Promise<[string, string]>,
|
|
50
|
+
): Promise<string> {
|
|
51
|
+
const [precontentHtml, postContent] = await getPrecontentHtml(headHtml);
|
|
52
|
+
const scriptContent = JSON.stringify({ hadars: { props: clientProps } }).replace(/</g, '\\u003c');
|
|
53
|
+
return (
|
|
54
|
+
precontentHtml +
|
|
55
|
+
`<div id="app">${bodyHtml}</div><script id="hadars" type="application/json">${scriptContent}</script>` +
|
|
56
|
+
postContent
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
/**
|
|
40
61
|
* Returns a function that parses `out.html` into pre-head, post-head, and
|
|
41
62
|
* post-content segments and caches the result. Call the returned function with
|