@solidjs/start 2.0.0-beta.0 → 2.0.0-beta.10
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/CHANGELOG.md +71 -0
- package/dist/config/boundary-modules.d.ts +14 -0
- package/dist/config/boundary-modules.js +41 -0
- package/dist/config/dev-server.d.ts +3 -1
- package/dist/config/dev-server.js +25 -5
- package/dist/config/env.js +16 -12
- package/dist/config/fs-router.d.ts +1 -1
- package/dist/config/fs-router.js +28 -21
- package/dist/config/fs-routes/router.d.ts +2 -1
- package/dist/config/fs-routes/router.js +8 -10
- package/dist/config/index.js +42 -7
- package/dist/directives/index.js +39 -7
- package/dist/fns/handler.js +40 -4
- package/dist/fns/registration.d.ts +2 -1
- package/dist/fns/registration.js +4 -1
- package/dist/http/http.d.ts +81 -0
- package/dist/http/http.js +129 -0
- package/dist/http/index.d.ts +2 -81
- package/dist/http/index.js +6 -129
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/server/StartServer.jsx +1 -1
- package/dist/server/handler.d.ts +3 -61
- package/dist/server/handler.js +4 -8
- package/dist/server/spa/StartServer.jsx +1 -1
- package/dist/server/spa/handler.d.ts +2 -30
- package/dist/server/web-stream.d.ts +9 -0
- package/dist/server/web-stream.js +26 -0
- package/dist/shared/HttpHeader.jsx +1 -1
- package/env.d.ts +12 -0
- package/package.json +14 -8
- package/scripts/build.js +0 -15
- package/scripts/validate-imports.js +0 -316
- package/src/client/StartClient.tsx +0 -34
- package/src/client/index.tsx +0 -2
- package/src/client/mount.ts +0 -1
- package/src/client/spa/index.tsx +0 -9
- package/src/config/constants.ts +0 -19
- package/src/config/dev-server.ts +0 -157
- package/src/config/env.ts +0 -105
- package/src/config/fs-router.ts +0 -162
- package/src/config/fs-routes/fs-watcher.ts +0 -66
- package/src/config/fs-routes/index.ts +0 -136
- package/src/config/fs-routes/router.ts +0 -184
- package/src/config/fs-routes/tree-shake.ts +0 -324
- package/src/config/index.ts +0 -239
- package/src/config/lazy.ts +0 -132
- package/src/config/manifest.ts +0 -120
- package/src/config/utils.ts +0 -5
- package/src/config/vite-utils.ts +0 -113
- package/src/directives/bubble-function-declaration.ts +0 -33
- package/src/directives/compile.ts +0 -54
- package/src/directives/generate-unique-name.ts +0 -22
- package/src/directives/get-descriptive-name.ts +0 -39
- package/src/directives/get-import-identifier.ts +0 -34
- package/src/directives/get-root-statement-path.ts +0 -14
- package/src/directives/index.ts +0 -233
- package/src/directives/is-statement-top-level.ts +0 -13
- package/src/directives/paths.ts +0 -63
- package/src/directives/plugin.ts +0 -389
- package/src/directives/remove-unused-variables.ts +0 -70
- package/src/directives/types.ts +0 -12
- package/src/directives/xxhash32.ts +0 -214
- package/src/env.d.ts +0 -17
- package/src/fns/client.ts +0 -141
- package/src/fns/handler.spec.ts +0 -85
- package/src/fns/handler.ts +0 -287
- package/src/fns/registration.ts +0 -19
- package/src/fns/serialization.ts +0 -250
- package/src/fns/server.ts +0 -46
- package/src/fns/shared.ts +0 -116
- package/src/http/index.ts +0 -216
- package/src/index.tsx +0 -7
- package/src/internal.d.ts +0 -14
- package/src/middleware/index.ts +0 -92
- package/src/router.tsx +0 -37
- package/src/server/StartServer.tsx +0 -58
- package/src/server/assets/PatchVirtualDevStyles.tsx +0 -31
- package/src/server/assets/index.ts +0 -70
- package/src/server/assets/render.tsx +0 -46
- package/src/server/collect-styles.ts +0 -70
- package/src/server/fetchEvent.spec.ts +0 -85
- package/src/server/fetchEvent.ts +0 -36
- package/src/server/handler.ts +0 -261
- package/src/server/index.tsx +0 -29
- package/src/server/manifest/client-manifest.ts +0 -8
- package/src/server/manifest/dev-client-manifest.ts +0 -21
- package/src/server/manifest/dev-ssr-manifest.ts +0 -23
- package/src/server/manifest/prod-client-manifest.ts +0 -21
- package/src/server/manifest/prod-ssr-manifest.ts +0 -109
- package/src/server/manifest/ssr-manifest.ts +0 -10
- package/src/server/routes.ts +0 -126
- package/src/server/spa/StartServer.tsx +0 -42
- package/src/server/spa/handler.ts +0 -29
- package/src/server/spa/index.tsx +0 -5
- package/src/server/types.ts +0 -82
- package/src/server/util.ts +0 -12
- package/src/shared/ErrorBoundary.tsx +0 -52
- package/src/shared/GET.ts +0 -8
- package/src/shared/HttpHeader.tsx +0 -42
- package/src/shared/HttpStatusCode.ts +0 -27
- package/src/shared/clientOnly.ts +0 -44
- package/src/shared/dev-overlay/CodeView.tsx +0 -90
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +0 -316
- package/src/shared/dev-overlay/createStackFrame.ts +0 -74
- package/src/shared/dev-overlay/download.ts +0 -6
- package/src/shared/dev-overlay/env.d.ts +0 -4
- package/src/shared/dev-overlay/get-source-map.ts +0 -33
- package/src/shared/dev-overlay/icons.tsx +0 -456
- package/src/shared/dev-overlay/index.tsx +0 -63
- package/src/shared/dev-overlay/styles.css +0 -292
- package/src/shared/lazy.ts +0 -52
- package/src/shared/serverFunction.ts +0 -10
- package/src/utils/debounce.ts +0 -10
- package/src/virtual.d.ts +0 -27
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
# @solidjs/start
|
|
2
2
|
|
|
3
|
+
## 2.0.0-beta.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8af6304: Support for Vite 8.1 Experimental Bundled Dev Mode
|
|
8
|
+
- 9d91484: fix: don't crash when a server function throws an error whose message contains non-latin1 characters.
|
|
9
|
+
- 068b64c: Return a cancellation-safe web `ReadableStream` for streaming SSR in development. Returning Solid's
|
|
10
|
+
raw stream only rendered on Node; Bun and Deno coerced it to `[object Object]`.
|
|
11
|
+
|
|
12
|
+
## 2.0.0-beta.9
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- f3e84ec: Add support for `server-only` and `client-only` modules
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- a8a2328: fix: mark `@solidjs/start/http` and `@solidjs/start/middleware` as `server-only` so importing them from client-reachable code fails loudly at dev/build time, instead of silently shipping them to the browser where they crashed hydration and broke unrelated actions/forms with no diagnostic (#2068)
|
|
21
|
+
|
|
22
|
+
## 2.0.0-beta.8
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- ecc02be: fix: resolve server functions in dev when their route was reached through client-side navigation before its module was evaluated on the server
|
|
27
|
+
- 85b24b2: Use per-environment Vite plugin hook APIs for forward compatibility with Vite 9.
|
|
28
|
+
|
|
29
|
+
## 2.0.0-beta.7
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- d2f0621: Support JavaScript projects whose app and client/server entries use `.jsx`.
|
|
34
|
+
|
|
35
|
+
## 2.0.0-beta.6
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 25769f2: Fix Vite preview for non-HTML responses and projects whose server build uses an `.mjs`
|
|
40
|
+
entry.
|
|
41
|
+
|
|
42
|
+
## 2.0.0-beta.5
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- eb73dd5: Use `oxc-parser` to analyze filesystem route exports.
|
|
47
|
+
|
|
48
|
+
## 2.0.0-beta.4
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- 21fdb2c: Update `h3` to `2.0.1-rc.25`.
|
|
53
|
+
|
|
54
|
+
## 2.0.0-beta.3
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- 12dc2d3: Bundle `h3` and `cookie-es` into server builds to avoid resolving incompatible hoisted versions
|
|
59
|
+
|
|
60
|
+
## 2.0.0-beta.2
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- 3e961e0: Require Vite 8
|
|
65
|
+
- 11907a2: Fix published package missing `dist/`: pnpm 11 respects `.gitignore` when packing a package without a `files` field, so `2.0.0-beta.1` was published without its build output. Add an explicit `files` field.
|
|
66
|
+
|
|
67
|
+
## 2.0.0-beta.1
|
|
68
|
+
|
|
69
|
+
### Patch Changes
|
|
70
|
+
|
|
71
|
+
- ee1193a: Update srvx to maintain response compatibility with Nitro v3.
|
|
72
|
+
- e263338: Fix `ERR_UNSUPPORTED_ESM_URL_SCHEME` when running `vite preview` on Windows
|
|
73
|
+
|
|
3
74
|
## 2.0.0-beta.0
|
|
4
75
|
|
|
5
76
|
### Minor Changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Supports `server-only` and `client-only` marker modules (#2162): importing
|
|
4
|
+
* `server-only` from a client module (or `client-only` from a server module)
|
|
5
|
+
* fails at resolve time; in the allowed environment the marker resolves to an
|
|
6
|
+
* empty module.
|
|
7
|
+
*
|
|
8
|
+
* Start's own server-only entry points (`@solidjs/start/http`,
|
|
9
|
+
* `@solidjs/start/middleware`) import `server-only` themselves, so pulling
|
|
10
|
+
* them into the client bundle fails loudly instead of shipping server code to
|
|
11
|
+
* the browser, where it crashed hydration and broke unrelated actions/forms
|
|
12
|
+
* with no diagnostic (https://github.com/solidjs/solid-start/issues/2068).
|
|
13
|
+
*/
|
|
14
|
+
export declare function boundaryModules(): Plugin;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const VIRTUAL_ID = "\0solid-start:boundary-modules:id";
|
|
2
|
+
/**
|
|
3
|
+
* Supports `server-only` and `client-only` marker modules (#2162): importing
|
|
4
|
+
* `server-only` from a client module (or `client-only` from a server module)
|
|
5
|
+
* fails at resolve time; in the allowed environment the marker resolves to an
|
|
6
|
+
* empty module.
|
|
7
|
+
*
|
|
8
|
+
* Start's own server-only entry points (`@solidjs/start/http`,
|
|
9
|
+
* `@solidjs/start/middleware`) import `server-only` themselves, so pulling
|
|
10
|
+
* them into the client bundle fails loudly instead of shipping server code to
|
|
11
|
+
* the browser, where it crashed hydration and broke unrelated actions/forms
|
|
12
|
+
* with no diagnostic (https://github.com/solidjs/solid-start/issues/2068).
|
|
13
|
+
*/
|
|
14
|
+
export function boundaryModules() {
|
|
15
|
+
return {
|
|
16
|
+
name: "solid-start:boundary-modules",
|
|
17
|
+
enforce: "pre",
|
|
18
|
+
resolveId(id, importer, { ssr }) {
|
|
19
|
+
if (id === "server-only") {
|
|
20
|
+
if (!ssr)
|
|
21
|
+
this.error(`Attempt to import 'server-only' in a client module: ${importer}. ` +
|
|
22
|
+
`Code that uses this module must run only on the server: mark it with ` +
|
|
23
|
+
`"use server", or make sure it is only imported by server code.`);
|
|
24
|
+
}
|
|
25
|
+
else if (id === "client-only") {
|
|
26
|
+
if (ssr)
|
|
27
|
+
this.error(`Attempt to import 'client-only' in a server module: ${importer}. ` +
|
|
28
|
+
`Code that uses this module must run only in the browser: make sure it ` +
|
|
29
|
+
`is only imported by client code (e.g. wrap components with clientOnly()).`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return VIRTUAL_ID;
|
|
35
|
+
},
|
|
36
|
+
load(id) {
|
|
37
|
+
if (id === VIRTUAL_ID)
|
|
38
|
+
return "export {}";
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { type PluginOption } from "vite";
|
|
2
|
-
export declare function devServer(): Array<PluginOption>;
|
|
2
|
+
export declare function devServer(serverEntryPath: string): Array<PluginOption>;
|
|
3
|
+
export declare function resolvePreviewServerEntry(root: string): string;
|
|
4
|
+
export declare function isHtmlResponse(response: Response): boolean;
|
|
@@ -6,20 +6,27 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { pathToFileURL } from "node:url";
|
|
9
12
|
import { NodeRequest, sendNodeResponse } from "srvx/node";
|
|
10
13
|
import { isRunnableDevEnvironment, } from "vite";
|
|
11
14
|
import { VITE_ENVIRONMENTS } from "./constants.js";
|
|
12
|
-
export function devServer() {
|
|
15
|
+
export function devServer(serverEntryPath) {
|
|
13
16
|
return [
|
|
14
17
|
{
|
|
15
18
|
name: "solid-start-dev-server",
|
|
16
19
|
configurePreviewServer(server) {
|
|
20
|
+
const serverEntryUrl = pathToFileURL(resolvePreviewServerEntry(server.config.root)).href;
|
|
17
21
|
return () => {
|
|
18
22
|
server.middlewares.use(async (req, res) => {
|
|
19
|
-
res.setHeader("content-encoding", "identity");
|
|
20
23
|
const webReq = new NodeRequest({ req, res });
|
|
21
|
-
const def = await import(__rewriteRelativeImportExtension(
|
|
22
|
-
|
|
24
|
+
const def = await import(__rewriteRelativeImportExtension(serverEntryUrl, true));
|
|
25
|
+
const webRes = await def.default.fetch(webReq);
|
|
26
|
+
if (isHtmlResponse(webRes)) {
|
|
27
|
+
res.setHeader("content-encoding", "identity");
|
|
28
|
+
}
|
|
29
|
+
sendNodeResponse(res, webRes);
|
|
23
30
|
});
|
|
24
31
|
};
|
|
25
32
|
},
|
|
@@ -47,7 +54,7 @@ export function devServer() {
|
|
|
47
54
|
}
|
|
48
55
|
const webReq = new NodeRequest({ req, res });
|
|
49
56
|
try {
|
|
50
|
-
const serverEntry = await serverEnv.runner.import(
|
|
57
|
+
const serverEntry = await serverEnv.runner.import(serverEntryPath);
|
|
51
58
|
const webRes = await serverEntry.default.fetch(webReq);
|
|
52
59
|
return sendNodeResponse(res, webRes);
|
|
53
60
|
}
|
|
@@ -92,6 +99,19 @@ export function devServer() {
|
|
|
92
99
|
},
|
|
93
100
|
];
|
|
94
101
|
}
|
|
102
|
+
export function resolvePreviewServerEntry(root) {
|
|
103
|
+
const serverDirectory = join(root, "dist/server");
|
|
104
|
+
const serverEntry = ["js", "mjs"]
|
|
105
|
+
.map(extension => join(serverDirectory, `entry-server.${extension}`))
|
|
106
|
+
.find(existsSync);
|
|
107
|
+
if (!serverEntry) {
|
|
108
|
+
throw new Error(`Could not find the SolidStart server entry in ${serverDirectory}`);
|
|
109
|
+
}
|
|
110
|
+
return serverEntry;
|
|
111
|
+
}
|
|
112
|
+
export function isHtmlResponse(response) {
|
|
113
|
+
return response.headers.get("content-type")?.startsWith("text/html") ?? false;
|
|
114
|
+
}
|
|
95
115
|
/**
|
|
96
116
|
* Removes Vite internal middleware
|
|
97
117
|
*
|
package/dist/config/env.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { loadEnv } from "vite";
|
|
2
|
+
import { parseIdQuery } from "./utils.js";
|
|
2
3
|
const LOADERS = {
|
|
3
4
|
node: `export default key => process.env[key];`,
|
|
4
5
|
"cloudflare-workers": `import { env } from 'cloudflare:workers';export default key => env[key];`,
|
|
@@ -39,17 +40,20 @@ export function envPlugin(options) {
|
|
|
39
40
|
env = config.mode !== "production" ? "development" : "production";
|
|
40
41
|
},
|
|
41
42
|
resolveId(id) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const { filename } = parseIdQuery(id);
|
|
44
|
+
if (filename === SERVER_ENV ||
|
|
45
|
+
filename === CLIENT_ENV ||
|
|
46
|
+
filename === SERVER_RUNTIME_ENV ||
|
|
47
|
+
filename === SERVER_RUNTIME_LOADER) {
|
|
46
48
|
return id;
|
|
47
49
|
}
|
|
48
50
|
return undefined;
|
|
49
51
|
},
|
|
50
|
-
load(id
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
load(id) {
|
|
53
|
+
const { filename } = parseIdQuery(id);
|
|
54
|
+
const isServer = this.environment.config.consumer === "server";
|
|
55
|
+
if (filename === SERVER_ENV) {
|
|
56
|
+
if (!isServer) {
|
|
53
57
|
return SERVER_ONLY_MODULE;
|
|
54
58
|
}
|
|
55
59
|
const vars = currentOptions.server?.load
|
|
@@ -57,20 +61,20 @@ export function envPlugin(options) {
|
|
|
57
61
|
: loadEnv(env, '.', serverPrefix);
|
|
58
62
|
return convertObjectToModule(vars);
|
|
59
63
|
}
|
|
60
|
-
if (
|
|
64
|
+
if (filename === CLIENT_ENV) {
|
|
61
65
|
const vars = currentOptions.client?.load
|
|
62
66
|
? currentOptions.client.load(env)
|
|
63
67
|
: loadEnv(env, '.', clientPrefix);
|
|
64
68
|
return convertObjectToModule(vars);
|
|
65
69
|
}
|
|
66
|
-
if (
|
|
67
|
-
if (!
|
|
70
|
+
if (filename === SERVER_RUNTIME_LOADER) {
|
|
71
|
+
if (!isServer) {
|
|
68
72
|
return SERVER_ONLY_MODULE;
|
|
69
73
|
}
|
|
70
74
|
return runtimeCode;
|
|
71
75
|
}
|
|
72
|
-
if (
|
|
73
|
-
if (!
|
|
76
|
+
if (filename === SERVER_RUNTIME_ENV) {
|
|
77
|
+
if (!isServer) {
|
|
74
78
|
return SERVER_ONLY_MODULE;
|
|
75
79
|
}
|
|
76
80
|
return SERVER_RUNTIME_CODE;
|
|
@@ -23,7 +23,6 @@ export declare class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
|
23
23
|
});
|
|
24
24
|
toPath(src: string): string;
|
|
25
25
|
toRoute(src: string): {
|
|
26
|
-
path: string;
|
|
27
26
|
page: boolean;
|
|
28
27
|
$component: {
|
|
29
28
|
src: string;
|
|
@@ -33,5 +32,6 @@ export declare class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
|
33
32
|
src: string;
|
|
34
33
|
pick: string[];
|
|
35
34
|
} | undefined;
|
|
35
|
+
path: string;
|
|
36
36
|
} | undefined;
|
|
37
37
|
}
|
package/dist/config/fs-router.js
CHANGED
|
@@ -30,19 +30,17 @@ export class SolidStartClientFileRouter extends BaseFileSystemRouter {
|
|
|
30
30
|
// filePath: src
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
33
|
+
const exports = analyzeModule(src);
|
|
34
|
+
const exportNames = exports.map(getExportName);
|
|
35
|
+
const localExportNames = exports.map(getLocalExportName).filter(name => name !== undefined);
|
|
36
|
+
const hasDefault = exportNames.includes("default");
|
|
37
|
+
const hasRouteConfig = exportNames.includes("route");
|
|
36
38
|
if (hasDefault) {
|
|
37
39
|
return {
|
|
38
40
|
page: true,
|
|
39
41
|
$component: {
|
|
40
42
|
src: src,
|
|
41
|
-
pick: [
|
|
42
|
-
...exports.filter(e => e.n === e.ln && e.n !== "route").map(e => e.n),
|
|
43
|
-
"default",
|
|
44
|
-
"$css",
|
|
45
|
-
],
|
|
43
|
+
pick: [...localExportNames.filter(name => name !== "route"), "default", "$css"],
|
|
46
44
|
},
|
|
47
45
|
$$route: hasRouteConfig
|
|
48
46
|
? {
|
|
@@ -57,18 +55,27 @@ export class SolidStartClientFileRouter extends BaseFileSystemRouter {
|
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
|
|
58
|
+
function getExportName(entry) {
|
|
59
|
+
return entry.exportName.name ?? "default";
|
|
60
|
+
}
|
|
61
|
+
function getLocalExportName(entry) {
|
|
62
|
+
const name = getExportName(entry);
|
|
63
|
+
if (name === "default")
|
|
64
|
+
return;
|
|
65
|
+
return name === (entry.localName.name ?? entry.importName.name ?? name) ? name : undefined;
|
|
66
|
+
}
|
|
60
67
|
function createHTTPHandlers(src, exports) {
|
|
61
68
|
const handlers = {};
|
|
62
69
|
for (const exp of exports) {
|
|
63
|
-
if (HTTP_METHODS.includes(exp
|
|
64
|
-
handlers[`$${exp
|
|
70
|
+
if (HTTP_METHODS.includes(exp)) {
|
|
71
|
+
handlers[`$${exp}`] = {
|
|
65
72
|
src: src,
|
|
66
|
-
pick: [exp
|
|
73
|
+
pick: [exp],
|
|
67
74
|
};
|
|
68
|
-
if (exp
|
|
75
|
+
if (exp === "GET" && !exports.includes("HEAD")) {
|
|
69
76
|
handlers.$HEAD = {
|
|
70
77
|
src: src,
|
|
71
|
-
pick: [exp
|
|
78
|
+
pick: [exp],
|
|
72
79
|
};
|
|
73
80
|
}
|
|
74
81
|
}
|
|
@@ -108,10 +115,12 @@ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
|
108
115
|
path,
|
|
109
116
|
};
|
|
110
117
|
}
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
const
|
|
118
|
+
const exports = analyzeModule(src);
|
|
119
|
+
const exportNames = exports.map(getExportName);
|
|
120
|
+
const localExportNames = exports.map(getLocalExportName).filter(name => name !== undefined);
|
|
121
|
+
const hasRouteConfig = exportNames.includes("route");
|
|
122
|
+
const hasDefault = exportNames.includes("default");
|
|
123
|
+
const hasAPIRoutes = exportNames.some(name => HTTP_METHODS.includes(name));
|
|
115
124
|
if (hasDefault || hasAPIRoutes) {
|
|
116
125
|
return {
|
|
117
126
|
page: hasDefault,
|
|
@@ -119,9 +128,7 @@ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
|
119
128
|
? {
|
|
120
129
|
src: src,
|
|
121
130
|
pick: [
|
|
122
|
-
...
|
|
123
|
-
.filter(e => e.n === e.ln && e.n !== "route" && !HTTP_METHODS.includes(e.n))
|
|
124
|
-
.map(e => e.n),
|
|
131
|
+
...localExportNames.filter(name => name !== "route" && !HTTP_METHODS.includes(name)),
|
|
125
132
|
"default",
|
|
126
133
|
"$css",
|
|
127
134
|
],
|
|
@@ -133,7 +140,7 @@ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
|
|
|
133
140
|
pick: ["route"],
|
|
134
141
|
}
|
|
135
142
|
: undefined,
|
|
136
|
-
...createHTTPHandlers(src,
|
|
143
|
+
...createHTTPHandlers(src, exportNames),
|
|
137
144
|
path,
|
|
138
145
|
};
|
|
139
146
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type StaticExportEntry } from "oxc-parser";
|
|
1
2
|
import { pathToRegexp } from "path-to-regexp";
|
|
2
3
|
export { pathToRegexp };
|
|
3
4
|
export declare const glob: (path: string) => string[];
|
|
@@ -9,7 +10,7 @@ type Route = {
|
|
|
9
10
|
path: string;
|
|
10
11
|
} & Record<string, any>;
|
|
11
12
|
export declare function cleanPath(src: string, config: FileSystemRouterConfig): string;
|
|
12
|
-
export declare function analyzeModule(src: string):
|
|
13
|
+
export declare function analyzeModule(src: string): StaticExportEntry[];
|
|
13
14
|
type RouterEvent = CustomEvent<{
|
|
14
15
|
route: string;
|
|
15
16
|
type: "update" | "remove" | "add";
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { init, parse } from "es-module-lexer";
|
|
2
|
-
import esbuild from "esbuild";
|
|
3
1
|
import fg from "fast-glob";
|
|
4
2
|
import fs from "node:fs";
|
|
5
3
|
import micromatch from "micromatch";
|
|
6
4
|
import { posix } from "node:path";
|
|
5
|
+
import { parseSync } from "oxc-parser";
|
|
7
6
|
import { pathToRegexp } from "path-to-regexp";
|
|
8
7
|
import { normalizePath } from "vite";
|
|
9
8
|
export { pathToRegexp };
|
|
@@ -14,11 +13,11 @@ export function cleanPath(src, config) {
|
|
|
14
13
|
.replace(new RegExp(`\.(${(config.extensions ?? []).join("|")})$`), "");
|
|
15
14
|
}
|
|
16
15
|
export function analyzeModule(src) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}).
|
|
16
|
+
const result = parseSync(src, fs.readFileSync(src, "utf-8"), { lang: "tsx" });
|
|
17
|
+
const error = result.errors[0];
|
|
18
|
+
if (error)
|
|
19
|
+
throw new SyntaxError(`Failed to parse ${src}:\n${error.codeframe || error.message}`);
|
|
20
|
+
return result.module.staticExports.flatMap(({ entries }) => entries.filter(entry => !entry.isType && entry.exportName.kind !== "None"));
|
|
22
21
|
}
|
|
23
22
|
export class BaseFileSystemRouter extends EventTarget {
|
|
24
23
|
routes;
|
|
@@ -37,7 +36,6 @@ export class BaseFileSystemRouter extends EventTarget {
|
|
|
37
36
|
`.{${this.config.extensions.join(",")}}`);
|
|
38
37
|
}
|
|
39
38
|
async buildRoutes() {
|
|
40
|
-
await init;
|
|
41
39
|
for (var src of glob(this.glob())) {
|
|
42
40
|
await this.addRoute(src);
|
|
43
41
|
}
|
|
@@ -53,8 +51,8 @@ export class BaseFileSystemRouter extends EventTarget {
|
|
|
53
51
|
let path = this.toPath(src);
|
|
54
52
|
if (path === undefined)
|
|
55
53
|
return;
|
|
56
|
-
const
|
|
57
|
-
if (!exports.find(
|
|
54
|
+
const exports = analyzeModule(src);
|
|
55
|
+
if (!exports.find(entry => entry.exportName.kind === "Default")) {
|
|
58
56
|
console.warn("No default export", src);
|
|
59
57
|
}
|
|
60
58
|
return {
|
package/dist/config/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { defu } from "defu";
|
|
2
2
|
import { globSync } from "node:fs";
|
|
3
|
-
import { extname, isAbsolute, join } from "node:path";
|
|
3
|
+
import { basename, extname, isAbsolute, join } from "node:path";
|
|
4
4
|
import solid from "vite-plugin-solid";
|
|
5
5
|
import { serverFunctionsPlugin } from "../directives/index.js";
|
|
6
|
+
import { boundaryModules } from "./boundary-modules.js";
|
|
6
7
|
import { DEFAULT_EXTENSIONS, VIRTUAL_MODULES, VITE_ENVIRONMENTS } from "./constants.js";
|
|
7
8
|
import { devServer } from "./dev-server.js";
|
|
8
9
|
import { envPlugin } from "./env.js";
|
|
@@ -44,8 +45,8 @@ export function solidStart(options) {
|
|
|
44
45
|
serverFunctionsPlugin({
|
|
45
46
|
manifest: VIRTUAL_MODULES.serverFnManifest,
|
|
46
47
|
runtime: {
|
|
47
|
-
server:
|
|
48
|
-
client:
|
|
48
|
+
server: "@solidjs/start/fns/server",
|
|
49
|
+
client: "@solidjs/start/fns/client",
|
|
49
50
|
},
|
|
50
51
|
filter: options?.serverFunctions?.filter,
|
|
51
52
|
}),
|
|
@@ -60,8 +61,11 @@ export function solidStart(options) {
|
|
|
60
61
|
},
|
|
61
62
|
};
|
|
62
63
|
},
|
|
63
|
-
async config(
|
|
64
|
+
async config(config, env) {
|
|
64
65
|
const clientInput = [handlers.client];
|
|
66
|
+
const clientEntryUrl = env.command === "serve" && config.experimental?.bundledDev
|
|
67
|
+
? `assets/${basename(handlers.client, entryExtension)}.js`
|
|
68
|
+
: handlers.client;
|
|
65
69
|
if (env.command === "build") {
|
|
66
70
|
const clientRouter = globalThis.ROUTERS.client;
|
|
67
71
|
for (const route of await clientRouter.getRoutes()) {
|
|
@@ -110,7 +114,7 @@ export function solidStart(options) {
|
|
|
110
114
|
manifest: true,
|
|
111
115
|
copyPublicDir: false,
|
|
112
116
|
rollupOptions: {
|
|
113
|
-
input:
|
|
117
|
+
input: handlers.server,
|
|
114
118
|
},
|
|
115
119
|
outDir: "dist/server",
|
|
116
120
|
commonjsOptions: {
|
|
@@ -132,7 +136,14 @@ export function solidStart(options) {
|
|
|
132
136
|
},
|
|
133
137
|
// Depending on the package manager and dependency structure Vite externalizes @solidjs/start
|
|
134
138
|
// This makes sure that @solidjs/start goes through the Vite build process
|
|
135
|
-
|
|
139
|
+
//
|
|
140
|
+
// h3 and cookie-es must be bundled as well: if they stay external, the server build
|
|
141
|
+
// emits bare imports that nitro later re-resolves from the project root, where package
|
|
142
|
+
// managers like yarn may have hoisted the older major versions required by nitropack
|
|
143
|
+
// and unstorage (h3 v1 / cookie-es v1) instead of the versions @solidjs/start needs
|
|
144
|
+
// (see https://github.com/solidjs/solid-start/issues/2101
|
|
145
|
+
// and https://github.com/solidjs/solid-start/issues/2178)
|
|
146
|
+
noExternal: ["@solidjs/start", "h3", "cookie-es"],
|
|
136
147
|
},
|
|
137
148
|
define: {
|
|
138
149
|
"import.meta.env.MANIFEST": `globalThis.MANIFEST`,
|
|
@@ -141,6 +152,7 @@ export function solidStart(options) {
|
|
|
141
152
|
// esbuild receives a valid JS string literal for the define value
|
|
142
153
|
"import.meta.env.START_APP_ENTRY": JSON.stringify(appEntryPath),
|
|
143
154
|
"import.meta.env.START_CLIENT_ENTRY": JSON.stringify(handlers.client),
|
|
155
|
+
"import.meta.env.START_CLIENT_ENTRY_URL": JSON.stringify(clientEntryUrl),
|
|
144
156
|
"import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
|
|
145
157
|
"import.meta.env.SEROVAL_MODE": JSON.stringify(start.serialization?.mode || "json"),
|
|
146
158
|
},
|
|
@@ -178,6 +190,29 @@ export function solidStart(options) {
|
|
|
178
190
|
}),
|
|
179
191
|
lazy(),
|
|
180
192
|
envPlugin(options?.env),
|
|
193
|
+
boundaryModules(),
|
|
194
|
+
{
|
|
195
|
+
name: "solid-start:boundary-modules",
|
|
196
|
+
enforce: "pre",
|
|
197
|
+
resolveId(id, importer, { ssr }) {
|
|
198
|
+
if (id === "server-only") {
|
|
199
|
+
if (!ssr)
|
|
200
|
+
this.error(`Attempt to import 'server-only' in a client module: ${importer}`);
|
|
201
|
+
}
|
|
202
|
+
else if (id === "client-only") {
|
|
203
|
+
if (ssr)
|
|
204
|
+
this.error(`Attempt to import 'client-only' in a server module: ${importer}`);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
return "\0solid-start:boundary-modules:id";
|
|
210
|
+
},
|
|
211
|
+
load(id) {
|
|
212
|
+
if (id === "\0solid-start:boundary-modules:id")
|
|
213
|
+
return "export {}";
|
|
214
|
+
},
|
|
215
|
+
},
|
|
181
216
|
{
|
|
182
217
|
name: "solid-start:virtual-modules",
|
|
183
218
|
async resolveId(id) {
|
|
@@ -207,7 +242,7 @@ export function solidStart(options) {
|
|
|
207
242
|
globalThis.START_CLIENT_OUT_DIR = options.dir;
|
|
208
243
|
},
|
|
209
244
|
},
|
|
210
|
-
devServer(),
|
|
245
|
+
devServer(handlers.server),
|
|
211
246
|
solid({
|
|
212
247
|
...start.solid,
|
|
213
248
|
ssr: true,
|
package/dist/directives/index.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { createFilter, } from "vite";
|
|
2
|
+
import fg from "fast-glob";
|
|
2
3
|
import { compile } from "./compile.js";
|
|
4
|
+
import xxHash32 from "./xxhash32.js";
|
|
3
5
|
const DEFAULT_INCLUDE = "src/**/*.{jsx,tsx,ts,js,mjs,cjs}";
|
|
4
6
|
const DEFAULT_EXCLUDE = "node_modules/**/*.{jsx,tsx,ts,js,mjs,cjs}";
|
|
5
7
|
const DIRECTIVE = "use server";
|
|
8
|
+
// Dev-only virtual module used by fns/handler.ts to lazily resolve a server
|
|
9
|
+
// function id back to its owning module when the function was never evaluated
|
|
10
|
+
// in the server environment (e.g. its route was only client-side navigated to).
|
|
11
|
+
const LOOKUP_ID = "solid-start:server-fn-lookup";
|
|
6
12
|
function createManifest() {
|
|
7
13
|
return {
|
|
8
14
|
server: new Set(),
|
|
@@ -63,8 +69,11 @@ function invalidateModule(moduleGraph, path) {
|
|
|
63
69
|
function invalidateModules(server, result, manifest) {
|
|
64
70
|
if (server) {
|
|
65
71
|
if (result.invalidPreload) {
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
// Environments are not limited to "client"/"ssr": plugins like nitro
|
|
73
|
+
// render in their own environment (e.g. "nitro"), so invalidate everywhere.
|
|
74
|
+
for (const environment of Object.values(server.environments)) {
|
|
75
|
+
invalidateModule(environment.moduleGraph, manifest);
|
|
76
|
+
}
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
}
|
|
@@ -125,24 +134,47 @@ export function serverFunctionsPlugin(options) {
|
|
|
125
134
|
if (source === options.manifest) {
|
|
126
135
|
return { id: options.manifest, moduleSideEffects: true };
|
|
127
136
|
}
|
|
137
|
+
if (source.startsWith(LOOKUP_ID)) {
|
|
138
|
+
return { id: source, moduleSideEffects: true };
|
|
139
|
+
}
|
|
128
140
|
return null;
|
|
129
141
|
},
|
|
130
|
-
async load(id
|
|
131
|
-
const mode =
|
|
142
|
+
async load(id) {
|
|
143
|
+
const mode = this.environment.config.consumer;
|
|
132
144
|
if (id === options.manifest) {
|
|
133
145
|
const current = new Debouncer(() => [...manifest[mode]].map(entry => `import "${entry}";`).join("\n"));
|
|
134
146
|
preload[mode] = current;
|
|
135
147
|
const result = await current.promise.reference;
|
|
136
148
|
return result;
|
|
137
149
|
}
|
|
150
|
+
if (id.startsWith(LOOKUP_ID)) {
|
|
151
|
+
if (this.environment.mode !== "dev") {
|
|
152
|
+
throw new Error(`${LOOKUP_ID} is only available in dev`);
|
|
153
|
+
}
|
|
154
|
+
const functionId = new URLSearchParams(id.slice(LOOKUP_ID.length + 1)).get("id");
|
|
155
|
+
// dev function ids are `${xxHash32(file)}-${count}-${name}`
|
|
156
|
+
const hash = functionId?.split("-")[0];
|
|
157
|
+
if (!hash)
|
|
158
|
+
return "export {};";
|
|
159
|
+
// Look through the files already discovered by the transform first;
|
|
160
|
+
// fall back to scanning the project so a function is found even when
|
|
161
|
+
// the browser kept a chunk from before a dev server restart.
|
|
162
|
+
let files = [...manifest.server].filter(file => xxHash32(file).toString(16) === hash);
|
|
163
|
+
if (files.length === 0) {
|
|
164
|
+
files = fg
|
|
165
|
+
.sync(DEFAULT_INCLUDE, { cwd: this.environment.config.root, absolute: true })
|
|
166
|
+
.filter(file => filter(file) && xxHash32(file).toString(16) === hash);
|
|
167
|
+
}
|
|
168
|
+
return files.map(file => `import ${JSON.stringify(file)};`).join("\n") || "export {};";
|
|
169
|
+
}
|
|
138
170
|
return null;
|
|
139
171
|
},
|
|
140
172
|
},
|
|
141
173
|
{
|
|
142
174
|
name: "solid-start:server-functions/compiler",
|
|
143
|
-
enforce:
|
|
144
|
-
async transform(code, fileId
|
|
145
|
-
const mode =
|
|
175
|
+
enforce: "pre",
|
|
176
|
+
async transform(code, fileId) {
|
|
177
|
+
const mode = this.environment.config.consumer;
|
|
146
178
|
const [id] = fileId.split("?");
|
|
147
179
|
if (!filter(id)) {
|
|
148
180
|
return null;
|