From 3c9172159c72f3c8ea116557ba5bf917a15d2f07 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:56:53 +0000 Subject: [PATCH] feat(@angular/build): integrate Chrome automatic workspace folders This commit integrates automatic Chrome DevTools workspace folder connection into the vite dev-server process, leveraging the experimental feature available in Chrome Canary, as described in the Chrome DevTools documentation https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/ecosystem/automatic_workspace_folders.md --- .../src/builders/dev-server/vite-server.ts | 1 + .../middlewares/chrome-devtools-middleware.ts | 51 +++++++++++++++++++ .../build/src/tools/vite/middlewares/index.ts | 1 + .../vite/plugins/setup-middlewares-plugin.ts | 6 +++ 4 files changed, 59 insertions(+) create mode 100644 packages/angular/build/src/tools/vite/middlewares/chrome-devtools-middleware.ts diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index 241ff2cdc5..f211ae5872 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -908,6 +908,7 @@ export async function setupServer( templateUpdates, ssrMode, resetComponentUpdates: () => templateUpdates.clear(), + projectRoot: serverOptions.projectRoot, }), createRemoveIdPrefixPlugin(externalMetadata.explicitBrowser), await createAngularSsrTransformPlugin(serverOptions.workspaceRoot), diff --git a/packages/angular/build/src/tools/vite/middlewares/chrome-devtools-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/chrome-devtools-middleware.ts new file mode 100644 index 0000000000..4d7b18022a --- /dev/null +++ b/packages/angular/build/src/tools/vite/middlewares/chrome-devtools-middleware.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { randomUUID } from 'node:crypto'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import type { Connect } from 'vite'; + +const CHROME_DEVTOOLS_ROUTE = '/.well-known/appspecific/com.chrome.devtools.json'; + +export function createChromeDevtoolsMiddleware( + cacheDir: string, + projectRoot: string, +): Connect.NextHandleFunction { + let devtoolsConfig: string; + const devtoolsConfigPath = join(cacheDir, 'com.chrome.devtools.json'); + + return function chromeDevtoolsMiddleware(req, res, next) { + if (req.url !== CHROME_DEVTOOLS_ROUTE) { + next(); + + return; + } + + // We store the UUID and re-use it to ensure Chrome does not repeatedly ask for permissions when restarting the dev server. + try { + devtoolsConfig ??= readFileSync(devtoolsConfigPath, 'utf-8'); + } catch { + const devtoolsConfigJson = { + workspace: { + root: projectRoot, + uuid: randomUUID(), + }, + }; + + devtoolsConfig = JSON.stringify(devtoolsConfigJson, undefined, 2); + try { + mkdirSync(cacheDir, { recursive: true }); + writeFileSync(devtoolsConfigPath, devtoolsConfig); + } catch {} + } + + res.setHeader('Content-Type', 'application/json'); + res.end(devtoolsConfig); + }; +} diff --git a/packages/angular/build/src/tools/vite/middlewares/index.ts b/packages/angular/build/src/tools/vite/middlewares/index.ts index 2981e99120..ef2db01f3a 100644 --- a/packages/angular/build/src/tools/vite/middlewares/index.ts +++ b/packages/angular/build/src/tools/vite/middlewares/index.ts @@ -15,3 +15,4 @@ export { } from './ssr-middleware'; export { createAngularHeadersMiddleware } from './headers-middleware'; export { createAngularComponentMiddleware } from './component-middleware'; +export { createChromeDevtoolsMiddleware } from './chrome-devtools-middleware'; diff --git a/packages/angular/build/src/tools/vite/plugins/setup-middlewares-plugin.ts b/packages/angular/build/src/tools/vite/plugins/setup-middlewares-plugin.ts index 2e251285e9..21ddaa350a 100644 --- a/packages/angular/build/src/tools/vite/plugins/setup-middlewares-plugin.ts +++ b/packages/angular/build/src/tools/vite/plugins/setup-middlewares-plugin.ts @@ -17,6 +17,7 @@ import { createAngularIndexHtmlMiddleware, createAngularSsrExternalMiddleware, createAngularSsrInternalMiddleware, + createChromeDevtoolsMiddleware, } from '../middlewares'; import { AngularMemoryOutputFiles, AngularOutputAssets } from '../utils'; @@ -54,6 +55,7 @@ interface AngularSetupMiddlewaresPluginOptions { templateUpdates: Map; ssrMode: ServerSsrMode; resetComponentUpdates: () => void; + projectRoot: string; } async function createEncapsulateStyle(): Promise< @@ -99,6 +101,10 @@ export function createAngularSetupMiddlewaresPlugin( ), ); + server.middlewares.use( + createChromeDevtoolsMiddleware(server.config.cacheDir, options.projectRoot), + ); + extensionMiddleware?.forEach((middleware) => server.middlewares.use(middleware)); // Returning a function, installs middleware after the main transform middleware but