@solidjs/start 2.0.0-alpha.2 → 2.0.0-beta.0

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/config/constants.d.ts +3 -3
  3. package/dist/config/constants.js +1 -1
  4. package/dist/config/dev-server.js +9 -1
  5. package/dist/config/env.d.ts +19 -0
  6. package/dist/config/env.js +81 -0
  7. package/dist/config/fs-routes/fs-watcher.js +32 -28
  8. package/dist/config/fs-routes/index.js +2 -2
  9. package/dist/config/fs-routes/router.d.ts +8 -3
  10. package/dist/config/fs-routes/router.js +26 -13
  11. package/dist/config/fs-routes/tree-shake.js +0 -43
  12. package/dist/config/index.d.ts +16 -1
  13. package/dist/config/index.js +31 -31
  14. package/dist/config/lazy.js +4 -2
  15. package/dist/config/manifest.js +41 -7
  16. package/dist/config/vite-utils.d.ts +1 -1
  17. package/dist/directives/bubble-function-declaration.d.ts +3 -0
  18. package/dist/directives/bubble-function-declaration.js +23 -0
  19. package/dist/directives/compile.d.ts +9 -0
  20. package/dist/directives/compile.js +40 -0
  21. package/dist/directives/generate-unique-name.d.ts +3 -0
  22. package/dist/directives/generate-unique-name.js +16 -0
  23. package/dist/directives/get-descriptive-name.d.ts +2 -0
  24. package/dist/directives/get-descriptive-name.js +37 -0
  25. package/dist/directives/get-import-identifier.d.ts +4 -0
  26. package/dist/directives/get-import-identifier.js +19 -0
  27. package/dist/directives/get-root-statement-path.d.ts +2 -0
  28. package/dist/directives/get-root-statement-path.js +12 -0
  29. package/dist/directives/index.d.ts +14 -0
  30. package/dist/directives/index.js +170 -0
  31. package/dist/directives/is-statement-top-level.d.ts +3 -0
  32. package/dist/directives/is-statement-top-level.js +9 -0
  33. package/dist/directives/paths.d.ts +9 -0
  34. package/dist/directives/paths.js +36 -0
  35. package/dist/directives/plugin.d.ts +21 -0
  36. package/dist/directives/plugin.js +302 -0
  37. package/dist/directives/remove-unused-variables.d.ts +3 -0
  38. package/dist/directives/remove-unused-variables.js +66 -0
  39. package/dist/directives/types.d.ts +10 -0
  40. package/dist/directives/xxhash32.d.ts +6 -0
  41. package/dist/directives/xxhash32.js +193 -0
  42. package/dist/{server/server-runtime.d.ts → fns/client.d.ts} +1 -1
  43. package/dist/fns/client.js +106 -0
  44. package/dist/fns/handler.d.ts +5 -0
  45. package/dist/{server/server-functions-handler.js → fns/handler.js} +55 -96
  46. package/dist/fns/registration.d.ts +2 -0
  47. package/dist/fns/registration.js +12 -0
  48. package/dist/fns/serialization.d.ts +6 -0
  49. package/dist/fns/serialization.js +208 -0
  50. package/dist/fns/server.d.ts +7 -0
  51. package/dist/{server/server-fns-runtime.js → fns/server.js} +7 -1
  52. package/dist/fns/shared.d.ts +17 -0
  53. package/dist/fns/shared.js +105 -0
  54. package/dist/http/index.d.ts +1 -1
  55. package/dist/middleware/index.d.ts +17 -0
  56. package/dist/middleware/index.js +15 -0
  57. package/dist/server/handler.d.ts +61 -3
  58. package/dist/server/handler.js +18 -16
  59. package/dist/server/spa/handler.d.ts +30 -1
  60. package/dist/server/types.d.ts +1 -1
  61. package/dist/shared/dev-overlay/CodeView.jsx +4 -4
  62. package/dist/shared/dev-overlay/DevOverlayDialog.jsx +34 -34
  63. package/dist/shared/dev-overlay/index.jsx +2 -2
  64. package/dist/shared/dev-overlay/styles.css +40 -40
  65. package/dist/utils/debounce.d.ts +4 -0
  66. package/dist/utils/debounce.js +10 -0
  67. package/package.json +28 -21
  68. package/src/config/constants.ts +3 -3
  69. package/src/config/env.ts +105 -0
  70. package/src/config/fs-routes/fs-watcher.ts +38 -49
  71. package/src/config/fs-routes/index.ts +2 -2
  72. package/src/config/fs-routes/router.ts +29 -13
  73. package/src/config/fs-routes/tree-shake.ts +1 -48
  74. package/src/config/index.ts +45 -41
  75. package/src/config/lazy.ts +3 -2
  76. package/src/config/manifest.ts +45 -10
  77. package/src/config/vite-utils.ts +1 -1
  78. package/src/directives/bubble-function-declaration.ts +33 -0
  79. package/src/directives/compile.ts +54 -0
  80. package/src/directives/generate-unique-name.ts +22 -0
  81. package/src/directives/get-descriptive-name.ts +39 -0
  82. package/src/directives/get-import-identifier.ts +34 -0
  83. package/src/directives/get-root-statement-path.ts +14 -0
  84. package/src/directives/index.ts +233 -0
  85. package/src/directives/is-statement-top-level.ts +13 -0
  86. package/src/directives/paths.ts +63 -0
  87. package/src/directives/plugin.ts +389 -0
  88. package/src/directives/remove-unused-variables.ts +70 -0
  89. package/src/directives/types.ts +12 -0
  90. package/src/directives/xxhash32.ts +214 -0
  91. package/src/env.d.ts +1 -1
  92. package/src/fns/client.ts +141 -0
  93. package/src/fns/handler.spec.ts +85 -0
  94. package/src/{server/server-functions-handler.ts → fns/handler.ts} +65 -117
  95. package/src/fns/registration.ts +19 -0
  96. package/src/fns/serialization.ts +250 -0
  97. package/src/{server/server-fns-runtime.ts → fns/server.ts} +17 -2
  98. package/src/fns/shared.ts +116 -0
  99. package/src/middleware/index.ts +17 -0
  100. package/src/server/handler.ts +19 -17
  101. package/src/server/types.ts +1 -1
  102. package/src/shared/dev-overlay/CodeView.tsx +5 -7
  103. package/src/shared/dev-overlay/DevOverlayDialog.tsx +34 -34
  104. package/src/shared/dev-overlay/get-source-map.ts +1 -1
  105. package/src/shared/dev-overlay/index.tsx +4 -4
  106. package/src/shared/dev-overlay/styles.css +40 -40
  107. package/src/utils/debounce.ts +10 -0
  108. package/tsconfig.json +1 -0
  109. package/dist/server/fetchEvent.spec.js +0 -65
  110. package/dist/server/server-fns-runtime.d.ts +0 -1
  111. package/dist/server/server-functions-handler.d.ts +0 -2
  112. package/dist/server/server-runtime.js +0 -194
  113. package/src/server/server-runtime.ts +0 -240
  114. /package/dist/{server/fetchEvent.spec.d.ts → directives/types.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @solidjs/start
2
2
 
3
+ ## 2.0.0-beta.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0a9fdc3: fix cloudflare
8
+
9
+ ### Patch Changes
10
+
11
+ - 0c95804: Fix URL to path conversion in manifest resolver
12
+ - 6011e5a: Fixed changes in route files resulting in a reload instead of hot module replace. Reloads now only are triggered when adding or removing routes.
13
+ - 8fb81e6: Fixed niche edge cases in the server functions dead code removal (DCE) logic:
14
+ - Server functions only referenced in event handlers (e.g. `onClick`) now aren't considered unused and work properly.
15
+ - Unused variables in server functions no longer lead to compilation errors.
16
+ - 8d12d6a: Fixed tailwind class changes not getting applied via HMR in filesystem routes.
17
+ - ec1b82b: Included Vite 8 in the peer dependency range.
18
+
19
+ ## 2.0.0-alpha.3
20
+
21
+ ### Minor Changes
22
+
23
+ - 798b285: Updated dependencies.
24
+ - f6f0452: seroval json mode
25
+ - d4be1b6: Add new directives plugin with shorter function IDs and inner declaration support
26
+ - b9c4ade: feat: add `env:*` runtime environment variables support
27
+
28
+ ### Patch Changes
29
+
30
+ - ff9607c: import DevEnvironment and Rollup as type from vite
31
+ - 6da636b: The server function directives runtime is now internally accessed via package.json exports instead of relative paths, fixing inconsistencies in the file resolution. Also the server functions file inclusion/exclusion patterns can now be configured in the start plugin options via `serverFunctions`.
32
+ - 2885905: fix: clone request headers in single-flight to avoid mutating immutable headers
33
+ - abe3979: reload ssr server when new route files are created in dev
34
+ - 7c288f6: Sanitize Location header value in streaming redirect script
35
+ - 6c83886: update seroval to 1.5.4
36
+ - 9d5d783: Add support for Vite 8 asset manifest loading
37
+
3
38
  ## 2.0.0-alpha.2
4
39
 
5
40
  ### Minor Changes
@@ -5,12 +5,12 @@ export declare const VIRTUAL_MODULES: {
5
5
  readonly getClientManifest: "solid-start:get-client-manifest";
6
6
  readonly getManifest: "solid-start:get-manifest";
7
7
  readonly middleware: "solid-start:middleware";
8
- readonly serverFnManifest: "solidstart:server-fn-manifest";
8
+ readonly serverFnManifest: "solid-start:server-fn-manifest";
9
9
  readonly clientEntry: "solid-start:client-entry";
10
10
  readonly serverEntry: "solid-start:server-entry";
11
11
  readonly app: "solid-start:app";
12
12
  };
13
13
  export declare const VITE_ENVIRONMENTS: {
14
- client: string;
15
- server: string;
14
+ client: "client";
15
+ server: "ssr";
16
16
  };
@@ -5,7 +5,7 @@ export const VIRTUAL_MODULES = {
5
5
  getClientManifest: "solid-start:get-client-manifest",
6
6
  getManifest: "solid-start:get-manifest",
7
7
  middleware: "solid-start:middleware",
8
- serverFnManifest: "solidstart:server-fn-manifest",
8
+ serverFnManifest: "solid-start:server-fn-manifest",
9
9
  clientEntry: "solid-start:client-entry",
10
10
  serverEntry: "solid-start:server-entry",
11
11
  app: "solid-start:app",
@@ -1,3 +1,11 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
1
9
  import { NodeRequest, sendNodeResponse } from "srvx/node";
2
10
  import { isRunnableDevEnvironment, } from "vite";
3
11
  import { VITE_ENVIRONMENTS } from "./constants.js";
@@ -10,7 +18,7 @@ export function devServer() {
10
18
  server.middlewares.use(async (req, res) => {
11
19
  res.setHeader("content-encoding", "identity");
12
20
  const webReq = new NodeRequest({ req, res });
13
- const def = await import(process.cwd() + "/dist/server/entry-server.js");
21
+ const def = await import(__rewriteRelativeImportExtension(process.cwd() + "/dist/server/entry-server.js", true));
14
22
  sendNodeResponse(res, await def.default.fetch(webReq));
15
23
  });
16
24
  };
@@ -0,0 +1,19 @@
1
+ import { type Plugin } from "vite";
2
+ declare const LOADERS: {
3
+ node: string;
4
+ "cloudflare-workers": string;
5
+ "netlify-edge": string;
6
+ };
7
+ export interface EnvPluginOptions {
8
+ server?: {
9
+ runtime?: keyof typeof LOADERS | (string & {});
10
+ load?: (mode: string) => Record<string, string>;
11
+ prefix?: string;
12
+ };
13
+ client?: {
14
+ load?: (mode: string) => Record<string, string>;
15
+ prefix?: string;
16
+ };
17
+ }
18
+ export declare function envPlugin(options?: EnvPluginOptions): Plugin;
19
+ export {};
@@ -0,0 +1,81 @@
1
+ import { loadEnv } from "vite";
2
+ const LOADERS = {
3
+ node: `export default key => process.env[key];`,
4
+ "cloudflare-workers": `import { env } from 'cloudflare:workers';export default key => env[key];`,
5
+ "netlify-edge": `export default key => Netlify.env.get(key);`,
6
+ };
7
+ const SERVER_ENV = "env:server";
8
+ const CLIENT_ENV = "env:client";
9
+ const SERVER_RUNTIME_ENV = `${SERVER_ENV}/runtime`;
10
+ const SERVER_RUNTIME_LOADER = `${SERVER_RUNTIME_ENV}/loader`;
11
+ const DEFAULT_SERVER_PREFIX = "SERVER_";
12
+ const DEFAULT_CLIENT_PREFIX = "CLIENT_";
13
+ const SERVER_ONLY_MODULE = `throw new Error('Attempt to load server-only environment variables in client runtime.');`;
14
+ const SERVER_RUNTIME_CODE = `import load from '${SERVER_RUNTIME_LOADER}';
15
+
16
+ export default new Proxy({}, {
17
+ get(_, key) {
18
+ return load(key);
19
+ },
20
+ })`;
21
+ function convertObjectToModule(object) {
22
+ let result = "";
23
+ for (const key in object) {
24
+ result += `export const ${key} = ${JSON.stringify(object[key])};`;
25
+ }
26
+ return result;
27
+ }
28
+ export function envPlugin(options) {
29
+ const currentOptions = options ?? {};
30
+ let env;
31
+ const serverPrefix = currentOptions.server?.prefix ?? DEFAULT_SERVER_PREFIX;
32
+ const clientPrefix = currentOptions.client?.prefix ?? DEFAULT_CLIENT_PREFIX;
33
+ const runtime = options?.server?.runtime ?? "node";
34
+ const runtimeCode = runtime in LOADERS ? LOADERS[runtime] : runtime;
35
+ return {
36
+ name: "solid-start:env",
37
+ enforce: "pre",
38
+ configResolved(config) {
39
+ env = config.mode !== "production" ? "development" : "production";
40
+ },
41
+ resolveId(id) {
42
+ if (id === SERVER_ENV ||
43
+ id === CLIENT_ENV ||
44
+ id === SERVER_RUNTIME_ENV ||
45
+ id === SERVER_RUNTIME_LOADER) {
46
+ return id;
47
+ }
48
+ return undefined;
49
+ },
50
+ load(id, opts) {
51
+ if (id === SERVER_ENV) {
52
+ if (!opts?.ssr) {
53
+ return SERVER_ONLY_MODULE;
54
+ }
55
+ const vars = currentOptions.server?.load
56
+ ? currentOptions.server.load(env)
57
+ : loadEnv(env, '.', serverPrefix);
58
+ return convertObjectToModule(vars);
59
+ }
60
+ if (id === CLIENT_ENV) {
61
+ const vars = currentOptions.client?.load
62
+ ? currentOptions.client.load(env)
63
+ : loadEnv(env, '.', clientPrefix);
64
+ return convertObjectToModule(vars);
65
+ }
66
+ if (id === SERVER_RUNTIME_LOADER) {
67
+ if (!opts?.ssr) {
68
+ return SERVER_ONLY_MODULE;
69
+ }
70
+ return runtimeCode;
71
+ }
72
+ if (id === SERVER_RUNTIME_ENV) {
73
+ if (!opts?.ssr) {
74
+ return SERVER_ONLY_MODULE;
75
+ }
76
+ return SERVER_RUNTIME_CODE;
77
+ }
78
+ return undefined;
79
+ },
80
+ };
81
+ }
@@ -1,3 +1,5 @@
1
+ import { debounce } from "../../utils/debounce.js";
2
+ import { VITE_ENVIRONMENTS } from "../constants.js";
1
3
  import { moduleId } from "./index.js";
2
4
  function setupWatcher(watcher, routes) {
3
5
  watcher.on("unlink", path => routes.removeRoute(path));
@@ -5,44 +7,46 @@ function setupWatcher(watcher, routes) {
5
7
  watcher.on("change", path => routes.updateRoute(path));
6
8
  }
7
9
  function createRoutesReloader(server, routes, environment) {
8
- routes.addEventListener("reload", handleRoutesReload);
9
- return () => routes.removeEventListener("reload", handleRoutesReload);
10
- function handleRoutesReload() {
11
- if (environment === "ssr") {
12
- // Handle server environment HMR reload
13
- const serverEnv = server.environments.server;
14
- if (serverEnv && serverEnv.moduleGraph) {
15
- const mod = serverEnv.moduleGraph.getModuleById(moduleId);
16
- if (mod) {
17
- const seen = new Set();
18
- serverEnv.moduleGraph.invalidateModule(mod, seen);
19
- }
20
- }
10
+ const devEnv = server.environments[environment];
11
+ if (!devEnv?.moduleGraph)
12
+ return;
13
+ /**
14
+ * Debounce catches multiple route changes in a row
15
+ * Short timeout for inexpensive invalidations
16
+ */
17
+ const invalidateModule = debounce((mod) => {
18
+ devEnv.moduleGraph.invalidateModule(mod);
19
+ }, 0);
20
+ /**
21
+ * Long debounce timeout for expensive reloads
22
+ */
23
+ const reloadModule = debounce((mod) => {
24
+ devEnv.reloadModule(mod);
25
+ }, 200);
26
+ return routes.on("reload", function handleRoutesReload(evt) {
27
+ const mod = devEnv.moduleGraph.getModuleById(moduleId);
28
+ if (!mod) {
29
+ devEnv.hot.send({ type: "full-reload" });
30
+ return;
21
31
  }
22
- else {
23
- // Handle client environment HMR reload
24
- const { moduleGraph } = server;
25
- const mod = moduleGraph.getModuleById(moduleId);
26
- if (mod) {
27
- const seen = new Set();
28
- moduleGraph.invalidateModule(mod, seen);
29
- server.reloadModule(mod);
30
- }
32
+ if (environment === VITE_ENVIRONMENTS.client && evt.detail.type !== "update") {
33
+ // Client has to be reloaded when routes are added or removed
34
+ reloadModule(mod);
31
35
  }
32
- if (!server.hot) {
33
- server.ws.send({ type: "full-reload" });
36
+ else {
37
+ invalidateModule(mod);
34
38
  }
35
- }
39
+ });
36
40
  }
37
41
  export const fileSystemWatcher = (routers) => {
38
42
  const plugin = {
39
43
  name: "fs-watcher",
40
44
  async configureServer(server) {
41
- Object.keys(routers).forEach(environment => {
42
- const router = globalThis.ROUTERS[environment];
45
+ for (const environment of [VITE_ENVIRONMENTS.server, VITE_ENVIRONMENTS.client]) {
46
+ const router = routers[environment];
43
47
  setupWatcher(server.watcher, router);
44
48
  createRoutesReloader(server, router, environment);
45
- });
49
+ }
46
50
  },
47
51
  };
48
52
  return plugin;
@@ -43,8 +43,8 @@ export function fsRoutes({ routers }) {
43
43
  const buildId = `${v.src}?${v.pick.map((p) => `pick=${p}`).join("&")}`;
44
44
  return {
45
45
  src: relative(root, buildId),
46
- build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined,
47
- import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`,
46
+ build: isBuild ? `_$() => import('${buildId}')$_` : undefined,
47
+ import: `_$() => import('${buildId}')$_`,
48
48
  };
49
49
  }
50
50
  return v;
@@ -10,6 +10,10 @@ type Route = {
10
10
  } & Record<string, any>;
11
11
  export declare function cleanPath(src: string, config: FileSystemRouterConfig): string;
12
12
  export declare function analyzeModule(src: string): readonly [imports: readonly import("es-module-lexer").ImportSpecifier[], exports: readonly import("es-module-lexer").ExportSpecifier[], facade: boolean, hasModuleSyntax: boolean];
13
+ type RouterEvent = CustomEvent<{
14
+ route: string;
15
+ type: "update" | "remove" | "add";
16
+ }>;
13
17
  export declare class BaseFileSystemRouter extends EventTarget {
14
18
  routes: Route[];
15
19
  config: FileSystemRouterConfig;
@@ -27,11 +31,12 @@ export declare class BaseFileSystemRouter extends EventTarget {
27
31
  * To be attached by vite plugin to the vite dev server
28
32
  */
29
33
  update: undefined;
30
- _addRoute(route: Route): void;
34
+ _addRoute(route: Route): boolean;
31
35
  addRoute(src: string): Promise<void>;
32
- reload(route: string): void;
33
- updateRoute(src: string): Promise<void>;
36
+ reload(route: string, type: "update" | "remove" | "add"): void;
37
+ updateRoute(src_: string): Promise<void>;
34
38
  removeRoute(src: string): void;
39
+ on(type: string, cb: (evt: RouterEvent) => void): () => void;
35
40
  buildRoutesPromise?: Promise<any[]>;
36
41
  getRoutes(): Promise<Route[]>;
37
42
  }
@@ -1,9 +1,9 @@
1
1
  import { init, parse } from "es-module-lexer";
2
2
  import esbuild from "esbuild";
3
3
  import fg from "fast-glob";
4
- import fs from "fs";
4
+ import fs from "node:fs";
5
5
  import micromatch from "micromatch";
6
- import { posix } from "path";
6
+ import { posix } from "node:path";
7
7
  import { pathToRegexp } from "path-to-regexp";
8
8
  import { normalizePath } from "vite";
9
9
  export { pathToRegexp };
@@ -71,8 +71,11 @@ export class BaseFileSystemRouter extends EventTarget {
71
71
  */
72
72
  update = undefined;
73
73
  _addRoute(route) {
74
- this.routes = this.routes.filter(r => r.path !== route.path);
74
+ const idx = this.routes.findIndex(r => r.path === route.path);
75
+ if (idx >= 0)
76
+ this.routes.splice(idx, 1);
75
77
  this.routes.push(route);
78
+ return idx >= 0;
76
79
  }
77
80
  async addRoute(src) {
78
81
  src = normalizePath(src);
@@ -81,7 +84,7 @@ export class BaseFileSystemRouter extends EventTarget {
81
84
  const route = this.toRoute(src);
82
85
  if (route) {
83
86
  this._addRoute(route);
84
- this.reload(route.path);
87
+ this.reload(route.path, "add");
85
88
  }
86
89
  }
87
90
  catch (e) {
@@ -89,22 +92,25 @@ export class BaseFileSystemRouter extends EventTarget {
89
92
  }
90
93
  }
91
94
  }
92
- reload(route) {
93
- this.dispatchEvent(new Event("reload", {
94
- // @ts-ignore
95
+ reload(route, type) {
96
+ this.dispatchEvent(new CustomEvent("reload", {
95
97
  detail: {
96
98
  route,
99
+ type,
97
100
  },
98
101
  }));
99
102
  }
100
- async updateRoute(src) {
101
- src = normalizePath(src);
103
+ async updateRoute(src_) {
104
+ const src = normalizePath(src_);
102
105
  if (this.isRoute(src)) {
103
106
  try {
104
107
  const route = this.toRoute(src);
105
108
  if (route) {
106
- this._addRoute(route);
107
- this.reload(route.path);
109
+ const updated = this._addRoute(route);
110
+ this.reload(route.path, updated ? "update" : "add");
111
+ }
112
+ else {
113
+ this.removeRoute(src_);
108
114
  }
109
115
  }
110
116
  catch (e) {
@@ -120,10 +126,17 @@ export class BaseFileSystemRouter extends EventTarget {
120
126
  if (path === undefined) {
121
127
  return;
122
128
  }
123
- this.routes = this.routes.filter(r => r.path !== path);
124
- this.dispatchEvent(new Event("reload", {}));
129
+ const idx = this.routes.findIndex(r => r.path === path);
130
+ if (idx === -1)
131
+ return;
132
+ this.routes.splice(idx, 1);
133
+ this.reload(path, "remove");
125
134
  }
126
135
  }
136
+ on(type, cb) {
137
+ this.addEventListener(type, cb);
138
+ return () => this.removeEventListener(type, cb);
139
+ }
127
140
  buildRoutesPromise;
128
141
  async getRoutes() {
129
142
  if (!this.buildRoutesPromise) {
@@ -260,9 +260,6 @@ function treeShakeTransform({ types: t }) {
260
260
  };
261
261
  }
262
262
  export function treeShake() {
263
- let config;
264
- const cache = {};
265
- let server;
266
263
  async function transform(id, code) {
267
264
  const [path, queryString] = id.split("?");
268
265
  const query = new URLSearchParams(queryString);
@@ -286,44 +283,6 @@ export function treeShake() {
286
283
  return {
287
284
  name: "tree-shake",
288
285
  enforce: "pre",
289
- configResolved(resolvedConfig) {
290
- config = resolvedConfig;
291
- },
292
- configureServer(s) {
293
- server = s;
294
- },
295
- async handleHotUpdate(ctx) {
296
- if (cache[ctx.file]) {
297
- const mods = [];
298
- const newCode = await ctx.read();
299
- for (const [id, code] of Object.entries(cache[ctx.file])) {
300
- const transformed = await transform(id, newCode);
301
- if (!transformed)
302
- continue;
303
- const { code: transformedCode } = transformed;
304
- if (transformedCode !== code) {
305
- const mod = server.moduleGraph.getModuleById(id);
306
- if (mod)
307
- mods.push(mod);
308
- }
309
- cache[ctx.file] ??= {};
310
- cache[ctx.file][id] = transformedCode;
311
- // server.moduleGraph.setModuleSource(id, code);
312
- }
313
- return mods;
314
- }
315
- // const mods = [];
316
- // [...server.moduleGraph.urlToModuleMap.entries()].forEach(([url, m]) => {
317
- // if (m.file === ctx.file && m.id.includes("pick=")) {
318
- // if (!m.id.includes("pick=loader")) {
319
- // mods.push(m);
320
- // }
321
- // }
322
- // });
323
- // return mods;
324
- // // this.router.updateRoute(ctx.path);
325
- // }
326
- },
327
286
  async transform(code, id) {
328
287
  const [path, queryString] = id.split("?");
329
288
  if (!path)
@@ -336,8 +295,6 @@ export function treeShake() {
336
295
  const transformed = await transform(id, code);
337
296
  if (!transformed?.code)
338
297
  return;
339
- cache[path] ??= {};
340
- cache[path][id] = transformed.code;
341
298
  return {
342
299
  code: transformed.code,
343
300
  map: transformed.map,
@@ -1,10 +1,25 @@
1
- import { type PluginOption } from "vite";
1
+ import type { PluginOption } from "vite";
2
2
  import { type Options as SolidOptions } from "vite-plugin-solid";
3
+ import { type ServerFunctionsOptions } from "../directives/index.ts";
4
+ import { type EnvPluginOptions } from "./env.ts";
3
5
  export interface SolidStartOptions {
4
6
  solid?: Partial<SolidOptions>;
5
7
  ssr?: boolean;
6
8
  routeDir?: string;
7
9
  extensions?: string[];
8
10
  middleware?: string;
11
+ serialization?: {
12
+ /**
13
+ * The serialization mode to use for server functions/actions.
14
+ * The "js" mode uses a custom binary format that is more efficient than JSON, but requires a custom deserializer (with `eval()`) on the client.
15
+ * A strong CSP should block `eval()` executions, which would prevent the "js" mode from working.
16
+ * The "json" mode uses JSON for serialization, which is less efficient but can be deserialized with `JSON.parse` on the client.
17
+ *
18
+ * @default "json"
19
+ */
20
+ mode?: "js" | "json";
21
+ };
22
+ env?: EnvPluginOptions;
23
+ serverFunctions?: Pick<ServerFunctionsOptions, "filter">;
9
24
  }
10
25
  export declare function solidStart(options?: SolidStartOptions): Array<PluginOption>;
@@ -1,12 +1,11 @@
1
- import { TanStackServerFnPlugin } from "@tanstack/server-functions-plugin";
2
1
  import { defu } from "defu";
3
2
  import { globSync } from "node:fs";
4
3
  import { extname, isAbsolute, join } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { normalizePath } from "vite";
7
4
  import solid from "vite-plugin-solid";
5
+ import { serverFunctionsPlugin } from "../directives/index.js";
8
6
  import { DEFAULT_EXTENSIONS, VIRTUAL_MODULES, VITE_ENVIRONMENTS } from "./constants.js";
9
7
  import { devServer } from "./dev-server.js";
8
+ import { envPlugin } from "./env.js";
10
9
  import { SolidStartClientFileRouter, SolidStartServerFileRouter } from "./fs-router.js";
11
10
  import { fsRoutes } from "./fs-routes/index.js";
12
11
  import lazy from "./lazy.js";
@@ -38,6 +37,18 @@ export function solidStart(options) {
38
37
  server: `${start.appRoot}/entry-server${entryExtension}`,
39
38
  };
40
39
  return [
40
+ // TODO (Alexis): check if the comment below is still relevant
41
+ //
42
+ // Must be placed after fsRoutes, as treeShake will remove the
43
+ // server fn exports added in by this plugin
44
+ serverFunctionsPlugin({
45
+ manifest: VIRTUAL_MODULES.serverFnManifest,
46
+ runtime: {
47
+ server: '@solidjs/start/fns/server',
48
+ client: '@solidjs/start/fns/client',
49
+ },
50
+ filter: options?.serverFunctions?.filter,
51
+ }),
41
52
  {
42
53
  name: "solid-start:config",
43
54
  enforce: "pre",
@@ -67,6 +78,16 @@ export function solidStart(options) {
67
78
  return {
68
79
  appType: "custom",
69
80
  build: { assetsDir: "_build/assets" },
81
+ optimizeDeps: {
82
+ // Suppress TS errors from Vite 7 types when configuring Vite 8's Rolldown
83
+ ...{
84
+ rolldownOptions: {
85
+ transform: {
86
+ jsx: "react",
87
+ },
88
+ },
89
+ },
90
+ },
70
91
  environments: {
71
92
  [VITE_ENVIRONMENTS.client]: {
72
93
  consumer: "client",
@@ -109,6 +130,9 @@ export function solidStart(options) {
109
130
  }
110
131
  : {}),
111
132
  },
133
+ // Depending on the package manager and dependency structure Vite externalizes @solidjs/start
134
+ // This makes sure that @solidjs/start goes through the Vite build process
135
+ noExternal: ["@solidjs/start"],
112
136
  },
113
137
  define: {
114
138
  "import.meta.env.MANIFEST": `globalThis.MANIFEST`,
@@ -118,6 +142,7 @@ export function solidStart(options) {
118
142
  "import.meta.env.START_APP_ENTRY": JSON.stringify(appEntryPath),
119
143
  "import.meta.env.START_CLIENT_ENTRY": JSON.stringify(handlers.client),
120
144
  "import.meta.env.START_DEV_OVERLAY": JSON.stringify(start.devOverlay),
145
+ "import.meta.env.SEROVAL_MODE": JSON.stringify(start.serialization?.mode || "json"),
121
146
  },
122
147
  builder: {
123
148
  sharedPlugins: true,
@@ -152,33 +177,7 @@ export function solidStart(options) {
152
177
  },
153
178
  }),
154
179
  lazy(),
155
- // Must be placed after fsRoutes, as treeShake will remove the
156
- // server fn exports added in by this plugin
157
- TanStackServerFnPlugin({
158
- // This is the ID that will be available to look up and import
159
- // our server function manifest and resolve its module
160
- manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,
161
- directive: "use server",
162
- callers: [
163
- {
164
- envConsumer: "client",
165
- envName: VITE_ENVIRONMENTS.client,
166
- getRuntimeCode: () => `import { createServerReference } from "${normalizePath(fileURLToPath(new URL("../server/server-runtime", import.meta.url)))}"`,
167
- replacer: opts => `createServerReference('${opts.functionId}')`,
168
- },
169
- {
170
- envConsumer: "server",
171
- envName: VITE_ENVIRONMENTS.server,
172
- getRuntimeCode: () => `import { createServerReference } from '${normalizePath(fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)))}'`,
173
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
174
- },
175
- ],
176
- provider: {
177
- envName: VITE_ENVIRONMENTS.server,
178
- getRuntimeCode: () => `import { createServerReference } from '${normalizePath(fileURLToPath(new URL("../server/server-fns-runtime", import.meta.url)))}'`,
179
- replacer: opts => `createServerReference(${opts.fn}, '${opts.functionId}')`,
180
- },
181
- }),
180
+ envPlugin(options?.env),
182
181
  {
183
182
  name: "solid-start:virtual-modules",
184
183
  async resolveId(id) {
@@ -203,8 +202,9 @@ export function solidStart(options) {
203
202
  {
204
203
  name: "solid-start:capture-client-bundle",
205
204
  enforce: "post",
206
- generateBundle(_options, bundle) {
205
+ generateBundle(options, bundle) {
207
206
  globalThis.START_CLIENT_BUNDLE = bundle;
207
+ globalThis.START_CLIENT_OUT_DIR = options.dir;
208
208
  },
209
209
  },
210
210
  devServer(),
@@ -1,7 +1,7 @@
1
1
  import babel from "@babel/core";
2
2
  import * as t from "@babel/types";
3
- import { sep as osSep } from "path";
4
- import { basename, relative, sep } from "path/posix";
3
+ import { sep as osSep } from "node:path";
4
+ import { basename, relative, sep } from "node:path/posix";
5
5
  import { VITE_ENVIRONMENTS } from "./constants.js";
6
6
  const idTransform = (id) => {
7
7
  return {
@@ -77,6 +77,8 @@ const lazy = () => {
77
77
  // Therefore we skip, if the src doesn't have any import
78
78
  if (src.indexOf("import") === -1)
79
79
  return;
80
+ if (id.includes("entry-server"))
81
+ return;
80
82
  const plugins = [];
81
83
  const hasDefaultExport = src.indexOf("export default") !== -1;
82
84
  if (hasDefaultExport) {