feat(core): support devtools injection in builds - #580
Merged
Merged
Conversation
@vitejs/devtools
@vitejs/devtools-kit
@vitejs/devtools-oxc
@vitejs/devtools-rolldown
@vitejs/devtools-vite
@vitejs/devtools-vitest
commit: |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Configuration validation and custom output-path issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds opt-in DevTools injection for production builds, with base-aware URLs, configuration diagnostics, and documentation.
Changes:
- Adds
build.injectionand build-time HTML injection. - Adds DTK0035 validation and error documentation.
- Documents configuration and usage.
File summaries
| File | Reviewed changes and findings |
|---|---|
packages/core/src/node/plugins/injection.ts |
Implements build injection. Moderate (1 vote): invalid injection without withApp may be silently ignored. Moderate (1 vote): custom outDir can produce a guaranteed 404. Nit (3 votes): add build-mode, base-path, and validation coverage. |
packages/core/src/node/plugins/index.ts |
Wires injection into the integration. Moderate (1 vote): validation is gated behind withApp, allowing invalid configuration to be ignored. |
packages/core/src/node/plugin-options.ts |
Defines build.injection. Moderate (1 vote): the option is silently ignored when withApp is false. |
packages/core/src/node/diagnostics.ts |
Adds the DTK0035 diagnostic. |
docs/guide/index.md |
Documents build injection. Nit (1 vote): the TypeScript example lacks the twoslash marker and defineConfig import. |
docs/errors/index.md |
Registers DTK0035. |
docs/errors/DTK0035.md |
Documents the DTK0035 configuration error. |
Review details
Suppressed comments (5)
docs/guide/index.md:156
- This new TypeScript config example is the only example in this section without the repository's
twoslashmarker and it omits thedefineConfigimport, so the docs build cannot type-check the newinjectionAPI. Keep it standalone and type-checked like the precedingvite.config.tsexample.
```ts
export default defineConfig({
devtools: {
build: {
withApp: true,
injection: true,
},
},
})
packages/core/src/node/plugin-options.ts:69
- This option is silently ignored in the automatic Vite integration when
withAppis false:DevToolsIntegrationonly callscreateDevToolsPlugins()inside thebuild.withAppbranch, so the newDTK0035check is never reached andinjection: truehas no effect. Validate the incompatible options in that path as well (or include a validation plugin) so this advertised option cannot be a silent no-op.
* Inject the dock into the built app. Requires `withApp: true`.
* Ensure the DevTools assets are served under Vite's `base` when deployed.
* @default false
*/
injection?: boolean
packages/core/src/node/plugins/index.ts:63
- With the automatic
devtools: { build: { injection: true } }configuration,DevToolsIntegrationonly callscreateDevToolsPluginswhenbuild.withAppis already true. IfwithAppis omitted, this new plugin is never instantiated, so DTK0035 is never emitted and the documented requirement is silently ignored. Validateinjectionbefore that gate (or add a validation-only path) so both registration paths reject this invalid configuration.
DevToolsInjection(build),
packages/core/src/node/plugins/injection.ts:37
- With the automatic
devtoolsintegration, this check is never reached whenbuild.injectionis true withoutbuild.withApp:DevToolsIntegrationonly addscreateDevToolsPlugins—and therefore this plugin—inside itsif (build?.withApp)branch. The invalid configuration is consequently ignored instead of emitting DTK0035; validate it before that gate or include the validation wheninjectionis set.
if (!build?.withApp)
throw diagnostics.DTK0035({})
packages/core/src/node/plugins/injection.ts:38
- When
build.outDiris different from Vite'sbuild.outDir,DevToolsBuildwritesembedded.jsunder the custom directory, but this URL still points to<base>/__devtools/embedded.jsin the app deployment root. For example,outDir: 'devtools-dist'producesdevtools-dist/__devtools/embedded.jswhile the injected app requests the missing file from the app output. Please reject or explicitly handle this combination so enabling injection does not create a guaranteed 404.
src = `${config.base.replace(/\/+$/, '')}${DEVTOOLS_MOUNT_PATH}embedded.js`
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (config.command === 'build') { | ||
| if (!build?.withApp) | ||
| throw diagnostics.DTK0035({}) | ||
| src = `${config.base.replace(/\/+$/, '')}${DEVTOOLS_MOUNT_PATH}embedded.js` |
antfu
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
Users may want to include devtools in production builds, as Eduardo does with Pinia Colada DevTools in his playground. This PR adds
build.injection: trueoption to support this use case./cc @posva — this should cover the Pinia Colada use case we discussed.