Skip to content

Commit b15abbb

Browse files
committed
make Start devtools optional
1 parent fdeef38 commit b15abbb

5 files changed

Lines changed: 60 additions & 16 deletions

File tree

.changeset/dev-toolbar-inspector.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'@solidjs/vite-plugin': minor
33
---
44

5-
Add the Start development toolbar, error overlay, and server function inspector.
5+
Add optional Start development toolbar, error overlay, and server function inspector integration.

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,16 @@ The object form carries the options (`start: true` is pure sugar for
181181
`false`/absent means off): `app`, `document`, `entryServer`, `entryClient`,
182182
`middleware`, `setup`, `env`, `devtools`, `external`, all documented below.
183183

184-
Start mode includes a development toolbar with runtime errors and server
185-
function calls. Set `start: { devtools: false }` to disable it. The toolbar is
186-
not included in production builds.
184+
Install `@solidjs/start-devtools` as a development dependency to add the
185+
development toolbar with runtime errors and server function calls:
186+
187+
```sh
188+
pnpm add -D @solidjs/start-devtools@next
189+
```
190+
191+
Start mode detects the package automatically. Set `start: { devtools: true }`
192+
to require it or `start: { devtools: false }` to disable it. The package is an
193+
optional peer and the toolbar is not included in production builds.
187194

