From e463adf6cb96716dd08371d582bb69e74d3356df Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 24 Mar 2026 20:46:11 +0200 Subject: [PATCH] feat: enable React profiling build for dogfood (#23354) --- .github/workflows/ci.yaml | 6 ++++++ site/vite.config.mts | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 239150a50b..e845c57875 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1217,6 +1217,12 @@ jobs: EV_CERTIFICATE_PATH: /tmp/ev_cert.pem GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }} JSIGN_PATH: /tmp/jsign-6.0.jar + # Enable React profiling build and discoverable source maps + # for the dogfood deployment (dev.coder.com). This also + # applies to release/* branch builds, but those still + # produce coder-preview images, not release images. + # Release images are built by release.yaml (no profiling). + CODER_REACT_PROFILING: "true" # Free up disk space before building Docker images. The preceding # Build step produces ~2 GB of binaries and packages, the Go build diff --git a/site/vite.config.mts b/site/vite.config.mts index 7e0fbf88d8..e91de22fe1 100644 --- a/site/vite.config.mts +++ b/site/vite.config.mts @@ -7,6 +7,14 @@ import type { PluginOption } from "vite"; import checker from "vite-plugin-checker"; import { defineConfig } from "vitest/config"; +// Enable the React profiling build and discoverable source maps for +// internal deployments (e.g. dogfood). The profiling build swaps +// react-dom/client for react-dom/profiling, which keeps production +// optimizations but leaves the onRender callback and +// React Performance Tracks instrumentation intact. The overhead is +// ~13% on the react-dom chunk size. +const isProfilingBuild = process.env.CODER_REACT_PROFILING === "true"; + const plugins: PluginOption[] = [ react({ babel: { @@ -42,7 +50,7 @@ export default defineConfig({ build: { outDir: path.resolve(__dirname, "./out"), emptyOutDir: false, // We need to keep the /bin folder and GITKEEP files - sourcemap: "hidden", + sourcemap: isProfilingBuild ? true : "hidden", rollupOptions: { input: { index: path.resolve(__dirname, "./index.html"), @@ -209,6 +217,15 @@ export default defineConfig({ }, resolve: { alias: { + // In profiling builds, swap the production react-dom client + // bundle for the profiling variant so that + // onRender receives actual timing data. + // Note: react-dom/profiling is a superset of react-dom/client + // (16 vs 3 exports). If a future React major changes this + // relationship, the alias may need updating. + ...(isProfilingBuild + ? { "react-dom/client": "react-dom/profiling" } + : {}), App: path.resolve(__dirname, "./src/App"), api: path.resolve(__dirname, "./src/api"), components: path.resolve(__dirname, "./src/components"),