@solidjs/vite-plugin 3.0.0-next.35 → 3.0.0-next.37
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/cjs/index.cjs +88 -25
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +89 -26
- package/dist/esm/index.mjs.map +1 -1
- package/dist/types/src/ssr/index.d.ts +6 -0
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -87,7 +87,16 @@ function webRequestFromNode(req, urlPath, res) {
|
|
|
87
87
|
signal = controller.signal;
|
|
88
88
|
}
|
|
89
89
|
const method = req.method || 'GET';
|
|
90
|
-
|
|
90
|
+
// Only attach a body when the request actually carries one. A web Request
|
|
91
|
+
// built by the browser for a bodyless POST has `body === null`, and the
|
|
92
|
+
// runtime keys off that (a present body that decodes to nothing is a 400
|
|
93
|
+
// since @solidjs/web 2.0.0-rc.5) — so an unconditionally attached (empty)
|
|
94
|
+
// stream misparses bodyless calls. HTTP/1 signals a body via
|
|
95
|
+
// Content-Length/Transfer-Encoding (RFC 9112 §6); the h2 compat API sets
|
|
96
|
+
// `stream.endAfterHeaders` when END_STREAM rode the headers frame.
|
|
97
|
+
const h2Stream = req.stream;
|
|
98
|
+
const hasBody = method !== 'GET' && method !== 'HEAD' && (h2Stream ? !h2Stream.endAfterHeaders : req.headers['transfer-encoding'] !== undefined || req.headers['content-length'] !== undefined && req.headers['content-length'] !== '0');
|
|
99
|
+
const body = hasBody ? node_stream.Readable.toWeb(req) : undefined;
|
|
91
100
|
return new Request(url, {
|
|
92
101
|
method,
|
|
93
102
|
headers,
|
|
@@ -1191,9 +1200,11 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1191
1200
|
`export function handleServerFunctionRequest(request, options) {`, ` const { event: eventInit, ...rest } = options || {};`, ` return handle(request, {`, ` provideEvent: provideRequestEvent,`, ` ...(eventInit ? { createEvent: (req) => ({ request: req, locals: {}, ...eventInit }) } : {}),`, ` ...rest,`, ` });`, `}`].join('\n');
|
|
1192
1201
|
}
|
|
1193
1202
|
|
|
1194
|
-
// Function IDs are
|
|
1195
|
-
//
|
|
1196
|
-
//
|
|
1203
|
+
// Function IDs are `<name>-<xxHash32(root-relative path)>[-<ordinal>]`
|
|
1204
|
+
// (identity-keyed, solidjs/solid#3109). The name is a JS identifier and
|
|
1205
|
+
// never contains `-`, so the hash is always the second segment and maps
|
|
1206
|
+
// an incoming ID back to its module. Rebuilt whenever a transform has
|
|
1207
|
+
// grown the manifest.
|
|
1197
1208
|
const hashIndex = new Map();
|
|
1198
1209
|
let hashIndexSize = -1;
|
|
1199
1210
|
function moduleForFunctionId(functionId) {
|
|
@@ -1205,7 +1216,7 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1205
1216
|
}
|
|
1206
1217
|
hashIndexSize = manifest.server.size;
|
|
1207
1218
|
}
|
|
1208
|
-
return hashIndex.get(functionId.split('-'
|
|
1219
|
+
return hashIndex.get(functionId.split('-')[1]);
|
|
1209
1220
|
}
|
|
1210
1221
|
function moduleDevUrl(entry) {
|
|
1211
1222
|
const relative = path.relative(root, entry).split(path.sep).join('/');
|
|
@@ -1243,10 +1254,11 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1243
1254
|
if (internal.externalDevServer || !isRunnableEnvironment(ssrEnvironment)) {
|
|
1244
1255
|
return;
|
|
1245
1256
|
}
|
|
1246
|
-
// A call's address is `<endpoint>/<id>`
|
|
1247
|
-
//
|
|
1248
|
-
//
|
|
1249
|
-
//
|
|
1257
|
+
// A call's address is `<endpoint>/<id>` — plain HTTP — or
|
|
1258
|
+
// `<endpoint>/data/<id>` — the scripted transport's own path
|
|
1259
|
+
// (solidjs/solid#3076, #3094). Bare-mount requests still reach the
|
|
1260
|
+
// runtime handler (it answers 404), so misdirected posts fail
|
|
1261
|
+
// through the endpoint rather than falling through to SSR.
|
|
1250
1262
|
const underMount = (pathname, mount) => pathname === mount || pathname.startsWith(mount + '/');
|
|
1251
1263
|
server.middlewares.use((req, res, next) => {
|
|
1252
1264
|
const url = new URL(req.url || '/', 'http://localhost');
|
|
@@ -1265,9 +1277,15 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1265
1277
|
// Make sure the referenced module has been evaluated in the SSR
|
|
1266
1278
|
// environment so its registration exists — functions only client
|
|
1267
1279
|
// code references are never loaded by the SSR render itself.
|
|
1268
|
-
// The id lives in the path segment after the mount
|
|
1280
|
+
// The id lives in the path segment after the mount — behind a
|
|
1281
|
+
// literal `data` segment on the scripted transport's address
|
|
1282
|
+
// (solidjs/solid#3094). Segment count keeps the two apart: an id
|
|
1283
|
+
// occupies exactly one segment, so `data/<id>` is only ever a
|
|
1284
|
+
// data address, and a function id spelled `data` still parses at
|
|
1285
|
+
// the bare one.
|
|
1269
1286
|
const mount = basePrefixed ? resolvedEndpoint : endpoint;
|
|
1270
|
-
|
|
1287
|
+
let segment = url.pathname.slice(mount.length + 1);
|
|
1288
|
+
if (segment.startsWith('data/')) segment = segment.slice(5);
|
|
1271
1289
|
let functionId = null;
|
|
1272
1290
|
if (segment && !segment.includes('/')) {
|
|
1273
1291
|
try {
|
|
@@ -1276,14 +1294,6 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1276
1294
|
// not an address; the runtime handler answers the 404
|
|
1277
1295
|
}
|
|
1278
1296
|
}
|
|
1279
|
-
if (!functionId) {
|
|
1280
|
-
// TRANSITIONAL (remove before 3.0 stable): the retired header
|
|
1281
|
-
// and `?id=` addressing, kept only for the RC window where this
|
|
1282
|
-
// plugin meets a @solidjs/web older than the path-addressing
|
|
1283
|
-
// change (solidjs/solid#3076).
|
|
1284
|
-
const headerId = req.headers['x-server-function-id'];
|
|
1285
|
-
functionId = (typeof headerId === 'string' ? headerId.split('#')[0] : undefined) || url.searchParams.get('id');
|
|
1286
|
-
}
|
|
1287
1297
|
if (functionId) {
|
|
1288
1298
|
const entry = moduleForFunctionId(functionId);
|
|
1289
1299
|
if (entry) await ssrEnvironment.runner.import(moduleDevUrl(entry));
|
|
@@ -1922,7 +1932,8 @@ function startServe(options, internal = {}) {
|
|
|
1922
1932
|
lines.push(``, `async function dispatchRequest(request, event, options) {`);
|
|
1923
1933
|
if (composeServerFunctions) {
|
|
1924
1934
|
lines.push(
|
|
1925
|
-
// A call's address is `<endpoint>/<id>`
|
|
1935
|
+
// A call's address is `<endpoint>/<id>` or `<endpoint>/data/<id>`
|
|
1936
|
+
// (solidjs/solid#3076, #3094); the prefix gate covers both, and the
|
|
1926
1937
|
// bare mount still routes so a misaddressed request 404s through the
|
|
1927
1938
|
// runtime handler instead of rendering a page at it.
|
|
1928
1939
|
` const requestPath = new URL(request.url).pathname;`, ` if (requestPath === endpoint || requestPath.startsWith(endpoint + '/')) {`,
|
|
@@ -1995,6 +2006,7 @@ function startServe(options, internal = {}) {
|
|
|
1995
2006
|
devtoolsResolutions = {};
|
|
1996
2007
|
devtoolsIds = {};
|
|
1997
2008
|
entries = resolveEntries(root, options, clientMode);
|
|
2009
|
+
internal.onDocumentResolved?.(entries.document);
|
|
1998
2010
|
middlewarePath = options.middleware ? path.resolve(root, normalizeUserPath(root, options.middleware, 'middleware')) : null;
|
|
1999
2011
|
// Server-mode only, like `entryServer`/`external` (a documented
|
|
2000
2012
|
// no-op in client mode so configs survive the `ssr` boolean flip).
|
|
@@ -2988,6 +3000,11 @@ const LAZY_PLACEHOLDER_PREFIX = '__SOLID_LAZY_MODULE__:';
|
|
|
2988
3000
|
* solid-refresh#85 — is no longer used at all).
|
|
2989
3001
|
*/
|
|
2990
3002
|
const REFRESH_RUNTIME_SOURCE = 'solid-js/refresh';
|
|
3003
|
+
|
|
3004
|
+
// Appended to the document shell's client compile instead of a refresh
|
|
3005
|
+
// boundary (see documentModuleId in solidPlugin): self-accept, then
|
|
3006
|
+
// invalidate — Vite's spelling for "this module cannot hot-update, reload".
|
|
3007
|
+
const DOCUMENT_HMR_DECLINE = '\nif (import.meta.hot) {\n import.meta.hot.accept(() => import.meta.hot.invalidate());\n}\n';
|
|
2991
3008
|
const DEFAULT_STYLE_EXCLUDE = /node_modules/;
|
|
2992
3009
|
const VIRTUAL_MANIFEST_ID = 'virtual:solid-manifest';
|
|
2993
3010
|
const RESOLVED_VIRTUAL_MANIFEST_ID = '\0' + VIRTUAL_MANIFEST_ID;
|
|
@@ -3279,6 +3296,15 @@ function solidPlugin(options = {}) {
|
|
|
3279
3296
|
const externalDevServer = !!options.ssr && !!startOptions?.external;
|
|
3280
3297
|
let needHmr = false;
|
|
3281
3298
|
let replaceDev = false;
|
|
3299
|
+
// Resolved absolute path of the start-mode document shell (normalized to
|
|
3300
|
+
// forward slashes, matching Vite ids), reported back by the start plugin's
|
|
3301
|
+
// config hook. The document is the one module whose client compile must
|
|
3302
|
+
// decline HMR instead of taking a refresh boundary: it hydrates the whole
|
|
3303
|
+
// `document`, and no component swap can re-claim `document.documentElement`
|
|
3304
|
+
// — an accepted update would be absorbed with nothing visibly changing
|
|
3305
|
+
// (solidjs/solid#3151). Declining makes a save invalidate the module, so
|
|
3306
|
+
// Vite falls back to a full page reload: the honest cost.
|
|
3307
|
+
let documentModuleId = null;
|
|
3282
3308
|
// The live dev server, kept so the dev manifest module can bake the bridge
|
|
3283
3309
|
// endpoint URL in when its code is generated (see devManifestBridgeUrl).
|
|
3284
3310
|
let devServer = null;
|
|
@@ -3521,6 +3547,20 @@ function solidPlugin(options = {}) {
|
|
|
3521
3547
|
// real server build resolves (isServer true).
|
|
3522
3548
|
...(isTestMode && !serverTestPosture && !opts.isSsrTargetWebworker ? ['browser'] : []), ...config.resolve.conditions];
|
|
3523
3549
|
|
|
3550
|
+
// `resolve.conditions` above only governs modules Vite inlines.
|
|
3551
|
+
// Externalized server deps are resolved by `fetchModule` with
|
|
3552
|
+
// `resolve.externalConditions` (default `['node', 'module-sync']`) and
|
|
3553
|
+
// handed to the module runner as concrete file paths — without
|
|
3554
|
+
// `development` there, packages that select their dev build through
|
|
3555
|
+
// the `development` export condition (@solidjs/web's server-functions
|
|
3556
|
+
// runtime among them) run their PRODUCTION copy under `vite dev`:
|
|
3557
|
+
// server errors reach the client sanitized to "Internal Server Error"
|
|
3558
|
+
// instead of carrying the real message, dev-only diagnostics vanish.
|
|
3559
|
+
// So the dev flag has to reach both lists.
|
|
3560
|
+
if (replaceDev && config.consumer !== 'client' && name !== 'client') {
|
|
3561
|
+
config.resolve.externalConditions = ['development', ...(config.resolve.externalConditions ?? vite.defaultExternalConditions)];
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3524
3564
|
// Set resolve.noExternal and resolve.external for the SSR environment.
|
|
3525
3565
|
// Only set resolve.external if noExternal is not true (to avoid conflicts with plugins like Cloudflare)
|
|
3526
3566
|
if (name === 'ssr' && solidPkgsConfig) {
|
|
@@ -3579,7 +3619,8 @@ function solidPlugin(options = {}) {
|
|
|
3579
3619
|
};
|
|
3580
3620
|
},
|
|
3581
3621
|
hotUpdate({
|
|
3582
|
-
modules
|
|
3622
|
+
modules,
|
|
3623
|
+
file
|
|
3583
3624
|
}) {
|
|
3584
3625
|
// solid-refresh only injects HMR boundaries into client modules, so
|
|
3585
3626
|
// non-client environments have no accept handlers. Without this, Vite
|
|
@@ -3599,6 +3640,19 @@ function solidPlugin(options = {}) {
|
|
|
3599
3640
|
this.environment.hot.send({
|
|
3600
3641
|
type: 'full-reload'
|
|
3601
3642
|
});
|
|
3643
|
+
// Server-only modules are the exception to the suppression: a file
|
|
3644
|
+
// with no modules in the client graph has no browser HMR path at
|
|
3645
|
+
// all — nothing client-side accepts it, so staying silent leaves
|
|
3646
|
+
// the browser rendering stale server output until a manual refresh
|
|
3647
|
+
// (e.g. the document shell, which only the server ever imports;
|
|
3648
|
+
// solidjs/solid#3151). Reload the page: the honest cost, and there
|
|
3649
|
+
// is no client update to race with by construction.
|
|
3650
|
+
const clientEnv = devServer?.environments.client;
|
|
3651
|
+
if (clientEnv && !clientEnv.moduleGraph.getModulesByFile(file)?.size) {
|
|
3652
|
+
clientEnv.hot.send({
|
|
3653
|
+
type: 'full-reload'
|
|
3654
|
+
});
|
|
3655
|
+
}
|
|
3602
3656
|
}
|
|
3603
3657
|
return [];
|
|
3604
3658
|
}
|
|
@@ -3702,7 +3756,12 @@ function solidPlugin(options = {}) {
|
|
|
3702
3756
|
if (shouldBeProcessedWithTypescript) {
|
|
3703
3757
|
plugins.push('typescript');
|
|
3704
3758
|
}
|
|
3705
|
-
|
|
3759
|
+
|
|
3760
|
+
// See the documentModuleId declaration: the document shell declines HMR
|
|
3761
|
+
// (no refresh boundary, explicit self-invalidation) so edits full-reload.
|
|
3762
|
+
const isDocumentShell = documentModuleId !== null && id === documentModuleId;
|
|
3763
|
+
const needRefresh = needHmr && !isSsr && !inNodeModules && !isDocumentShell;
|
|
3764
|
+
const declineHmr = isDocumentShell && needHmr && !isSsr;
|
|
3706
3765
|
const babelUserOptions = await getBabelUserOptions(options, source, id, !!isSsr);
|
|
3707
3766
|
|
|
3708
3767
|
// The native compiler picks its parser dialect from the file
|
|
@@ -3774,7 +3833,7 @@ function solidPlugin(options = {}) {
|
|
|
3774
3833
|
maps.push(result.map);
|
|
3775
3834
|
const finalCode = injectSsrModuleId(await resolveLazyModuleUrls(this, result.code || '', id), moduleId, !!isSsr);
|
|
3776
3835
|
return {
|
|
3777
|
-
code: finalCode,
|
|
3836
|
+
code: declineHmr ? finalCode + DOCUMENT_HMR_DECLINE : finalCode,
|
|
3778
3837
|
map: combineSourcemaps(maps)
|
|
3779
3838
|
};
|
|
3780
3839
|
}
|
|
@@ -3795,7 +3854,7 @@ function solidPlugin(options = {}) {
|
|
|
3795
3854
|
maps.push(result.map);
|
|
3796
3855
|
const finalCode = injectSsrModuleId(await resolveLazyModuleUrls(this, result.code || '', id), moduleId, !!isSsr);
|
|
3797
3856
|
return {
|
|
3798
|
-
code: finalCode,
|
|
3857
|
+
code: declineHmr ? finalCode + DOCUMENT_HMR_DECLINE : finalCode,
|
|
3799
3858
|
map: combineSourcemaps(maps)
|
|
3800
3859
|
};
|
|
3801
3860
|
}
|
|
@@ -3829,7 +3888,11 @@ function solidPlugin(options = {}) {
|
|
|
3829
3888
|
serverComponents,
|
|
3830
3889
|
ssr: !!options.ssr,
|
|
3831
3890
|
styleFilter: filterDevStyles,
|
|
3832
|
-
diagnostics: !!options.diagnostics
|
|
3891
|
+
diagnostics: !!options.diagnostics,
|
|
3892
|
+
onDocumentResolved(documentPath) {
|
|
3893
|
+
// Normalize to forward slashes to match Vite's transform ids.
|
|
3894
|
+
documentModuleId = documentPath ? documentPath.split(path.sep).join('/') : null;
|
|
3895
|
+
}
|
|
3833
3896
|
}));
|
|
3834
3897
|
}
|
|
3835
3898
|
|