188195
```tsx
189196
// src/App.tsx — the entire app: a plain content component

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
"@ampproject/remapping": "^2.3.0",
6060
"@babel/core": "^7.23.3",
6161
"@dom-expressions/compiler": "^0.50.0-next.43",
62-
"@solidjs/start-devtools": "^1.0.0-next.0",
6362
"@types/babel__core": "^7.20.4",
6463
"babel-preset-solid": "^2.0.0-rc.0",
6564
"merge-anything": "^5.1.7",
@@ -73,6 +72,7 @@
7372
"@rollup/plugin-commonjs": "^25.0.7",
7473
"@rollup/plugin-node-resolve": "^15.2.3",
7574
"@skypack/package-check": "^0.2.2",
75+
"@solidjs/start-devtools": "^1.0.0-next.0",
7676
"@types/node": "^18.18.4",
7777
"cypress": "^14.0.0",
7878
"cypress-visual-regression": "^5.2.2",
@@ -86,12 +86,16 @@
8686
"vite": "^7.0.0"
8787
},
8888
"peerDependencies": {
89+
"@solidjs/start-devtools": "^1.0.0-next.0",
8990
"@solidjs/web": "^2.0.0-rc.0",
9091
"@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*",
9192
"solid-js": "^2.0.0-rc.0",
9293
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
9394
},
9495
"peerDependenciesMeta": {
96+
"@solidjs/start-devtools": {
97+
"optional": true
98+
},
9599
"@testing-library/jest-dom": {
96100
"optional": true
97101
}

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ssr/index.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,13 @@ export interface StartOptions {
209209
* @default undefined (probe env.ts / env.js; off when absent)
210210
*/
211211
env?: boolean | string;
212-
/** Enable the development toolbar. @default true */
212+
/**
213+
* Enable the development toolbar. By default it is enabled when
214+
* `@solidjs/start-devtools` is installed. Setting this to `true` requires
215+
* the package, while `false` disables it.
216+
*
217+
* @default undefined
218+
*/
213219
devtools?: boolean;
214220
/**
215221
* Add the default production error boundary to generated entries.
@@ -435,7 +441,8 @@ export function startServe(
435441
const serverComponents = !!internal.serverComponents;
436442
const errorBoundary = options.errorBoundary !== false;
437443
const styleFilter = internal.styleFilter;
438-
const devtools = options.devtools !== false;
444+
let devtools: boolean | undefined = false;
445+
let devtoolsResolution: Promise<boolean> | undefined;
439446
// `external` is server-mode-only (documented no-op in client mode, so a
440447
// host-integrated config survives the `ssr` boolean flip untouched).
441448
const externalServer = !clientMode && !!options.external;
@@ -454,6 +461,19 @@ export function startServe(
454461
return entries;
455462
}
456463

464+
async function resolveDevtools(resolve: () => Promise<unknown>): Promise<boolean> {
465+
if (devtools !== undefined) return devtools;
466+
devtoolsResolution ??= resolve().then(Boolean);
467+
devtools = await devtoolsResolution;
468+
if (!devtools && options.devtools === true) {
469+
throw new Error(
470+
'[@solidjs/vite-plugin] start.devtools requires @solidjs/start-devtools. ' +
471+
'Install it as a development dependency or set start.devtools to false.',
472+
);
473+
}
474+
return devtools;
475+
}
476+
457477
/** Import specifier for generated code: absolute for files, id for virtuals. */
458478
function entryServerSpec(): string {
459479
const { entryServer } = requireEntries();
@@ -631,9 +651,8 @@ export function startServe(
631651
].join('\n');
632652
}
633653

634-
function generatedEntryClientCode(): string {
654+
function generatedEntryClientCode(toolbar: boolean): string {
635655
const { app } = requireEntries();
636-
const toolbar = devtools && !isBuild;
637656
if (clientMode) {
638657
// render(), not hydrate(): the shell's body is empty, the app mounts
639658
// fresh. Client code compiles non-hydratable in client mode, so the
@@ -1001,6 +1020,11 @@ export function startServe(
10011020
enforce: 'pre',
10021021
config(userConfig, env) {
10031022
root = path.resolve(userConfig.root || process.cwd());
1023+
devtools =
1024+
env.command === 'serve' && !env.isPreview && options.devtools !== false
1025+
? undefined
1026+
: false;
1027+
devtoolsResolution = undefined;
10041028
entries = resolveEntries(root, options, clientMode);
10051029
middlewarePath = options.middleware
10061030
? path.resolve(root, normalizeUserPath(root, options.middleware, 'middleware'))
@@ -1141,7 +1165,7 @@ export function startServe(
11411165
) {
11421166
return { id: source, moduleSideEffects: source === ENTRY_CLIENT_ID };
11431167
}
1144-
if (!isBuild && devtools && (source === DEVTOOLS_ID || source === DEVTOOLS_MOUNT_ID)) {
1168+
if (devtools && (source === DEVTOOLS_ID || source === DEVTOOLS_MOUNT_ID)) {
11451169
return { id: source, moduleSideEffects: true };
11461170
}
11471171
return null;
@@ -1165,7 +1189,12 @@ export function startServe(
11651189
return devStylesModuleCode(this.environment, (file) => this.addWatchFile(file));
11661190
}
11671191
if (id === ENTRY_SERVER_ID) return generatedEntryServerCode();
1168-
if (id === ENTRY_CLIENT_ID) return generatedEntryClientCode();
1192+
if (id === ENTRY_CLIENT_ID) {
1193+
const toolbar = await resolveDevtools(() =>
1194+
this.resolve('@solidjs/start-devtools', requireEntries().app!, { skipSelf: true }),
1195+
);
1196+
return generatedEntryClientCode(toolbar);
1197+
}
11691198
if (id === DOCUMENT_ID) return documentShellCode;
11701199
if (id === ERROR_BOUNDARY_ID) return errorBoundaryCode;
11711200
if (id === DEVTOOLS_ID || id === DEVTOOLS_MOUNT_ID) {
@@ -1176,13 +1205,17 @@ export function startServe(
11761205
}
11771206
return null;
11781207
},
1179-
transform(code, id, opts) {
1180-
if (isBuild || !devtools) return null;
1208+
async transform(code, id, opts) {
1209+
if (isBuild || devtools === false) return null;
11811210
const current = requireEntries();
11821211
if (current.generated || getEnvironmentConsumer(this.environment, opts) !== 'client') {
11831212
return null;
11841213
}
11851214
if (id.split('?')[0] !== path.resolve(root, current.entryClient)) return null;
1215+
const toolbar = await resolveDevtools(() =>
1216+
this.resolve('@solidjs/start-devtools', id, { skipSelf: true }),
1217+
);
1218+
if (!toolbar) return null;
11861219
return {
11871220
code: `import ${JSON.stringify(DEVTOOLS_MOUNT_ID)};\n${code}`,
11881221
map: null,

0 commit comments

Comments
 (0)