@solidjs/vite-plugin 3.0.0-next.31 → 3.0.0-next.32
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 +26 -8
- package/dist/cjs/index.cjs +121 -133
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +120 -132
- package/dist/esm/index.mjs.map +1 -1
- package/dist/types/src/devtools/index.d.ts +0 -2
- package/dist/types/src/environment.d.ts +2 -1
- package/package.json +9 -6
package/dist/esm/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { mergeAndConcat } from 'merge-anything';
|
|
|
6
6
|
import { createRequire } from 'module';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { Readable } from 'node:stream';
|
|
9
|
-
import { createFilter, normalizePath, loadEnv,
|
|
9
|
+
import { createFilter, normalizePath, loadEnv, runnerImport, defaultClientConditions, defaultServerConditions } from 'vite';
|
|
10
10
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
11
11
|
import { crawlFrameworkPkgs } from 'vitefu';
|
|
12
12
|
|
|
@@ -504,18 +504,18 @@ function boundaryModules() {
|
|
|
504
504
|
// import graph — no directive transforms have run, so it walks
|
|
505
505
|
// straight through 'use server' modules into genuinely server-only
|
|
506
506
|
// code. That graph is legal once transforms split it, so the guard
|
|
507
|
-
// must not fire on the scan pass (`options.scan`,
|
|
508
|
-
// scanner
|
|
509
|
-
// scanner in v8). Still claim the specifier: resolving to the empty
|
|
507
|
+
// must not fire on the scan pass (`options.scan`, set by Rolldown's
|
|
508
|
+
// dependency scanner). Still claim the specifier: resolving to the empty
|
|
510
509
|
// virtual module keeps the scanner from chasing `server-only` /
|
|
511
510
|
// `client-only` as missing bare dependencies, which would abort the
|
|
512
511
|
// scan all the same. Real dev/build module graphs resolve without
|
|
513
512
|
// the flag and stay fully guarded.
|
|
514
513
|
const scan = !!options?.scan;
|
|
514
|
+
const server = this.environment.config.consumer === 'server';
|
|
515
515
|
if (id === 'server-only') {
|
|
516
|
-
if (!
|
|
516
|
+
if (!server && !scan) this.error(`[@solidjs/vite-plugin] Attempt to import 'server-only' in a client module: ${importer}. ` + `Code that uses this module must run only on the server — make sure it is only ` + `imported by server code (e.g. a server entry, a "use server" module, or code ` + `reached exclusively from them).`);
|
|
517
517
|
} else if (id === 'client-only') {
|
|
518
|
-
if (
|
|
518
|
+
if (server && !scan) this.error(`[@solidjs/vite-plugin] Attempt to import 'client-only' in a server module: ${importer}. ` + `Code that uses this module must run only in the browser — make sure it is only ` + `imported by client code (e.g. behind a client-only lazy boundary).`);
|
|
519
519
|
} else {
|
|
520
520
|
return null;
|
|
521
521
|
}
|
|
@@ -818,8 +818,6 @@ function invalidateModule(moduleGraph, path) {
|
|
|
818
818
|
}
|
|
819
819
|
}
|
|
820
820
|
function invalidateModules(server, result, manifest) {
|
|
821
|
-
// `environments` requires Vite 6+; older versions just miss the eager
|
|
822
|
-
// manifest invalidation (the debounced reload still converges).
|
|
823
821
|
if (server?.environments && result.invalidPreload) {
|
|
824
822
|
invalidateModule(server.environments.client.moduleGraph, manifest);
|
|
825
823
|
invalidateModule(server.environments.ssr.moduleGraph, manifest);
|
|
@@ -1012,7 +1010,7 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1012
1010
|
apply: 'serve',
|
|
1013
1011
|
configureServer(server) {
|
|
1014
1012
|
const ssrEnvironment = server.environments.ssr;
|
|
1015
|
-
if (internal.externalDevServer ||
|
|
1013
|
+
if (internal.externalDevServer || !isRunnableEnvironment(ssrEnvironment)) {
|
|
1016
1014
|
return;
|
|
1017
1015
|
}
|
|
1018
1016
|
server.middlewares.use((req, res, next) => {
|
|
@@ -1035,7 +1033,7 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1035
1033
|
const functionId = (typeof headerId === 'string' ? headerId.split('#')[0] : undefined) || url.searchParams.get('id');
|
|
1036
1034
|
if (functionId) {
|
|
1037
1035
|
const entry = moduleForFunctionId(functionId);
|
|
1038
|
-
if (entry) await
|
|
1036
|
+
if (entry) await ssrEnvironment.runner.import(moduleDevUrl(entry));
|
|
1039
1037
|
}
|
|
1040
1038
|
// Dispatch through a module evaluated in the SSR environment so
|
|
1041
1039
|
// the handler shares the registry instance with the app modules.
|
|
@@ -1043,7 +1041,7 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1043
1041
|
// in, and dispatch goes through `handleRequest` instead — one
|
|
1044
1042
|
// middleware chain and one stub-backed request event front the
|
|
1045
1043
|
// endpoint exactly as they front page SSR.
|
|
1046
|
-
const handler = await
|
|
1044
|
+
const handler = await ssrEnvironment.runner.import(internal.ssrHandler ?? HANDLER_ID$1);
|
|
1047
1045
|
// Both dispatch shapes carry the raw Node request on the event
|
|
1048
1046
|
// (the `options.event` seam), matching the SSR dev middleware
|
|
1049
1047
|
// and what a production Node entry passes.
|
|
@@ -1055,7 +1053,6 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1055
1053
|
const response = internal.ssrHandler ? await handler.handleRequest(webRequestFromNode(req, dispatchUrl, res), dispatchOptions) : await handler.handleServerFunctionRequest(webRequestFromNode(req, dispatchUrl, res), dispatchOptions);
|
|
1056
1054
|
await sendWebResponse(res, response);
|
|
1057
1055
|
})().catch(error => {
|
|
1058
|
-
if (error instanceof Error) server.ssrFixStacktrace(error);
|
|
1059
1056
|
next(error);
|
|
1060
1057
|
});
|
|
1061
1058
|
});
|
|
@@ -1179,13 +1176,9 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1179
1176
|
}
|
|
1180
1177
|
|
|
1181
1178
|
const DEVTOOLS_PACKAGE = '@solidjs/start-devtools';
|
|
1182
|
-
const DEVTOOLS_ID = 'virtual:solid-devtools';
|
|
1183
1179
|
const DEVTOOLS_MOUNT_ID = 'virtual:solid-devtools/mount';
|
|
1184
|
-
function devtoolsModuleCode() {
|
|
1185
|
-
return [`import * as serverFunctions from '@solidjs/web/server-functions';`, `import { DevToolbar, pushServerFunctionCall } from '${DEVTOOLS_PACKAGE}';`, `const observe = Reflect.get(serverFunctions, 'observeServerFunctionCalls');`, `if (typeof observe === 'function') observe(pushServerFunctionCall);`, `export { DevToolbar };`].join('\n');
|
|
1186
|
-
}
|
|
1187
1180
|
function devtoolsMountModuleCode() {
|
|
1188
|
-
return [`import
|
|
1181
|
+
return [`import { mountDevToolbar } from '${DEVTOOLS_PACKAGE}';`, `mountDevToolbar();`].join('\n');
|
|
1189
1182
|
}
|
|
1190
1183
|
|
|
1191
1184
|
// Start-mode serving for plain Vite apps: `solid({ start: {...} })` (or the
|
|
@@ -1202,7 +1195,7 @@ function devtoolsMountModuleCode() {
|
|
|
1202
1195
|
// Both paths inject the Vite client, dev style patch, and entry CSS as
|
|
1203
1196
|
// `<style data-vite-dev-id>` tags before the body can paint.
|
|
1204
1197
|
// - Prod: the plugin configures a full-app build (client + server bundles
|
|
1205
|
-
// via the Vite
|
|
1198
|
+
// via the Vite environments/builder API — a single `vite build` builds
|
|
1206
1199
|
// both) whose server entry is `virtual:solid-ssr-handler`: an
|
|
1207
1200
|
// adapter-agnostic named `handleRequest(Request) => Promise<Response>` plus
|
|
1208
1201
|
// a default Fetchable `{ fetch(request) }` export. Both scope each request
|
|
@@ -1384,10 +1377,9 @@ function startServe(options, internal = {}) {
|
|
|
1384
1377
|
const serverComponents = !!internal.serverComponents;
|
|
1385
1378
|
const errorBoundary = options.errorBoundary !== false;
|
|
1386
1379
|
const styleFilter = internal.styleFilter;
|
|
1387
|
-
let
|
|
1388
|
-
let
|
|
1389
|
-
|
|
1390
|
-
let devtoolsId = null;
|
|
1380
|
+
let devtoolsEnabled = false;
|
|
1381
|
+
let devtoolsResolutions = {};
|
|
1382
|
+
let devtoolsIds = {};
|
|
1391
1383
|
// `external` is server-mode-only (documented no-op in client mode, so a
|
|
1392
1384
|
// host-integrated config survives the `ssr` boolean flip untouched).
|
|
1393
1385
|
const externalServer = !clientMode && !!options.external;
|
|
@@ -1404,31 +1396,36 @@ function startServe(options, internal = {}) {
|
|
|
1404
1396
|
if (!entries) throw new Error('[@solidjs/vite-plugin] SSR entries not resolved yet');
|
|
1405
1397
|
return entries;
|
|
1406
1398
|
}
|
|
1407
|
-
async function resolveDevtools(resolve, importer) {
|
|
1408
|
-
if (
|
|
1399
|
+
async function resolveDevtools(resolve, importer, consumer) {
|
|
1400
|
+
if (!devtoolsEnabled) return false;
|
|
1409
1401
|
// Detect from the app graph first (the documented install location), then
|
|
1410
1402
|
// from the plugin's own file: in pnpm-isolated apps a copy that is only a
|
|
1411
1403
|
// dependency of the plugin is not reachable from the app's importers. The
|
|
1412
|
-
// resolved id is kept so
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1404
|
+
// resolved id is kept so imports from generated modules can use it.
|
|
1405
|
+
devtoolsResolutions[consumer] ??= (async () => {
|
|
1406
|
+
// Resolving from the plugin's own file never yields null when the
|
|
1407
|
+
// package is absent: it is declared an optional peer dependency, so
|
|
1408
|
+
// Vite answers with its `__vite-optional-peer-dep:` stub (an empty
|
|
1409
|
+
// module). Treat that stub as "not installed".
|
|
1410
|
+
const realId = resolved => resolved && !resolved.id.startsWith('__vite-optional-peer-dep:') ? resolved.id : null;
|
|
1411
|
+
return realId(await resolve(DEVTOOLS_PACKAGE, importer)) ?? realId(await resolve(DEVTOOLS_PACKAGE, fileURLToPath(import.meta.url)));
|
|
1412
|
+
})();
|
|
1413
|
+
const id = await devtoolsResolutions[consumer];
|
|
1414
|
+
devtoolsIds[consumer] = id;
|
|
1415
|
+
if (!id && options.devtools === true) {
|
|
1418
1416
|
throw new Error('[@solidjs/vite-plugin] start.devtools requires @solidjs/start-devtools. ' + 'Install it as a development dependency or set start.devtools to false.');
|
|
1419
1417
|
}
|
|
1420
|
-
return
|
|
1418
|
+
return id !== null;
|
|
1421
1419
|
}
|
|
1422
1420
|
|
|
1423
1421
|
/**
|
|
1424
|
-
* Cheap
|
|
1422
|
+
* Cheap walk-up probe mirroring how the optimizer resolves bare
|
|
1425
1423
|
* `optimizeDeps.include` entries: is @solidjs/start-devtools reachable from
|
|
1426
|
-
*
|
|
1424
|
+
* this directory? Detection proper (resolveDevtools) runs later with a real
|
|
1427
1425
|
* importer; this only decides whether the toolbar graph can be pre-bundled
|
|
1428
|
-
* at scan time
|
|
1429
|
-
* first-request discovery would force a re-optimize + full page reload.
|
|
1426
|
+
* at scan time.
|
|
1430
1427
|
*/
|
|
1431
|
-
function
|
|
1428
|
+
function devtoolsReachableFrom(dir) {
|
|
1432
1429
|
for (let current = dir;;) {
|
|
1433
1430
|
if (existsSync(path.join(current, 'node_modules', DEVTOOLS_PACKAGE, 'package.json'))) {
|
|
1434
1431
|
return true;
|
|
@@ -1439,6 +1436,26 @@ function startServe(options, internal = {}) {
|
|
|
1439
1436
|
}
|
|
1440
1437
|
}
|
|
1441
1438
|
|
|
1439
|
+
/**
|
|
1440
|
+
* The `optimizeDeps.include` spec that pre-bundles the toolbar graph, or
|
|
1441
|
+
* null when it cannot be resolved at all. Pre-bundling it is not just a
|
|
1442
|
+
* warm-start nicety: the toolbar hangs off virtual modules the scanner
|
|
1443
|
+
* never crawls, so without an include the optimizer only discovers it on
|
|
1444
|
+
* first request. That re-optimize can pair chunks from different passes
|
|
1445
|
+
* whose shared minified exports disagree, taking down the whole client
|
|
1446
|
+
* entry graph. The spec must therefore cover every install shape
|
|
1447
|
+
* resolveDevtools accepts: bare when the app installs the package, and
|
|
1448
|
+
* Vite's nested-include form (`plugin > dep`) when it is only a dependency
|
|
1449
|
+
* of this plugin (pnpm-isolated installs).
|
|
1450
|
+
*/
|
|
1451
|
+
function devtoolsIncludeSpec(rootDir) {
|
|
1452
|
+
if (devtoolsReachableFrom(rootDir)) return DEVTOOLS_PACKAGE;
|
|
1453
|
+
if (devtoolsReachableFrom(path.dirname(fileURLToPath(import.meta.url)))) {
|
|
1454
|
+
return `@solidjs/vite-plugin > ${DEVTOOLS_PACKAGE}`;
|
|
1455
|
+
}
|
|
1456
|
+
return null;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1442
1459
|
/** Import specifier for generated code: absolute for files, id for virtuals. */
|
|
1443
1460
|
function entryServerSpec() {
|
|
1444
1461
|
const {
|
|
@@ -1492,7 +1509,7 @@ function startServe(options, internal = {}) {
|
|
|
1492
1509
|
const content = wrapper ? `<${wrapper}><${root} /></${wrapper}>` : `<${root} />`;
|
|
1493
1510
|
return isBuild && errorBoundary ? [` <DefaultErrorBoundary>`, ` <Document>`, ` <DefaultErrorBoundary>`, ` ${content}`, ` </DefaultErrorBoundary>`, ` </Document>`, ` </DefaultErrorBoundary>`] : [` <Document>`, ` ${content}`, ` </Document>`];
|
|
1494
1511
|
}
|
|
1495
|
-
function generatedEntryServerCode() {
|
|
1512
|
+
function generatedEntryServerCode(toolbar) {
|
|
1496
1513
|
if (clientMode) {
|
|
1497
1514
|
// The client-mode shell: the document without the app. Rendered per
|
|
1498
1515
|
// request in dev (any HTML GET gets it — history-fallback semantics)
|
|
@@ -1504,7 +1521,7 @@ function startServe(options, internal = {}) {
|
|
|
1504
1521
|
app
|
|
1505
1522
|
} = requireEntries();
|
|
1506
1523
|
const streamOptions = `{ manifest${serverComponents ? ', plugins: [ServerComponentPlugin]' : ''} }`;
|
|
1507
|
-
return [`import { renderToStream${setupPath ? ', getRequestEvent' : ''} } from '@solidjs/web';`, ...(serverComponents ? [`import { configureServerFunctionsServer } from '@solidjs/web/server-functions';`, `import { frameTransformDirectResult, ServerComponentPlugin } from '@solidjs/web/frames';`] : []), `import manifest from ${JSON.stringify(MANIFEST_ID)};`, `import Document from ${JSON.stringify(documentSpec())};`, `import App from ${JSON.stringify(app)};`, ...errorBoundaryImport(), ...(setupPath ? [`import setup from ${JSON.stringify(setupPath)};`] : []), ``, ...(setupPath ? [`if (typeof setup !== 'function') {`, ` throw new Error('[@solidjs/vite-plugin] start.setup must default-export a function ' +`, ` '((event, App) => Component | void | Promise<...>): ' + ${JSON.stringify(options.setup)});`, `}`, ``] : []), ...(serverComponents ? [
|
|
1524
|
+
return [`import { renderToStream${setupPath ? ', getRequestEvent' : ''} } from '@solidjs/web';`, ...(serverComponents ? [`import { configureServerFunctionsServer } from '@solidjs/web/server-functions';`, `import { frameTransformDirectResult, ServerComponentPlugin } from '@solidjs/web/frames';`] : []), `import manifest from ${JSON.stringify(MANIFEST_ID)};`, `import Document from ${JSON.stringify(documentSpec())};`, `import App from ${JSON.stringify(app)};`, ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), ...errorBoundaryImport(), ...(setupPath ? [`import setup from ${JSON.stringify(setupPath)};`] : []), ``, ...(setupPath ? [`if (typeof setup !== 'function') {`, ` throw new Error('[@solidjs/vite-plugin] start.setup must default-export a function ' +`, ` '((event, App) => Component | void | Promise<...>): ' + ${JSON.stringify(options.setup)});`, `}`, ``] : []), ...(serverComponents ? [
|
|
1508
1525
|
// Direct (in-process) server-function calls made during document
|
|
1509
1526
|
// SSR must resolve to inline-renderable components; the endpoint
|
|
1510
1527
|
// response transform is installed separately by the
|
|
@@ -1518,7 +1535,7 @@ function startServe(options, internal = {}) {
|
|
|
1518
1535
|
// the *complete* render) and buffers the stream — so it crosses
|
|
1519
1536
|
// boxed under a private key the generated handler unboxes
|
|
1520
1537
|
// (both modules are ours).
|
|
1521
|
-
`export function render(request, context) {`, ` const prepared = setup(getRequestEvent(), App);`, ` if (prepared && typeof prepared.then === 'function') {`, ` return prepared.then((component) => ({ ${STREAM_BOX}: renderApp(component || App) }));`, ` }`, ` return renderApp(prepared || App);`, `}`, ``, `function renderApp(Root) {`, ` return renderToStream(() => (`, ...documentTree('Root'), ` ), ${streamOptions});`, `}`] : [`export function render(request, context) {`, ` return renderToStream(() => (`, ...documentTree('App'), ` ), ${streamOptions});`, `}`])].join('\n');
|
|
1538
|
+
`export function render(request, context) {`, ` const prepared = setup(getRequestEvent(), App);`, ` if (prepared && typeof prepared.then === 'function') {`, ` return prepared.then((component) => ({ ${STREAM_BOX}: renderApp(component || App) }));`, ` }`, ` return renderApp(prepared || App);`, `}`, ``, `function renderApp(Root) {`, ` return renderToStream(() => (`, ...documentTree('Root', toolbar ? 'DevToolbar' : undefined), ` ), ${streamOptions});`, `}`] : [`export function render(request, context) {`, ` return renderToStream(() => (`, ...documentTree('App', toolbar ? 'DevToolbar' : undefined), ` ), ${streamOptions});`, `}`])].join('\n');
|
|
1522
1539
|
}
|
|
1523
1540
|
function generatedEntryClientCode(toolbar) {
|
|
1524
1541
|
const {
|
|
@@ -1530,9 +1547,9 @@ function startServe(options, internal = {}) {
|
|
|
1530
1547
|
// app cannot claim server DOM anyway. The entry script is injected
|
|
1531
1548
|
// without `async` (plain module = deferred), so document.body is
|
|
1532
1549
|
// complete when this runs.
|
|
1533
|
-
return [`import { render } from '@solidjs/web';`, ...errorBoundaryImport(), ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(
|
|
1550
|
+
return [`import { render } from '@solidjs/web';`, ...errorBoundaryImport(), ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), `import App from ${JSON.stringify(app)};`, ``, `render(() => ${isBuild && errorBoundary ? '<DefaultErrorBoundary><App /></DefaultErrorBoundary>' : toolbar ? '<DevToolbar><App /></DevToolbar>' : '<App />'}, document.body);`].join('\n');
|
|
1534
1551
|
}
|
|
1535
|
-
return [`import { hydrate } from '@solidjs/web';`, ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(
|
|
1552
|
+
return [`import { hydrate } from '@solidjs/web';`, ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), ...(serverComponents ? [`import { installServerComponents } from '@solidjs/web/frames';`] : []), ...errorBoundaryImport(), `import Document from ${JSON.stringify(documentSpec())};`, `import App from ${JSON.stringify(app)};`, ``, ...(serverComponents ? [
|
|
1536
1553
|
// Installs the t=0 document-adoption registry and the transport
|
|
1537
1554
|
// policy (component responses morph their boundary instead of
|
|
1538
1555
|
// decoding as data). Must run before hydrate().
|
|
@@ -1713,9 +1730,9 @@ function startServe(options, internal = {}) {
|
|
|
1713
1730
|
enforce: 'pre',
|
|
1714
1731
|
config(userConfig, env) {
|
|
1715
1732
|
root = path.resolve(userConfig.root || process.cwd());
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1733
|
+
devtoolsEnabled = env.command === 'serve' && !env.isPreview && options.devtools !== false;
|
|
1734
|
+
devtoolsResolutions = {};
|
|
1735
|
+
devtoolsIds = {};
|
|
1719
1736
|
entries = resolveEntries(root, options, clientMode);
|
|
1720
1737
|
middlewarePath = options.middleware ? path.resolve(root, normalizeUserPath(root, options.middleware, 'middleware')) : null;
|
|
1721
1738
|
// Server-mode only, like `entryServer`/`external` (a documented
|
|
@@ -1806,7 +1823,7 @@ function startServe(options, internal = {}) {
|
|
|
1806
1823
|
}
|
|
1807
1824
|
},
|
|
1808
1825
|
// Presence of `builder` makes a plain `vite build` build the
|
|
1809
|
-
// whole app (all environments: client then ssr)
|
|
1826
|
+
// whole app (all environments: client then ssr).
|
|
1810
1827
|
// A classic `vite build --ssr` invocation must stay a
|
|
1811
1828
|
// single-environment build, so it doesn't get the flag.
|
|
1812
1829
|
...(env.isSsrBuild ? {} : {
|
|
@@ -1836,23 +1853,32 @@ function startServe(options, internal = {}) {
|
|
|
1836
1853
|
optimizeDeps: {
|
|
1837
1854
|
entries: scanEntries,
|
|
1838
1855
|
// Like the refresh runtime in the main plugin: the toolbar
|
|
1839
|
-
// graph is injected behind
|
|
1840
|
-
//
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1856
|
+
// graph is injected behind modules the scanner never crawls,
|
|
1857
|
+
// so pre-bundle it and the server-functions runtime up front.
|
|
1858
|
+
...(() => {
|
|
1859
|
+
const spec = devtoolsEnabled ? devtoolsIncludeSpec(root) : null;
|
|
1860
|
+
return spec ? {
|
|
1861
|
+
include: [spec, '@solidjs/web/server-functions']
|
|
1862
|
+
} : {};
|
|
1863
|
+
})()
|
|
1846
1864
|
}
|
|
1847
1865
|
})
|
|
1848
1866
|
};
|
|
1849
1867
|
},
|
|
1868
|
+
configEnvironment(name, config) {
|
|
1869
|
+
if (name !== 'ssr') return;
|
|
1870
|
+
config.resolve ??= {};
|
|
1871
|
+
const noExternal = config.resolve.noExternal;
|
|
1872
|
+
if (noExternal !== true) {
|
|
1873
|
+
config.resolve.noExternal = [...(Array.isArray(noExternal) ? noExternal : noExternal ? [noExternal] : []), DEVTOOLS_PACKAGE];
|
|
1874
|
+
}
|
|
1875
|
+
},
|
|
1850
1876
|
configResolved(config) {
|
|
1851
1877
|
root = config.root;
|
|
1852
1878
|
base = config.base;
|
|
1853
1879
|
isBuild = config.command === 'build';
|
|
1854
1880
|
},
|
|
1855
|
-
resolveId(source, importer) {
|
|
1881
|
+
resolveId(source, importer, opts) {
|
|
1856
1882
|
if (source === HANDLER_ID) {
|
|
1857
1883
|
return {
|
|
1858
1884
|
id: HANDLER_ID,
|
|
@@ -1871,18 +1897,16 @@ function startServe(options, internal = {}) {
|
|
|
1871
1897
|
moduleSideEffects: source === ENTRY_CLIENT_ID
|
|
1872
1898
|
};
|
|
1873
1899
|
}
|
|
1874
|
-
if (
|
|
1900
|
+
if (devtoolsEnabled && source === DEVTOOLS_MOUNT_ID) {
|
|
1875
1901
|
return {
|
|
1876
1902
|
id: source,
|
|
1877
1903
|
moduleSideEffects: true
|
|
1878
1904
|
};
|
|
1879
1905
|
}
|
|
1880
|
-
//
|
|
1881
|
-
//
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
// Delegate to the resolution captured at detection time instead.
|
|
1885
|
-
if (devtoolsId && source === DEVTOOLS_PACKAGE && (importer === DEVTOOLS_ID || importer === DEVTOOLS_MOUNT_ID)) {
|
|
1906
|
+
// Generated modules have no directory for bare-package resolution.
|
|
1907
|
+
// Reuse the app-relative id captured during detection.
|
|
1908
|
+
const devtoolsId = devtoolsIds[getEnvironmentConsumer(this.environment, opts)];
|
|
1909
|
+
if (devtoolsId && source === DEVTOOLS_PACKAGE && (importer === ENTRY_SERVER_ID || importer === ENTRY_CLIENT_ID || importer === DEVTOOLS_MOUNT_ID)) {
|
|
1886
1910
|
return {
|
|
1887
1911
|
id: devtoolsId
|
|
1888
1912
|
};
|
|
@@ -1904,37 +1928,40 @@ function startServe(options, internal = {}) {
|
|
|
1904
1928
|
}
|
|
1905
1929
|
return devStylesModuleCode(this.environment, file => this.addWatchFile(file));
|
|
1906
1930
|
}
|
|
1907
|
-
if (id === ENTRY_SERVER_ID)
|
|
1931
|
+
if (id === ENTRY_SERVER_ID) {
|
|
1932
|
+
const toolbar = clientMode ? false : await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
1933
|
+
skipSelf: true
|
|
1934
|
+
}), requireEntries().app, 'server');
|
|
1935
|
+
return generatedEntryServerCode(toolbar);
|
|
1936
|
+
}
|
|
1908
1937
|
if (id === ENTRY_CLIENT_ID) {
|
|
1909
1938
|
const toolbar = await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
1910
1939
|
skipSelf: true
|
|
1911
|
-
}), requireEntries().app);
|
|
1940
|
+
}), requireEntries().app, 'client');
|
|
1912
1941
|
return generatedEntryClientCode(toolbar);
|
|
1913
1942
|
}
|
|
1914
1943
|
if (id === DOCUMENT_ID) return documentShellCode;
|
|
1915
1944
|
if (id === ERROR_BOUNDARY_ID) return errorBoundaryCode;
|
|
1916
|
-
if (id ===
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
// first-touch order doesn't matter.
|
|
1920
|
-
if (!isBuild && consumer === 'client' && devtools === undefined) {
|
|
1945
|
+
if (id === DEVTOOLS_MOUNT_ID) {
|
|
1946
|
+
let enabled = false;
|
|
1947
|
+
if (devtoolsEnabled && consumer === 'client') {
|
|
1921
1948
|
const {
|
|
1922
1949
|
app,
|
|
1923
1950
|
entryClient
|
|
1924
1951
|
} = requireEntries();
|
|
1925
|
-
await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
1952
|
+
enabled = await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
1926
1953
|
skipSelf: true
|
|
1927
|
-
}), app ?? path.resolve(root, entryClient));
|
|
1954
|
+
}), app ?? path.resolve(root, entryClient), 'client');
|
|
1928
1955
|
}
|
|
1929
|
-
if (
|
|
1956
|
+
if (!enabled) {
|
|
1930
1957
|
this.error(`${id} is only available to the development client.`);
|
|
1931
1958
|
}
|
|
1932
|
-
return
|
|
1959
|
+
return devtoolsMountModuleCode();
|
|
1933
1960
|
}
|
|
1934
1961
|
return null;
|
|
1935
1962
|
},
|
|
1936
1963
|
async transform(code, id, opts) {
|
|
1937
|
-
if (isBuild ||
|
|
1964
|
+
if (isBuild || !devtoolsEnabled) return null;
|
|
1938
1965
|
const current = requireEntries();
|
|
1939
1966
|
if (current.generated || getEnvironmentConsumer(this.environment, opts) !== 'client') {
|
|
1940
1967
|
return null;
|
|
@@ -1946,7 +1973,7 @@ function startServe(options, internal = {}) {
|
|
|
1946
1973
|
}
|
|
1947
1974
|
const toolbar = await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
1948
1975
|
skipSelf: true
|
|
1949
|
-
}), id);
|
|
1976
|
+
}), id, 'client');
|
|
1950
1977
|
if (!toolbar) return null;
|
|
1951
1978
|
return {
|
|
1952
1979
|
code: `import ${JSON.stringify(DEVTOOLS_MOUNT_ID)};\n${code}`,
|
|
@@ -2010,7 +2037,7 @@ function startServe(options, internal = {}) {
|
|
|
2010
2037
|
// that gets the streamed SSR render.
|
|
2011
2038
|
return () => {
|
|
2012
2039
|
const ssrEnvironment = server.environments.ssr;
|
|
2013
|
-
if (externalServer ||
|
|
2040
|
+
if (externalServer || !isRunnableEnvironment(ssrEnvironment)) {
|
|
2014
2041
|
return;
|
|
2015
2042
|
}
|
|
2016
2043
|
server.middlewares.use((req, res, next) => {
|
|
@@ -2027,7 +2054,7 @@ function startServe(options, internal = {}) {
|
|
|
2027
2054
|
(async () => {
|
|
2028
2055
|
// Loaded through the SSR environment so the app, the request
|
|
2029
2056
|
// event storage, and the handler share one module registry.
|
|
2030
|
-
const handler = await
|
|
2057
|
+
const handler = await ssrEnvironment.runner.import(HANDLER_ID);
|
|
2031
2058
|
const styles = pageRequest ? await collectDevStyles(server, styleRoots(), styleFilter) : [];
|
|
2032
2059
|
const devHead = styles.map(renderDevStyleTag).join('');
|
|
2033
2060
|
// Post middlewares run after Vite's base middleware stripped
|
|
@@ -2052,7 +2079,6 @@ function startServe(options, internal = {}) {
|
|
|
2052
2079
|
if (response.headers.has(DEV_FALLTHROUGH_HEADER)) return next();
|
|
2053
2080
|
await sendWebResponse(res, response);
|
|
2054
2081
|
})().catch(error => {
|
|
2055
|
-
if (error instanceof Error) server.ssrFixStacktrace(error);
|
|
2056
2082
|
// Vite's error middleware renders the overlay-enabled 500 page.
|
|
2057
2083
|
next(error);
|
|
2058
2084
|
});
|
|
@@ -2142,7 +2168,7 @@ function startServe(options, internal = {}) {
|
|
|
2142
2168
|
// https://github.com/pyyupsk/vite-env), the design-correct prior art. The
|
|
2143
2169
|
// implementation is fresh against this plugin's machinery: Standard Schema
|
|
2144
2170
|
// is the only contract (no zod dependency or zod-specific paths), the
|
|
2145
|
-
// schema file loads through Vite's own `runnerImport
|
|
2171
|
+
// schema file loads through Vite's own `runnerImport`
|
|
2146
2172
|
// (no jiti), server-graph protection keys off the environment *consumer*
|
|
2147
2173
|
// rather than environment-name lists, and the types are inferred from the
|
|
2148
2174
|
// user's schema instead of introspected per-library.
|
|
@@ -2201,37 +2227,18 @@ function formatValidationError(issues, envFile, mode) {
|
|
|
2201
2227
|
return `[@solidjs/vite-plugin] env validation failed (${issues.length} issue${issues.length === 1 ? '' : 's'}) — schema: ${envFile}, mode: ${mode}\n\n` + lines.join('\n') + `\n\nSet the variables in your environment or .env files, or adjust the schema.`;
|
|
2202
2228
|
}
|
|
2203
2229
|
|
|
2204
|
-
/**
|
|
2205
|
-
* Loads the schema module at config time through Vite itself: `runnerImport`
|
|
2206
|
-
* (Vite 6.1+) evaluates TypeScript in-process with project resolution;
|
|
2207
|
-
* older Vite 6 falls back to `loadConfigFromFile`, the exact machinery that
|
|
2208
|
-
* loads vite.config.ts.
|
|
2209
|
-
*/
|
|
2230
|
+
/** Loads the schema module through Vite with project resolution. */
|
|
2210
2231
|
async function importSchemaModule(envFileAbs, root, mode) {
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
} = await vite.runnerImport(envFileAbs, {
|
|
2217
|
-
root,
|
|
2218
|
-
mode
|
|
2219
|
-
});
|
|
2220
|
-
return {
|
|
2221
|
-
exported: module?.default,
|
|
2222
|
-
dependencies: (dependencies || []).map(dep => path.resolve(root, dep)).filter(dep => existsSync(dep))
|
|
2223
|
-
};
|
|
2224
|
-
}
|
|
2225
|
-
const result = await vite.loadConfigFromFile({
|
|
2226
|
-
command: 'serve',
|
|
2232
|
+
const {
|
|
2233
|
+
module,
|
|
2234
|
+
dependencies
|
|
2235
|
+
} = await runnerImport(envFileAbs, {
|
|
2236
|
+
root,
|
|
2227
2237
|
mode
|
|
2228
|
-
}
|
|
2229
|
-
if (!result) {
|
|
2230
|
-
throw new Error(`[@solidjs/vite-plugin] failed to load env schema from ${envFileAbs}`);
|
|
2231
|
-
}
|
|
2238
|
+
});
|
|
2232
2239
|
return {
|
|
2233
|
-
exported:
|
|
2234
|
-
dependencies:
|
|
2240
|
+
exported: module?.default,
|
|
2241
|
+
dependencies: dependencies.map(dep => path.resolve(root, dep)).filter(dep => existsSync(dep))
|
|
2235
2242
|
};
|
|
2236
2243
|
}
|
|
2237
2244
|
function assertSchemaShape(exported, envFile, envPrefixes) {
|
|
@@ -2715,8 +2722,6 @@ const LAZY_PLACEHOLDER_PREFIX = '__SOLID_LAZY_MODULE__:';
|
|
|
2715
2722
|
* solid-refresh#85 — is no longer used at all).
|
|
2716
2723
|
*/
|
|
2717
2724
|
const REFRESH_RUNTIME_SOURCE = 'solid-js/refresh';
|
|
2718
|
-
const viteVersionMajor = +version.split('.')[0];
|
|
2719
|
-
const isVite8 = viteVersionMajor >= 8;
|
|
2720
2725
|
const DEFAULT_STYLE_EXCLUDE = /node_modules/;
|
|
2721
2726
|
const VIRTUAL_MANIFEST_ID = 'virtual:solid-manifest';
|
|
2722
2727
|
const RESOLVED_VIRTUAL_MANIFEST_ID = '\0' + VIRTUAL_MANIFEST_ID;
|
|
@@ -3207,40 +3212,24 @@ function solidPlugin(options = {}) {
|
|
|
3207
3212
|
// server-components runtime installs its response policy there).
|
|
3208
3213
|
...(command === 'serve' && serverComponents ? ['@solidjs/web/frames', '@solidjs/web/server-functions'] : []), ...solidPkgsConfig.optimizeDeps.include],
|
|
3209
3214
|
exclude: solidPkgsConfig.optimizeDeps.exclude,
|
|
3210
|
-
//
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
// (issue #262). The classic runtime is the only scan-safe lowering:
|
|
3216
|
-
// it emits bare `React.createElement` calls without injecting any
|
|
3217
|
-
// import, and the scan output is never executed — it only exists so
|
|
3218
|
-
// rolldown can walk the import graph.
|
|
3219
|
-
...(isVite8 ? {
|
|
3220
|
-
rolldownOptions: {
|
|
3221
|
-
transform: {
|
|
3222
|
-
jsx: {
|
|
3223
|
-
runtime: 'classic'
|
|
3224
|
-
}
|
|
3215
|
+
// Keep Solid TSX from injecting React's automatic runtime during scanning.
|
|
3216
|
+
rolldownOptions: {
|
|
3217
|
+
transform: {
|
|
3218
|
+
jsx: {
|
|
3219
|
+
runtime: 'classic'
|
|
3225
3220
|
}
|
|
3226
3221
|
}
|
|
3227
|
-
}
|
|
3222
|
+
}
|
|
3228
3223
|
},
|
|
3229
3224
|
...(Object.keys(test).length ? {
|
|
3230
3225
|
test
|
|
3231
3226
|
} : {})
|
|
3232
3227
|
};
|
|
3233
3228
|
},
|
|
3234
|
-
|
|
3235
|
-
async configEnvironment(name, config, opts) {
|
|
3229
|
+
configEnvironment(name, config, opts) {
|
|
3236
3230
|
config.resolve ??= {};
|
|
3237
3231
|
// Emulate Vite default fallback for `resolve.conditions` if not set
|
|
3238
3232
|
if (config.resolve.conditions == null) {
|
|
3239
|
-
// @ts-ignore These exports only exist in Vite 6
|
|
3240
|
-
const {
|
|
3241
|
-
defaultClientConditions,
|
|
3242
|
-
defaultServerConditions
|
|
3243
|
-
} = await import('vite');
|
|
3244
3233
|
if (config.consumer === 'client' || name === 'client' || opts.isSsrTargetWebworker) {
|
|
3245
3234
|
config.resolve.conditions = [...defaultClientConditions];
|
|
3246
3235
|
} else {
|
|
@@ -3575,8 +3564,7 @@ function solidPlugin(options = {}) {
|
|
|
3575
3564
|
// would bake a manifest-less fallback into the server bundle. Every user
|
|
3576
3565
|
// of such a setup had to hand-write this ordering plugin; absorb it.
|
|
3577
3566
|
//
|
|
3578
|
-
// Semantics
|
|
3579
|
-
// these, keeping its build-everything default):
|
|
3567
|
+
// Semantics:
|
|
3580
3568
|
// - The first hook builds the client environment first, but only where
|
|
3581
3569
|
// the ordering matters: a client build that emits a manifest and
|
|
3582
3570
|
// actually has an input. It runs at *normal* order, deliberately not
|