@solidjs/start 2.0.0-beta.9 → 2.0.0-rc.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 +149 -1
- package/dist/config/app-root-alias.d.ts +7 -0
- package/dist/config/app-root-alias.js +58 -0
- package/dist/config/constants.d.ts +2 -0
- package/dist/config/constants.js +2 -0
- package/dist/config/env.js +13 -10
- package/dist/config/fs-routes/index.js +3 -3
- package/dist/config/fs-routes/tree-shake.d.ts +27 -0
- package/dist/config/fs-routes/tree-shake.js +226 -33
- package/dist/config/index.d.ts +154 -5
- package/dist/config/index.js +23 -10
- package/dist/config/lazy.js +7 -2
- package/dist/config/manifest.d.ts +3 -0
- package/dist/config/manifest.js +26 -4
- package/dist/directives/remove-unused-variables.js +15 -3
- package/dist/directives/xxhash32.js +5 -13
- package/dist/fns/client.js +14 -5
- package/dist/fns/error-handler.d.ts +34 -0
- package/dist/fns/error-handler.js +10 -0
- package/dist/fns/handler.d.ts +1 -1
- package/dist/fns/handler.js +58 -12
- package/dist/fns/plugins.d.ts +34 -0
- package/dist/fns/plugins.js +33 -0
- package/dist/fns/serialization.d.ts +15 -0
- package/dist/fns/serialization.js +36 -6
- package/dist/middleware/index.js +4 -1
- package/dist/server/StartServer.jsx +1 -1
- package/dist/server/assets/render.jsx +1 -1
- package/dist/server/collect-styles.d.ts +3 -1
- package/dist/server/collect-styles.js +8 -5
- package/dist/server/fetchEvent.d.ts +10 -0
- package/dist/server/fetchEvent.js +10 -0
- package/dist/server/handler.d.ts +3 -4
- package/dist/server/handler.js +22 -56
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.jsx +1 -0
- package/dist/server/manifest/dev-client-manifest.js +1 -1
- package/dist/server/manifest/dev-ssr-manifest.js +1 -1
- package/dist/server/spa/StartServer.jsx +1 -1
- package/dist/server/spa/handler.d.ts +2 -3
- package/dist/server/spa/handler.js +2 -2
- package/dist/server/strip-path-base.d.ts +1 -0
- package/dist/server/strip-path-base.js +10 -0
- package/dist/server/types.d.ts +12 -1
- package/dist/server/web-stream.d.ts +9 -0
- package/dist/server/web-stream.js +29 -0
- package/dist/shared/ErrorBoundary.jsx +3 -3
- package/dist/shared/clientOnly.js +3 -1
- package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.jsx +3 -3
- package/dist/shared/dev-toolbar/error-viewer/create-stack-frame.js +90 -0
- package/dist/shared/{dev-overlay/DevOverlayDialog.d.ts → dev-toolbar/error-viewer/index.d.ts} +3 -2
- package/dist/shared/{dev-overlay/DevOverlayDialog.jsx → dev-toolbar/error-viewer/index.jsx} +66 -77
- package/dist/shared/dev-toolbar/error-viewer/styles.css +224 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.css +4 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/BlobViewer.jsx +37 -0
- package/dist/shared/dev-toolbar/functions/FormDataViewer.d.ts +5 -0
- package/dist/shared/dev-toolbar/functions/FormDataViewer.jsx +23 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.css +8 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/HeadersViewer.jsx +15 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.css +34 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.d.ts +11 -0
- package/dist/shared/dev-toolbar/functions/HexViewer.jsx +70 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.css +5 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.d.ts +7 -0
- package/dist/shared/dev-toolbar/functions/SerovalValue.jsx +10 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.css +70 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.d.ts +6 -0
- package/dist/shared/dev-toolbar/functions/SerovalViewer.jsx +796 -0
- package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.d.ts +5 -0
- package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.jsx +22 -0
- package/dist/shared/dev-toolbar/functions/index.d.ts +13 -0
- package/dist/shared/dev-toolbar/functions/index.jsx +216 -0
- package/dist/shared/dev-toolbar/functions/styles.css +109 -0
- package/dist/shared/dev-toolbar/functions/tracker.d.ts +19 -0
- package/dist/shared/dev-toolbar/functions/tracker.js +29 -0
- package/dist/shared/{dev-overlay → dev-toolbar}/icons.d.ts +9 -0
- package/dist/shared/{dev-overlay → dev-toolbar}/icons.jsx +19 -1
- package/dist/shared/dev-toolbar/index.css +88 -0
- package/dist/shared/dev-toolbar/index.d.ts +6 -0
- package/dist/shared/dev-toolbar/index.jsx +179 -0
- package/dist/shared/ui/Badge.css +33 -0
- package/dist/shared/ui/Badge.d.ts +7 -0
- package/dist/shared/ui/Badge.jsx +7 -0
- package/dist/shared/ui/Button.css +32 -0
- package/dist/shared/ui/Button.d.ts +4 -0
- package/dist/shared/ui/Button.jsx +4 -0
- package/dist/shared/ui/Cascade.css +29 -0
- package/dist/shared/ui/Cascade.d.ts +4 -0
- package/dist/shared/ui/Cascade.jsx +4 -0
- package/dist/shared/ui/Dialog.css +25 -0
- package/dist/shared/ui/Dialog.d.ts +5 -0
- package/dist/shared/ui/Dialog.jsx +5 -0
- package/dist/shared/ui/IconButton.css +39 -0
- package/dist/shared/ui/IconButton.d.ts +4 -0
- package/dist/shared/ui/IconButton.jsx +4 -0
- package/dist/shared/ui/Placeholder.css +12 -0
- package/dist/shared/ui/Placeholder.d.ts +6 -0
- package/dist/shared/ui/Placeholder.jsx +4 -0
- package/dist/shared/ui/Section.css +18 -0
- package/dist/shared/ui/Section.d.ts +9 -0
- package/dist/shared/ui/Section.jsx +10 -0
- package/dist/shared/ui/Select.css +37 -0
- package/dist/shared/ui/Select.d.ts +4 -0
- package/dist/shared/ui/Select.jsx +4 -0
- package/dist/shared/ui/Table.css +22 -0
- package/dist/shared/ui/Table.d.ts +11 -0
- package/dist/shared/ui/Table.jsx +13 -0
- package/dist/shared/ui/Tabs.css +51 -0
- package/dist/shared/ui/Tabs.d.ts +6 -0
- package/dist/shared/ui/Tabs.jsx +6 -0
- package/dist/shared/ui/Text.css +73 -0
- package/dist/shared/ui/Text.d.ts +12 -0
- package/dist/shared/ui/Text.jsx +17 -0
- package/package.json +36 -29
- package/dist/shared/dev-overlay/createStackFrame.js +0 -56
- package/dist/shared/dev-overlay/index.d.ts +0 -5
- package/dist/shared/dev-overlay/index.jsx +0 -39
- package/dist/shared/dev-overlay/styles.css +0 -292
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/CodeView.d.ts +0 -0
- /package/dist/shared/{dev-overlay/createStackFrame.d.ts → dev-toolbar/error-viewer/create-stack-frame.d.ts} +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.d.ts +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/download.js +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.d.ts +0 -0
- /package/dist/shared/{dev-overlay → dev-toolbar/error-viewer}/get-source-map.js +0 -0
|
@@ -1,7 +1,52 @@
|
|
|
1
1
|
// All credit for this work goes to the amazing Next.js team.
|
|
2
2
|
// https://github.com/vercel/next.js/blob/canary/packages/next/build/babel/plugins/next-ssg-transform.ts
|
|
3
3
|
// This is adapted to work with routeData functions. It can be run in two modes, one which preserves the routeData and the Component in the same file, and one which creates a
|
|
4
|
-
import { basename } from "pathe";
|
|
4
|
+
import { basename, extname } from "pathe";
|
|
5
|
+
const PICKABLE_EXTENSIONS = ["js", "jsx", "ts", "tsx"];
|
|
6
|
+
/**
|
|
7
|
+
* Builds the module id used to import a subset of a route file's exports.
|
|
8
|
+
*
|
|
9
|
+
* The `pick` list has to live in the query so that the same file can be
|
|
10
|
+
* instantiated once per export subset (the client picks `default`/`$css`,
|
|
11
|
+
* the server picks its HTTP handlers). That query would otherwise leave the
|
|
12
|
+
* id ending in `?pick=GET`, which silently excludes route files from any
|
|
13
|
+
* plugin whose filter is anchored on the file extension -- a very common
|
|
14
|
+
* default, e.g. unplugin-macros' `/\.[cm]?[jt]sx?$/`.
|
|
15
|
+
*
|
|
16
|
+
* The trailing `lang.<ext>` marker is the same convention Vue SFCs use
|
|
17
|
+
* (`?vue&type=script&lang.ts`) and puts a real extension back at the end of
|
|
18
|
+
* the id, so those filters match again.
|
|
19
|
+
*
|
|
20
|
+
* @see https://github.com/solidjs/solid-start/issues/1918
|
|
21
|
+
*/
|
|
22
|
+
export function toPickId(src, pick) {
|
|
23
|
+
const query = pick.map(p => `pick=${p}`).join("&");
|
|
24
|
+
const ext = extname(src).slice(1);
|
|
25
|
+
return PICKABLE_EXTENSIONS.includes(ext) ? `${src}?${query}&lang.${ext}` : `${src}?${query}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Matches the tail that {@link toPickId} appends, as it appears in a chunk
|
|
29
|
+
* name. Rolldown derives a chunk name from the module id by taking the
|
|
30
|
+
* basename minus its extension, so `index.tsx?pick=default&pick=$css&lang.tsx`
|
|
31
|
+
* arrives here as `index.tsx?pick=default&pick=$css&lang`.
|
|
32
|
+
*/
|
|
33
|
+
const PICK_CHUNK_NAME_RE = /\.[cm]?[jt]sx?\?pick=[^?]*&lang$/;
|
|
34
|
+
const INVALID_CHAR_RE = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g;
|
|
35
|
+
const DRIVE_LETTER_RE = /^[a-z]:/i;
|
|
36
|
+
/**
|
|
37
|
+
* Rolldown's default chunk name sanitizer, plus a pass that drops the
|
|
38
|
+
* `?pick=...&lang` tail so route chunks keep the short, stable filenames they
|
|
39
|
+
* had before the `lang` marker was introduced (`index-<hash>.js`, not
|
|
40
|
+
* `index.tsx_pick_default_pick__css_lang-<hash>.js`). Client chunk filenames
|
|
41
|
+
* are public URLs, so this is not purely cosmetic.
|
|
42
|
+
*
|
|
43
|
+
* @see https://github.com/rollup/rollup/blob/master/src/utils/sanitizeFileName.ts
|
|
44
|
+
*/
|
|
45
|
+
export function sanitizeChunkFileName(name) {
|
|
46
|
+
const stripped = name.replace(PICK_CHUNK_NAME_RE, "");
|
|
47
|
+
const driveLetter = DRIVE_LETTER_RE.exec(stripped)?.[0] ?? "";
|
|
48
|
+
return driveLetter + stripped.slice(driveLetter.length).replace(INVALID_CHAR_RE, "_");
|
|
49
|
+
}
|
|
5
50
|
function treeShakeTransform({ types: t }) {
|
|
6
51
|
function getIdentifier(path) {
|
|
7
52
|
const parentPath = path.parentPath;
|
|
@@ -20,13 +65,28 @@ function treeShakeTransform({ types: t }) {
|
|
|
20
65
|
}
|
|
21
66
|
return path.node.id && path.node.id.type === "Identifier" ? path.get("id") : null;
|
|
22
67
|
}
|
|
23
|
-
function
|
|
68
|
+
function isTypeOnlyReference(path) {
|
|
69
|
+
return path.getAncestry().some(parent => {
|
|
70
|
+
if (parent.isTSType())
|
|
71
|
+
return true;
|
|
72
|
+
if (parent.isExportNamedDeclaration())
|
|
73
|
+
return parent.node.exportKind === "type";
|
|
74
|
+
if (parent.isExportSpecifier())
|
|
75
|
+
return parent.node.exportKind === "type";
|
|
76
|
+
return false;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function runtimeReferences(binding) {
|
|
80
|
+
return binding.referencePaths.filter(ref => !isTypeOnlyReference(ref));
|
|
81
|
+
}
|
|
82
|
+
function isIdentifierReferenced(ident, includeTypes = false) {
|
|
24
83
|
const b = ident.scope.getBinding(ident.node.name);
|
|
25
|
-
if (b
|
|
84
|
+
if (b) {
|
|
85
|
+
const references = b.constantViolations.concat(includeTypes ? b.referencePaths : runtimeReferences(b));
|
|
86
|
+
if (!references.length)
|
|
87
|
+
return false;
|
|
26
88
|
if (b.path.type === "FunctionDeclaration") {
|
|
27
|
-
return !b.
|
|
28
|
-
.concat(b.referencePaths)
|
|
29
|
-
.every(ref => ref.findParent(p => p === b.path));
|
|
89
|
+
return !references.every(ref => ref.findParent(p => p === b.path));
|
|
30
90
|
}
|
|
31
91
|
return true;
|
|
32
92
|
}
|
|
@@ -34,13 +94,13 @@ function treeShakeTransform({ types: t }) {
|
|
|
34
94
|
}
|
|
35
95
|
function markFunction(path, state) {
|
|
36
96
|
const ident = getIdentifier(path);
|
|
37
|
-
if (ident && ident.node && isIdentifierReferenced(ident)) {
|
|
97
|
+
if (ident && ident.node && isIdentifierReferenced(ident, true)) {
|
|
38
98
|
state.refs.add(ident);
|
|
39
99
|
}
|
|
40
100
|
}
|
|
41
101
|
function markImport(path, state) {
|
|
42
102
|
const local = path.get("local");
|
|
43
|
-
if (isIdentifierReferenced(local)) {
|
|
103
|
+
if (isIdentifierReferenced(local, true)) {
|
|
44
104
|
state.refs.add(local);
|
|
45
105
|
}
|
|
46
106
|
}
|
|
@@ -49,12 +109,13 @@ function treeShakeTransform({ types: t }) {
|
|
|
49
109
|
Program: {
|
|
50
110
|
enter(path, state) {
|
|
51
111
|
state.refs = new Set();
|
|
112
|
+
state.candidates = new Set();
|
|
52
113
|
state.done = false;
|
|
53
114
|
path.traverse({
|
|
54
115
|
VariableDeclarator(variablePath, variableState) {
|
|
55
116
|
if (variablePath.node.id.type === "Identifier") {
|
|
56
117
|
const local = variablePath.get("id");
|
|
57
|
-
if (isIdentifierReferenced(local)) {
|
|
118
|
+
if (isIdentifierReferenced(local, true)) {
|
|
58
119
|
variableState.refs.add(local);
|
|
59
120
|
}
|
|
60
121
|
}
|
|
@@ -69,7 +130,7 @@ function treeShakeTransform({ types: t }) {
|
|
|
69
130
|
: (() => {
|
|
70
131
|
throw new Error("invariant");
|
|
71
132
|
})());
|
|
72
|
-
if (isIdentifierReferenced(local)) {
|
|
133
|
+
if (isIdentifierReferenced(local, true)) {
|
|
73
134
|
variableState.refs.add(local);
|
|
74
135
|
}
|
|
75
136
|
});
|
|
@@ -88,29 +149,46 @@ function treeShakeTransform({ types: t }) {
|
|
|
88
149
|
else {
|
|
89
150
|
return;
|
|
90
151
|
}
|
|
91
|
-
if (isIdentifierReferenced(local)) {
|
|
152
|
+
if (isIdentifierReferenced(local, true)) {
|
|
92
153
|
variableState.refs.add(local);
|
|
93
154
|
}
|
|
94
155
|
});
|
|
95
156
|
}
|
|
96
157
|
},
|
|
97
158
|
ExportDefaultDeclaration(exportNamedPath) {
|
|
98
|
-
// if opts.keep is true, we don't remove the routeData export
|
|
99
159
|
if (state.opts.pick && !state.opts.pick.includes("default")) {
|
|
100
|
-
exportNamedPath.
|
|
160
|
+
const decl = exportNamedPath.node.declaration;
|
|
161
|
+
// A named function/class declaration creates a module-scope
|
|
162
|
+
// binding that picked exports may reference, so only strip
|
|
163
|
+
// the `export default`; the sweep below removes the
|
|
164
|
+
// declaration again if nothing references it.
|
|
165
|
+
if ((t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) && decl.id) {
|
|
166
|
+
const [newPath] = exportNamedPath.replaceWith(decl);
|
|
167
|
+
const id = newPath.get("id");
|
|
168
|
+
state.refs.add(id);
|
|
169
|
+
state.candidates.add(id);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
exportNamedPath.remove();
|
|
173
|
+
}
|
|
101
174
|
}
|
|
102
175
|
},
|
|
103
176
|
ExportNamedDeclaration(exportNamedPath) {
|
|
104
|
-
//
|
|
177
|
+
// No pick list means nothing gets pruned.
|
|
105
178
|
if (!state.opts.pick) {
|
|
106
179
|
return;
|
|
107
180
|
}
|
|
181
|
+
// Only module-level exports are route exports; `export` inside a
|
|
182
|
+
// TS namespace/module block is unrelated to the pick list.
|
|
183
|
+
if (!exportNamedPath.parentPath.isProgram()) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
108
186
|
const specifiers = exportNamedPath.get("specifiers");
|
|
109
187
|
if (specifiers.length) {
|
|
110
188
|
specifiers.forEach(s => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
189
|
+
const exported = s.node.exported;
|
|
190
|
+
const exportedName = t.isIdentifier(exported) ? exported.name : exported.value;
|
|
191
|
+
if (!state.opts.pick.includes(exportedName)) {
|
|
114
192
|
s.remove();
|
|
115
193
|
}
|
|
116
194
|
});
|
|
@@ -124,24 +202,51 @@ function treeShakeTransform({ types: t }) {
|
|
|
124
202
|
return;
|
|
125
203
|
}
|
|
126
204
|
switch (decl.node.type) {
|
|
127
|
-
case "FunctionDeclaration":
|
|
205
|
+
case "FunctionDeclaration":
|
|
206
|
+
case "ClassDeclaration": {
|
|
128
207
|
const name = decl.node.id?.name;
|
|
129
208
|
if (name && state.opts.pick && !state.opts.pick.includes(name)) {
|
|
130
|
-
|
|
209
|
+
// Keep the declaration in module scope since picked
|
|
210
|
+
// exports may reference it; the sweep below removes it
|
|
211
|
+
// again if unreferenced.
|
|
212
|
+
const [newPath] = exportNamedPath.replaceWith(decl.node);
|
|
213
|
+
const id = newPath.get("id");
|
|
214
|
+
state.refs.add(id);
|
|
215
|
+
state.candidates.add(id);
|
|
131
216
|
}
|
|
132
217
|
break;
|
|
133
218
|
}
|
|
134
219
|
case "VariableDeclaration": {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
220
|
+
const declNode = decl.node;
|
|
221
|
+
// Destructuring declarators are conservatively treated as
|
|
222
|
+
// picked (matching the previous behavior of leaving them
|
|
223
|
+
// untouched).
|
|
224
|
+
const isPicked = (d) => d.id.type !== "Identifier" || state.opts.pick.includes(d.id.name);
|
|
225
|
+
if (declNode.declarations.every(isPicked)) {
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
// Split into one declaration per declarator (preserving
|
|
229
|
+
// evaluation order) and export only the picked ones.
|
|
230
|
+
// Unpicked bindings are kept since picked exports may
|
|
231
|
+
// reference them; the sweep below removes them again if
|
|
232
|
+
// unreferenced.
|
|
233
|
+
const statements = declNode.declarations.map(d => {
|
|
234
|
+
const single = t.variableDeclaration(declNode.kind, [d]);
|
|
235
|
+
single.declare = declNode.declare;
|
|
236
|
+
return isPicked(d) ? t.exportNamedDeclaration(single, []) : single;
|
|
144
237
|
});
|
|
238
|
+
const newPaths = exportNamedPath.replaceWithMultiple(statements);
|
|
239
|
+
for (const p of newPaths) {
|
|
240
|
+
if (!p.isVariableDeclaration())
|
|
241
|
+
continue;
|
|
242
|
+
for (const d of p.get("declarations")) {
|
|
243
|
+
if (d.node.id.type === "Identifier") {
|
|
244
|
+
const id = d.get("id");
|
|
245
|
+
state.refs.add(id);
|
|
246
|
+
state.candidates.add(id);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
145
250
|
break;
|
|
146
251
|
}
|
|
147
252
|
default: {
|
|
@@ -152,6 +257,8 @@ function treeShakeTransform({ types: t }) {
|
|
|
152
257
|
FunctionDeclaration: markFunction,
|
|
153
258
|
FunctionExpression: markFunction,
|
|
154
259
|
ArrowFunctionExpression: markFunction,
|
|
260
|
+
ClassDeclaration: markFunction,
|
|
261
|
+
ClassExpression: markFunction,
|
|
155
262
|
ImportSpecifier: markImport,
|
|
156
263
|
ImportDefaultSpecifier: markImport,
|
|
157
264
|
ImportNamespaceSpecifier: markImport,
|
|
@@ -163,11 +270,95 @@ function treeShakeTransform({ types: t }) {
|
|
|
163
270
|
}
|
|
164
271
|
},
|
|
165
272
|
}, state);
|
|
273
|
+
// References alone cannot distinguish live bindings from dead cycles.
|
|
274
|
+
// Build a graph of localized exports and retain only those reachable
|
|
275
|
+
// from runtime code outside that graph.
|
|
276
|
+
path.scope.crawl();
|
|
277
|
+
const tracked = new Map();
|
|
278
|
+
const candidateOwners = new Map();
|
|
279
|
+
const addOwner = (owners, binding, owner) => {
|
|
280
|
+
const paths = owners.get(binding) ?? new Set();
|
|
281
|
+
paths.add(owner);
|
|
282
|
+
owners.set(binding, paths);
|
|
283
|
+
};
|
|
284
|
+
for (const identifier of state.refs) {
|
|
285
|
+
if (identifier.node?.type !== "Identifier" || !identifier.parentPath)
|
|
286
|
+
continue;
|
|
287
|
+
const binding = identifier.scope.getBinding(identifier.node.name);
|
|
288
|
+
if (binding)
|
|
289
|
+
addOwner(tracked, binding, identifier.parentPath);
|
|
290
|
+
}
|
|
291
|
+
for (const identifier of state.candidates) {
|
|
292
|
+
if (!identifier.parentPath)
|
|
293
|
+
continue;
|
|
294
|
+
const binding = identifier.scope.getBinding(identifier.node.name);
|
|
295
|
+
if (!binding)
|
|
296
|
+
continue;
|
|
297
|
+
addOwner(tracked, binding, identifier.parentPath);
|
|
298
|
+
addOwner(candidateOwners, binding, identifier.parentPath);
|
|
299
|
+
}
|
|
300
|
+
const dependencies = new Map();
|
|
301
|
+
const live = new Set();
|
|
302
|
+
for (const [binding, owners] of tracked) {
|
|
303
|
+
dependencies.set(binding, new Set());
|
|
304
|
+
if ([...owners].some(owner => owner.findParent(parent => parent.isExportNamedDeclaration() || parent.isExportDefaultDeclaration()))) {
|
|
305
|
+
live.add(binding);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const ownerBindings = new Map();
|
|
309
|
+
for (const [binding, owners] of tracked) {
|
|
310
|
+
for (const owner of owners) {
|
|
311
|
+
ownerBindings.set(owner, binding);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const owningBinding = (reference) => {
|
|
315
|
+
const owner = reference.find(parent => ownerBindings.has(parent));
|
|
316
|
+
return owner && ownerBindings.get(owner);
|
|
317
|
+
};
|
|
318
|
+
for (const target of tracked.keys()) {
|
|
319
|
+
const references = target.constantViolations.concat(runtimeReferences(target));
|
|
320
|
+
for (const reference of references) {
|
|
321
|
+
const source = owningBinding(reference);
|
|
322
|
+
if (source)
|
|
323
|
+
dependencies.get(source)?.add(target);
|
|
324
|
+
else
|
|
325
|
+
live.add(target);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const pending = [...live];
|
|
329
|
+
while (pending.length) {
|
|
330
|
+
const source = pending.pop();
|
|
331
|
+
for (const dependency of dependencies.get(source) ?? []) {
|
|
332
|
+
if (live.has(dependency))
|
|
333
|
+
continue;
|
|
334
|
+
live.add(dependency);
|
|
335
|
+
pending.push(dependency);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const deadCandidates = new Set([...candidateOwners.keys()].filter(candidate => !live.has(candidate)));
|
|
339
|
+
path.traverse({
|
|
340
|
+
VariableDeclarator(variablePath) {
|
|
341
|
+
if (variablePath.node.id.type !== "Identifier")
|
|
342
|
+
return;
|
|
343
|
+
const binding = variablePath.scope.getBinding(variablePath.node.id.name);
|
|
344
|
+
if (binding && deadCandidates.has(binding))
|
|
345
|
+
variablePath.remove();
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
for (const [candidate, owners] of candidateOwners) {
|
|
349
|
+
if (!deadCandidates.has(candidate))
|
|
350
|
+
continue;
|
|
351
|
+
for (const owner of owners) {
|
|
352
|
+
if (!owner.removed && !owner.isVariableDeclarator())
|
|
353
|
+
owner.remove();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
166
356
|
const refs = state.refs;
|
|
357
|
+
const refNodes = new Set([...refs].map(ref => ref.node));
|
|
167
358
|
let count = 0;
|
|
168
359
|
const sweepFunction = (sweepPath) => {
|
|
169
360
|
const ident = getIdentifier(sweepPath);
|
|
170
|
-
if (ident && ident.node &&
|
|
361
|
+
if (ident && ident.node && refNodes.has(ident.node) && !isIdentifierReferenced(ident)) {
|
|
171
362
|
++count;
|
|
172
363
|
if (t.isAssignmentExpression(sweepPath.parentPath) ||
|
|
173
364
|
t.isVariableDeclarator(sweepPath.parentPath)) {
|
|
@@ -180,7 +371,7 @@ function treeShakeTransform({ types: t }) {
|
|
|
180
371
|
};
|
|
181
372
|
function sweepImport(sweepPath) {
|
|
182
373
|
const local = sweepPath.get("local");
|
|
183
|
-
if (
|
|
374
|
+
if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
|
|
184
375
|
++count;
|
|
185
376
|
sweepPath.remove();
|
|
186
377
|
if (sweepPath.parent.specifiers.length === 0) {
|
|
@@ -195,7 +386,7 @@ function treeShakeTransform({ types: t }) {
|
|
|
195
386
|
VariableDeclarator(variablePath) {
|
|
196
387
|
if (variablePath.node.id.type === "Identifier") {
|
|
197
388
|
const local = variablePath.get("id");
|
|
198
|
-
if (
|
|
389
|
+
if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
|
|
199
390
|
++count;
|
|
200
391
|
variablePath.remove();
|
|
201
392
|
}
|
|
@@ -212,7 +403,7 @@ function treeShakeTransform({ types: t }) {
|
|
|
212
403
|
: (() => {
|
|
213
404
|
throw new Error("invariant");
|
|
214
405
|
})());
|
|
215
|
-
if (
|
|
406
|
+
if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
|
|
216
407
|
++count;
|
|
217
408
|
p.remove();
|
|
218
409
|
}
|
|
@@ -236,7 +427,7 @@ function treeShakeTransform({ types: t }) {
|
|
|
236
427
|
else {
|
|
237
428
|
return;
|
|
238
429
|
}
|
|
239
|
-
if (
|
|
430
|
+
if (refNodes.has(local.node) && !isIdentifierReferenced(local)) {
|
|
240
431
|
++count;
|
|
241
432
|
e.remove();
|
|
242
433
|
}
|
|
@@ -249,6 +440,8 @@ function treeShakeTransform({ types: t }) {
|
|
|
249
440
|
FunctionDeclaration: sweepFunction,
|
|
250
441
|
FunctionExpression: sweepFunction,
|
|
251
442
|
ArrowFunctionExpression: sweepFunction,
|
|
443
|
+
ClassDeclaration: sweepFunction,
|
|
444
|
+
ClassExpression: sweepFunction,
|
|
252
445
|
ImportSpecifier: sweepImport,
|
|
253
446
|
ImportDefaultSpecifier: sweepImport,
|
|
254
447
|
ImportNamespaceSpecifier: sweepImport,
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,25 +1,174 @@
|
|
|
1
|
-
import type { PluginOption } from "vite";
|
|
1
|
+
import type { PluginOption, FilterPattern } from "vite";
|
|
2
2
|
import { type Options as SolidOptions } from "vite-plugin-solid";
|
|
3
3
|
import { type ServerFunctionsOptions } from "../directives/index.ts";
|
|
4
4
|
import { type EnvPluginOptions } from "./env.ts";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for SolidStart. (previously in `app.config.ts`)
|
|
7
|
+
*
|
|
8
|
+
* @see https://docs.solidjs.com/solid-start/v2/migrating-from-v1#move-framework-configuration-into-viteconfigts
|
|
9
|
+
*/
|
|
5
10
|
export interface SolidStartOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Path to the root of the application (where `app.tsx` / `app.jsx` lives).
|
|
13
|
+
*
|
|
14
|
+
* @default "./src"
|
|
15
|
+
*/
|
|
16
|
+
appRoot?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Options related to the css crawling logic
|
|
19
|
+
*/
|
|
20
|
+
css?: {
|
|
21
|
+
/**
|
|
22
|
+
* Filter files included during css crawling in development.
|
|
23
|
+
*/
|
|
24
|
+
filter?: {
|
|
25
|
+
include?: FilterPattern;
|
|
26
|
+
exclude?: FilterPattern;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Options forwarded to `vite-plugin-solid`.
|
|
31
|
+
*
|
|
32
|
+
* @see https://github.com/solidjs/vite-plugin-solid#api
|
|
33
|
+
*/
|
|
6
34
|
solid?: Partial<SolidOptions>;
|
|
35
|
+
/**
|
|
36
|
+
* Enable or disable server-side rendering.
|
|
37
|
+
*
|
|
38
|
+
* - `true` — SSR (default)
|
|
39
|
+
* - `false` — client-side rendering only (SPA mode)
|
|
40
|
+
*
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
7
43
|
ssr?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Show the SolidStart development overlay (error overlay, etc.) in development.
|
|
46
|
+
*
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
devOverlay?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Experimental features.
|
|
52
|
+
*/
|
|
53
|
+
experimental?: {
|
|
54
|
+
/**
|
|
55
|
+
* Enable islands architecture mode.
|
|
56
|
+
*
|
|
57
|
+
* Currently fixed to `false` (not yet fully supported).
|
|
58
|
+
*
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
islands?: false;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Directory containing file-system routes, relative to {@link appRoot}.
|
|
65
|
+
*
|
|
66
|
+
* @default "./routes"
|
|
67
|
+
*/
|
|
8
68
|
routeDir?: string;
|
|
69
|
+
/**
|
|
70
|
+
* File extensions that should be treated as routes.
|
|
71
|
+
*
|
|
72
|
+
* @default ["js", "jsx", "ts", "tsx"]
|
|
73
|
+
*/
|
|
9
74
|
extensions?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* Path to an optional middleware module.
|
|
77
|
+
*
|
|
78
|
+
* The module should export a middleware created with `createMiddleware`
|
|
79
|
+
* from `@solidjs/start/middleware`.
|
|
80
|
+
*
|
|
81
|
+
* @example "src/middleware/index.ts"
|
|
82
|
+
*/
|
|
10
83
|
middleware?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Serialization settings for server-function / action payloads
|
|
86
|
+
* that cross the server-client boundary.
|
|
87
|
+
*/
|
|
11
88
|
serialization?: {
|
|
12
89
|
/**
|
|
13
90
|
* The serialization mode to use for server functions/actions.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
91
|
+
*
|
|
92
|
+
* - `"js"` — Uses a custom binary format (Seroval) that is more efficient
|
|
93
|
+
* than JSON, but requires a custom deserializer (with `eval()`) on the client.
|
|
94
|
+
* A strong CSP that blocks `eval()` will prevent this mode from working.
|
|
95
|
+
* - `"json"` — Uses JSON for serialization. Less efficient / larger payloads,
|
|
96
|
+
* but can be deserialized with `JSON.parse` on the client and is CSP-friendly.
|
|
17
97
|
*
|
|
18
98
|
* @default "json"
|
|
19
99
|
*/
|
|
20
100
|
mode?: "js" | "json";
|
|
101
|
+
/**
|
|
102
|
+
* Path to a module whose default export is an array of custom Seroval
|
|
103
|
+
* plugins, used to serialize values Seroval doesn't understand natively
|
|
104
|
+
* (ORM id types, decimals, `Temporal`, and other custom classes).
|
|
105
|
+
*
|
|
106
|
+
* Build plugins with `createPlugin` from `seroval`. The module is bundled
|
|
107
|
+
* into both the client and the server so that both ends of a server
|
|
108
|
+
* function agree on the format, so it must not import server-only code.
|
|
109
|
+
*
|
|
110
|
+
* SolidStart's built-in plugins take precedence: Seroval uses the first
|
|
111
|
+
* plugin whose `test()` passes, and these are appended after the built-ins.
|
|
112
|
+
*
|
|
113
|
+
* A plugin's `deserialize` rebuilds the value under {@link mode} `"json"`.
|
|
114
|
+
* `serialize` is only used by `mode: "js"`, where the payload is evaluated
|
|
115
|
+
* on the client and may therefore reference globals only, not the plugin
|
|
116
|
+
* module's own imports.
|
|
117
|
+
*
|
|
118
|
+
* Only applies to server-function and action payloads. The SSR hydration
|
|
119
|
+
* payload is serialized by `solid-js/web` and is unaffected.
|
|
120
|
+
*
|
|
121
|
+
* @example "src/seroval-plugins.ts"
|
|
122
|
+
*/
|
|
123
|
+
plugins?: string;
|
|
21
124
|
};
|
|
125
|
+
/**
|
|
126
|
+
* Configures plugin behavior per build environment
|
|
127
|
+
*/
|
|
22
128
|
env?: EnvPluginOptions;
|
|
23
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Options for server functions: which files the `"use server"` transform
|
|
131
|
+
* processes (inclusion / exclusion filters), and what happens when a server
|
|
132
|
+
* function throws.
|
|
133
|
+
*/
|
|
134
|
+
serverFunctions?: Pick<ServerFunctionsOptions, "filter"> & {
|
|
135
|
+
/**
|
|
136
|
+
* Path to a module whose default export handles whatever a server function
|
|
137
|
+
* throws, before it reaches the client. Use it to report failures to a
|
|
138
|
+
* monitoring service, or to replace an error carrying internal detail with
|
|
139
|
+
* one that is safe to send.
|
|
140
|
+
*
|
|
141
|
+
* Only server function calls made over the network run through it. A
|
|
142
|
+
* server function called during rendering runs in process and throws
|
|
143
|
+
* straight to its caller, and errors from API routes never reach it
|
|
144
|
+
* either.
|
|
145
|
+
*
|
|
146
|
+
* The handler may be asynchronous. SolidStart awaits its return value
|
|
147
|
+
* before serializing the response, allowing a monitoring service to flush
|
|
148
|
+
* first. The resolved value decides what the client sees:
|
|
149
|
+
*
|
|
150
|
+
* - `undefined` (or `null`) sends what was thrown, unchanged.
|
|
151
|
+
* - A `Response` is passed through unchanged, which keeps a thrown
|
|
152
|
+
* `redirect()` working.
|
|
153
|
+
* - Any other value is sent in place of what was thrown, and the client
|
|
154
|
+
* call rejects with it.
|
|
155
|
+
* - If the handler throws or rejects, what the server function threw is
|
|
156
|
+
* sent unchanged.
|
|
157
|
+
*
|
|
158
|
+
* Control flow reaches the export the same way errors do, so a handler
|
|
159
|
+
* that replaces everything it sees turns redirects into errors.
|
|
160
|
+
*
|
|
161
|
+
* Whatever is sent gets serialized to the client along with its own
|
|
162
|
+
* properties, so an error meant to be safe to expose must not carry
|
|
163
|
+
* internal detail.
|
|
164
|
+
*
|
|
165
|
+
* Type the export as `ServerFunctionErrorHandler` from
|
|
166
|
+
* `@solidjs/start/server`. The module is bundled into the server only, so
|
|
167
|
+
* it may import server-only code such as a monitoring SDK.
|
|
168
|
+
*
|
|
169
|
+
* @example "src/server-fn-error.ts"
|
|
170
|
+
*/
|
|
171
|
+
onError?: string;
|
|
172
|
+
};
|
|
24
173
|
}
|
|
25
174
|
export declare function solidStart(options?: SolidStartOptions): Array<PluginOption>;
|