@solidjs/vite-plugin 3.0.0-next.36 → 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 +74 -25
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +74 -25
- 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;
|
|
@@ -3593,7 +3619,8 @@ function solidPlugin(options = {}) {
|
|
|
3593
3619
|
};
|
|
3594
3620
|
},
|
|
3595
3621
|
hotUpdate({
|
|
3596
|
-
modules
|
|
3622
|
+
modules,
|
|
3623
|
+
file
|
|
3597
3624
|
}) {
|
|
3598
3625
|
// solid-refresh only injects HMR boundaries into client modules, so
|
|
3599
3626
|
// non-client environments have no accept handlers. Without this, Vite
|
|
@@ -3613,6 +3640,19 @@ function solidPlugin(options = {}) {
|
|
|
3613
3640
|
this.environment.hot.send({
|
|
3614
3641
|
type: 'full-reload'
|
|
3615
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
|
+
}
|
|
3616
3656
|
}
|
|
3617
3657
|
return [];
|
|
3618
3658
|
}
|
|
@@ -3716,7 +3756,12 @@ function solidPlugin(options = {}) {
|
|
|
3716
3756
|
if (shouldBeProcessedWithTypescript) {
|
|
3717
3757
|
plugins.push('typescript');
|
|
3718
3758
|
}
|
|
3719
|
-
|
|
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;
|
|
3720
3765
|
const babelUserOptions = await getBabelUserOptions(options, source, id, !!isSsr);
|
|
3721
3766
|
|
|
3722
3767
|
// The native compiler picks its parser dialect from the file
|
|
@@ -3788,7 +3833,7 @@ function solidPlugin(options = {}) {
|
|
|
3788
3833
|
maps.push(result.map);
|
|
3789
3834
|
const finalCode = injectSsrModuleId(await resolveLazyModuleUrls(this, result.code || '', id), moduleId, !!isSsr);
|
|
3790
3835
|
return {
|
|
3791
|
-
code: finalCode,
|
|
3836
|
+
code: declineHmr ? finalCode + DOCUMENT_HMR_DECLINE : finalCode,
|
|
3792
3837
|
map: combineSourcemaps(maps)
|
|
3793
3838
|
};
|
|
3794
3839
|
}
|
|
@@ -3809,7 +3854,7 @@ function solidPlugin(options = {}) {
|
|
|
3809
3854
|
maps.push(result.map);
|
|
3810
3855
|
const finalCode = injectSsrModuleId(await resolveLazyModuleUrls(this, result.code || '', id), moduleId, !!isSsr);
|
|
3811
3856
|
return {
|
|
3812
|
-
code: finalCode,
|
|
3857
|
+
code: declineHmr ? finalCode + DOCUMENT_HMR_DECLINE : finalCode,
|
|
3813
3858
|
map: combineSourcemaps(maps)
|
|
3814
3859
|
};
|
|
3815
3860
|
}
|
|
@@ -3843,7 +3888,11 @@ function solidPlugin(options = {}) {
|
|
|
3843
3888
|
serverComponents,
|
|
3844
3889
|
ssr: !!options.ssr,
|
|
3845
3890
|
styleFilter: filterDevStyles,
|
|
3846
|
-
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
|
+
}
|
|
3847
3896
|
}));
|
|
3848
3897
|
}
|
|
3849
3898
|
|