diff --git a/.changeset/floppy-flies-help.md b/.changeset/floppy-flies-help.md new file mode 100644 index 000000000..2b236bba9 --- /dev/null +++ b/.changeset/floppy-flies-help.md @@ -0,0 +1,5 @@ +--- +'sv': patch +--- + +feat(devtools-json): default to handle replying 404 to chromium devtools diff --git a/documentation/docs/30-add-ons/03-devtools-json.md b/documentation/docs/30-add-ons/03-devtools-json.md index 67274f434..1c05e94db 100644 --- a/documentation/docs/30-add-ons/03-devtools-json.md +++ b/documentation/docs/30-add-ons/03-devtools-json.md @@ -2,32 +2,28 @@ title: devtools-json --- -The `devtools-json` add-on installs [`vite-plugin-devtools-json`](https://github.com/ChromeDevTools/vite-plugin-devtools-json/), which is a Vite plugin for generating a Chromium DevTools project settings file on-the-fly in the development server. This file is served from `/.well-known/appspecific/com.chrome.devtools.json` and tells Chromium browsers where your project's source code lives so that you can use [the workspaces feature](https://developer.chrome.com/docs/devtools/workspaces) to edit source files in the browser. - -> [!NOTE] -> Installing the plugin enables the feature for all users connecting to the dev server with a Chromium browser, and allows the browser to read and write all files within the directory. If you are using Chrome's AI Assistance feature, this may also result in data being sent to Google. +The `devtools-json` add-on adds a [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook that responds to the `/.well-known/appspecific/com.chrome.devtools.json` request with a 404 (aka `"Go away, Chrome DevTools!"`) during development, preventing the notice in your server logs. ## Alternatives -If you'd prefer not to install the plugin, but still want to avoid seeing a message about the missing file, you have a couple of options. +If you'd prefer to disable the feature in your browser instead, you can do this in Chrome by visiting `chrome://flags` and disabling the "DevTools Project Settings". You may also be interested in disabling "DevTools Automatic Workspace Folders" since it's closely related. -Firstly, you can prevent the request from being issued on your machine by disabling the feature in your browser. You can do this in Chrome by visiting `chrome://flags` and disabling the "DevTools Project Settings". You may also be interested in disabling "DevTools Automatic Workspace Folders" since it’s closely related. - -You can also prevent the web server from issuing a notice regarding the incoming request for all developers of your application by handling the request yourself. For example, you can create a file named `.well-known/appspecific/com.chrome.devtools.json` with the contents `"Go away, Chrome DevTools!"` or you can add logic to respond to the request in your [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook: +If you want to enable [the workspaces feature](https://developer.chrome.com/docs/devtools/workspaces) instead, you can install [`vite-plugin-devtools-json`](https://github.com/ChromeDevTools/vite-plugin-devtools-json/), which is a Vite plugin for generating the project settings file on-the-fly in the development server: ```js -/// file: src/hooks.server.js -import { dev } from '$app/environment'; - -export function handle({ event, resolve }) { - if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') { - return new Response(undefined, { status: 404 }); - } - - return resolve(event); -} +/// file: vite.config.js +import devtoolsJson from 'vite-plugin-devtools-json'; +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [sveltekit(), devtoolsJson()] +}); ``` +> [!NOTE] +> Installing the plugin enables the feature for all users connecting to the dev server with a Chromium browser, and allows the browser to read and write all files within the directory. If you are using Chrome's AI Assistance feature, this may also result in data being sent to Google. + ## Usage ```sh @@ -36,4 +32,4 @@ npx sv add devtools-json ## What you get -- `vite-plugin-devtools-json` added to your Vite plugin options +- A `handleDevtoolsJson` handle function added to your `hooks.server` file diff --git a/packages/sv-utils/src/tooling/js/kit.ts b/packages/sv-utils/src/tooling/js/kit.ts index 12a84d7de..bee214bed 100644 --- a/packages/sv-utils/src/tooling/js/kit.ts +++ b/packages/sv-utils/src/tooling/js/kit.ts @@ -271,6 +271,7 @@ export function addHooksHandle( } else { node.body.push(newHandleDecl, exportDecl); } + return; } // At this point, the existing `handle` doesn't call `sequence`, so we'll need to rename the original // `handle` and create a new `handle` that uses `sequence` diff --git a/packages/sv/src/addons/devtools-json.ts b/packages/sv/src/addons/devtools-json.ts index 311f631e0..8c05f2503 100644 --- a/packages/sv/src/addons/devtools-json.ts +++ b/packages/sv/src/addons/devtools-json.ts @@ -3,20 +3,28 @@ import { defineAddon } from '../core/config.ts'; export default defineAddon({ id: 'devtools-json', - shortDescription: 'devtools json', - homepage: 'https://github.com/ChromeDevTools/vite-plugin-devtools-json', + shortDescription: 'handle devtools json in dev mode', options: {}, - run: ({ sv, file }) => { - sv.devDependency('vite-plugin-devtools-json', '^1.0.0'); - - // add the vite plugin + run: ({ sv, language }) => { sv.file( - file.viteConfig, - transforms.script(({ ast, js }) => { - const vitePluginName = 'devtoolsJson'; - js.imports.addDefault(ast, { as: vitePluginName, from: 'vite-plugin-devtools-json' }); - js.vite.addPlugin(ast, { code: `${vitePluginName}()` }); + `src/hooks.server.${language}`, + transforms.script(({ ast, comments, js }) => { + js.imports.addNamed(ast, { imports: ['dev'], from: '$app/environment' }); + + const handleContent = `({ event, resolve }) => { + if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') { + return new Response(undefined, { status: 404 }); + } + return resolve(event); + };`; + + js.kit.addHooksHandle(ast, { + language, + newHandleName: 'handleDevtoolsJson', + handleContent, + comments + }); }) ); } diff --git a/packages/sv/src/addons/tests/devtools-json/test.ts b/packages/sv/src/addons/tests/devtools-json/test.ts index 608963a1b..d2cf647bc 100644 --- a/packages/sv/src/addons/tests/devtools-json/test.ts +++ b/packages/sv/src/addons/tests/devtools-json/test.ts @@ -13,13 +13,10 @@ test.concurrent.for(testCases)('devtools-json $variant', (testCase, ctx) => { const cwd = ctx.cwd(testCase); const language = testCase.variant.includes('ts') ? 'ts' : 'js'; - const viteFile = path.resolve(cwd, `vite.config.${language}`); - const viteContent = fs.readFileSync(viteFile, 'utf8'); + const hooksFile = path.resolve(cwd, `src/hooks.server.${language}`); + const hooksContent = fs.readFileSync(hooksFile, 'utf8'); - // Check if we have the import part - expect(viteContent).toContain(`import devtoolsJson from`); - expect(viteContent).toContain(`vite-plugin-devtools-json`); - - // Check if it's called - expect(viteContent).toContain(`devtoolsJson()`); + expect(hooksContent).toContain(`handleDevtoolsJson`); + expect(hooksContent).toContain(`com.chrome.devtools.json`); + expect(hooksContent).toContain(`from '$app/environment'`); }); diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json index f30915e72..e65833f64 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/package.json @@ -53,7 +53,6 @@ "typescript": "^5.9.3", "typescript-eslint": "^8.57.0", "vite": "^7.3.1", - "vite-plugin-devtools-json": "^1.0.0", "vitest": "^4.1.0", "vitest-browser-svelte": "^2.0.2" } diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.server.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.server.ts index f0872bb70..8d3734a7a 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.server.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/src/hooks.server.ts @@ -1,10 +1,18 @@ -import { sequence } from '@sveltejs/kit/hooks'; -import { building } from '$app/environment'; import { auth } from '$lib/server/auth'; import { svelteKitHandler } from 'better-auth/svelte-kit'; -import type { Handle } from '@sveltejs/kit'; +import { sequence } from '@sveltejs/kit/hooks'; import { getTextDirection } from '$lib/paraglide/runtime'; import { paraglideMiddleware } from '$lib/paraglide/server'; +import type { Handle } from '@sveltejs/kit'; +import { dev, building } from '$app/environment'; + +const handleDevtoolsJson: Handle = ({ event, resolve }) => { + if (dev && event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json') { + return new Response(undefined, { status: 404 }); + } + + return resolve(event); +}; const handleParaglide: Handle = ({ event, resolve }) => paraglideMiddleware(event.request, ({ request, locale }) => { event.request = request; @@ -25,4 +33,4 @@ const handleBetterAuth: Handle = async ({ event, resolve }) => { return svelteKitHandler({ event, resolve, auth, building }); }; -export const handle: Handle = sequence(handleParaglide, handleBetterAuth); +export const handle: Handle = sequence(handleDevtoolsJson, handleParaglide, handleBetterAuth); diff --git a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/vite.config.ts b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/vite.config.ts index e6136df66..9c72d3491 100644 --- a/packages/sv/src/cli/tests/snapshots/create-with-all-addons/vite.config.ts +++ b/packages/sv/src/cli/tests/snapshots/create-with-all-addons/vite.config.ts @@ -1,5 +1,4 @@ import { paraglideVitePlugin } from '@inlang/paraglide-js'; -import devtoolsJson from 'vite-plugin-devtools-json'; import tailwindcss from '@tailwindcss/vite'; import { defineConfig } from 'vitest/config'; import { playwright } from '@vitest/browser-playwright'; @@ -9,7 +8,6 @@ export default defineConfig({ plugins: [ tailwindcss(), sveltekit(), - devtoolsJson(), paraglideVitePlugin({ project: './project.inlang', outdir: './src/lib/paraglide' }) ], test: {