From dadde5b1aafe97681402e55da43c9a6b3913ffe0 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Thu, 16 Mar 2023 16:20:51 +1100 Subject: [PATCH 01/22] fix: handle CSS bundle updates during HMR --- .changeset/css-bundle-hmr.md | 6 ++ integration/hmr-test.ts | 24 +++++- packages/remix-css-bundle/browser.ts | 10 ++- packages/remix-dev/compiler/assets.ts | 6 +- packages/remix-dev/compiler/compileBrowser.ts | 28 +++++-- .../compiler/plugins/cssBundleUpdatePlugin.ts | 74 +++++++++++++++++++ 6 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 .changeset/css-bundle-hmr.md create mode 100644 packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts diff --git a/.changeset/css-bundle-hmr.md b/.changeset/css-bundle-hmr.md new file mode 100644 index 00000000000..08fd8503b76 --- /dev/null +++ b/.changeset/css-bundle-hmr.md @@ -0,0 +1,6 @@ +--- +"@remix-run/css-bundle": patch +"@remix-run/dev": patch +--- + +Ensure changes to CSS inserted via `@remix-run/css-bundle` are picked up during HMR diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 13af69b0261..bd08171da42 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -13,6 +13,7 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ port: options.port, appServerPort: options.appServerPort, }, + unstable_cssModules: true, unstable_tailwind: true, v2_routeConvention: true, v2_errorBoundary: true, @@ -26,6 +27,7 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "dev:app": `cross-env NODE_ENV=development nodemon --watch build/ ./server.js`, }, dependencies: { + "@remix-run/css-bundle": "0.0.0-local-version", "@remix-run/node": "0.0.0-local-version", "@remix-run/react": "0.0.0-local-version", "cross-env": "0.0.0-local-version", @@ -90,15 +92,23 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ @tailwind utilities; `, + "app/styles.module.css": css` + .test { + color: initial; + } + `, + "app/root.tsx": js` import type { LinksFunction } from "@remix-run/node"; import { Link, Links, LiveReload, Meta, Outlet, Scripts } from "@remix-run/react"; + import { cssBundleHref } from "@remix-run/css-bundle"; import Counter from "./components/counter"; import styles from "./tailwind.css"; export const links: LinksFunction = () => [ { rel: "stylesheet", href: styles }, + ...cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : [], ]; export default function Root() { @@ -246,15 +256,26 @@ test("HMR", async ({ page }) => { let originalIndex = fs.readFileSync(indexPath, "utf8"); let counterPath = path.join(projectDir, "app", "components", "counter.tsx"); let originalCounter = fs.readFileSync(counterPath, "utf8"); + let cssModulePath = path.join(projectDir, "app", "styles.module.css"); + let originalCssModule = fs.readFileSync(cssModulePath, "utf8"); // make content and style changed to index route + let newCssModule = ` + .test { + background: black; + color: white; + } + `; + fs.writeFileSync(cssModulePath, newCssModule); + let newIndex = ` import { useLoaderData } from "@remix-run/react"; + import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Changed

+

Changed

) } @@ -274,6 +295,7 @@ test("HMR", async ({ page }) => { // undo change fs.writeFileSync(indexPath, originalIndex); + fs.writeFileSync(cssModulePath, originalCssModule); await page.getByText("Index Title").waitFor({ timeout: 2000 }); expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); await page.waitForSelector(`#root-counter:has-text("inc 1")`); diff --git a/packages/remix-css-bundle/browser.ts b/packages/remix-css-bundle/browser.ts index e17c8ce3d10..02c76cfa629 100644 --- a/packages/remix-css-bundle/browser.ts +++ b/packages/remix-css-bundle/browser.ts @@ -2,4 +2,12 @@ import type { AssetsManifest } from "@remix-run/dev/assets-manifest"; let assetsManifest: AssetsManifest = (window as any).__remixManifest; -export const cssBundleHref = assetsManifest.cssBundleHref; +declare const __INJECT_CSS_BUNDLE_HREF__: string | undefined; + +// Injected by `cssBundleUpdatePlugin` on rebuilds +let updatedHref: string | undefined = + typeof __INJECT_CSS_BUNDLE_HREF__ === "string" + ? __INJECT_CSS_BUNDLE_HREF__ + : undefined; + +export const cssBundleHref = updatedHref || assetsManifest.cssBundleHref; diff --git a/packages/remix-dev/compiler/assets.ts b/packages/remix-dev/compiler/assets.ts index f8c427704cc..fad890502b5 100644 --- a/packages/remix-dev/compiler/assets.ts +++ b/packages/remix-dev/compiler/assets.ts @@ -42,12 +42,12 @@ export interface AssetsManifest { export async function createAssetsManifest({ config, metafile, - cssBundlePath, + cssBundleHref, hmr, }: { config: RemixConfig; metafile: esbuild.Metafile; - cssBundlePath?: string; + cssBundleHref?: string; hmr?: AssetsManifest["hmr"]; }): Promise { function resolveUrl(outputPath: string): string { @@ -126,8 +126,6 @@ export async function createAssetsManifest({ JSON.stringify({ entry, routes, hmrRoutes: hmr?.routes }) ).slice(0, 8); - let cssBundleHref = cssBundlePath ? resolveUrl(cssBundlePath) : undefined; - return { version, entry, routes, cssBundleHref, hmr }; } diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index ff5d00a9e0e..16e9eb311b5 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -20,6 +20,7 @@ import { deprecatedRemixPackagePlugin } from "./plugins/deprecatedRemixPackagePl import { emptyModulesPlugin } from "./plugins/emptyModulesPlugin"; import { mdxPlugin } from "./plugins/mdx"; import { urlImportsPlugin } from "./plugins/urlImportsPlugin"; +import { cssBundleUpdatePlugin } from "./plugins/cssBundleUpdatePlugin"; import { cssModulesPlugin } from "./plugins/cssModulesPlugin"; import { cssSideEffectImportsPlugin } from "./plugins/cssSideEffectImportsPlugin"; import { vanillaExtractPlugin } from "./plugins/vanillaExtractPlugin"; @@ -78,6 +79,12 @@ const isCssBundlingEnabled = (config: RemixConfig): boolean => config.future.unstable_cssSideEffectImports || config.future.unstable_vanillaExtract ); + +let cssBundleHrefPromise: Promise; + +// Allow plugins to access the latest value of the CSS bundle during rebuilds +const getCssBundleHref = () => cssBundleHrefPromise; + const createEsbuildConfig = ( build: "app" | "css", config: RemixConfig, @@ -109,6 +116,7 @@ const createEsbuildConfig = ( let plugins: esbuild.Plugin[] = [ deprecatedRemixPackagePlugin(options.onWarning), + build === "css" ? cssBundleUpdatePlugin({ getCssBundleHref }) : null, isCssBundlingEnabled(config) && isCssBuild ? cssBundleEntryModulePlugin(config) : null, @@ -131,7 +139,7 @@ const createEsbuildConfig = ( NodeModulesPolyfillPlugin(), ].filter(isNotNull); - if (mode === "development" && config.future.unstable_dev) { + if (build === "app" && mode === "development" && config.future.unstable_dev) { // TODO prebundle deps instead of chunking just these ones let isolateChunks = [ require.resolve("react"), @@ -305,12 +313,20 @@ export const createBrowserCompiler = ( }), ]); - // Return the CSS bundle path so we can use it to generate the manifest - return cssBundlePath; + let cssBundleHref = + remixConfig.publicPath + + path.relative( + remixConfig.assetsBuildDirectory, + path.resolve(cssBundlePath) + ); + + return cssBundleHref; }; - let [cssBundlePath, metafile] = await Promise.all([ - cssBuildTask(), + cssBundleHrefPromise = cssBuildTask(); + + let [cssBundleHref, metafile] = await Promise.all([ + cssBundleHrefPromise, appBuildTask(), ]); @@ -336,7 +352,7 @@ export const createBrowserCompiler = ( let manifest = await createAssetsManifest({ config: remixConfig, metafile: appCompiler.metafile!, - cssBundlePath, + cssBundleHref, hmr, }); await writeAssetsManifest(remixConfig, manifest); diff --git a/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts b/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts new file mode 100644 index 00000000000..29d444a3f30 --- /dev/null +++ b/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts @@ -0,0 +1,74 @@ +import type { Plugin } from "esbuild"; +import { readFile } from "fs-extra"; + +const pluginName = "css-bundle-update-plugin"; +const namespace = `${pluginName}-ns`; + +/** + * This plugin updates the source code for the "css-bundle" package on rebuilds + * to contain the latest CSS bundle href so CSS changes get picked up for HMR. + * Without this plugin, the "css-bundle" package source code never changes on + * disk so it never triggers an update. + */ +export function cssBundleUpdatePlugin({ + getCssBundleHref, +}: { + getCssBundleHref: () => Promise; +}): Plugin { + return { + name: "css-bundle-update-plugin", + async setup(build) { + let isRebuild = false; + build.onEnd(() => { + isRebuild = true; + }); + + let preventInfiniteLoop = {}; + build.onResolve({ filter: /^@remix-run\/css-bundle$/ }, async (args) => { + // Prevent plugin from infinitely trying to resolve itself + if (args.pluginData === preventInfiniteLoop) { + return null; + } + + // We don't wait for the href on the first build and instead rely on the + // default runtime manifest lookup. We only need to update this package + // to reflect changes during development so the first build is fine. + if (!isRebuild) { + return null; + } + + let resolvedPath = ( + await build.resolve(args.path, { + resolveDir: args.resolveDir, + kind: args.kind, + pluginData: preventInfiniteLoop, + }) + ).path; + + return { + path: resolvedPath, + namespace, + }; + }); + + build.onLoad({ filter: /.*/, namespace }, async (args) => { + let [cssBundleHref, contents] = await Promise.all([ + getCssBundleHref(), + readFile(args.path, "utf8"), + ]); + + if (cssBundleHref) { + contents = contents.replace( + /__INJECT_CSS_BUNDLE_HREF__/g, + JSON.stringify(cssBundleHref) + ); + } + + return { + loader: "js", + contents, + }; + }); + }, + }; +} From ec86cbb02a8c25eace6367a6577929349135132c Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Thu, 16 Mar 2023 16:42:06 +1100 Subject: [PATCH 02/22] Add extra wait to test --- integration/hmr-test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index bd08171da42..b425f2b0e93 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -268,6 +268,9 @@ test("HMR", async ({ page }) => { `; fs.writeFileSync(cssModulePath, newCssModule); + // detect HMR'd style changes + await page.waitForLoadState("networkidle"); + let newIndex = ` import { useLoaderData } from "@remix-run/react"; import styles from "~/styles.module.css"; @@ -282,10 +285,11 @@ test("HMR", async ({ page }) => { `; fs.writeFileSync(indexPath, newIndex); - // detect HMR'd content and style changes + // detect HMR'd content await page.waitForLoadState("networkidle"); + let h1 = page.getByText("Changed"); - await h1.waitFor({ timeout: 2000 }); + await h1.waitFor({ timeout: 5000 }); expect(h1).toHaveCSS("color", "rgb(255, 255, 255)"); expect(h1).toHaveCSS("background-color", "rgb(0, 0, 0)"); From 8cc612dc63a01ef38f7000f25ceb8f617a4f2191 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 10:10:19 +1100 Subject: [PATCH 03/22] Move CSS update into separate step in test --- integration/hmr-test.ts | 50 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index b425f2b0e93..1cab458a5b2 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -94,7 +94,8 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/styles.module.css": css` .test { - color: initial; + color: black; + background: white; } `, @@ -259,18 +260,6 @@ test("HMR", async ({ page }) => { let cssModulePath = path.join(projectDir, "app", "styles.module.css"); let originalCssModule = fs.readFileSync(cssModulePath, "utf8"); - // make content and style changed to index route - let newCssModule = ` - .test { - background: black; - color: white; - } - `; - fs.writeFileSync(cssModulePath, newCssModule); - - // detect HMR'd style changes - await page.waitForLoadState("networkidle"); - let newIndex = ` import { useLoaderData } from "@remix-run/react"; import styles from "~/styles.module.css"; @@ -278,7 +267,7 @@ test("HMR", async ({ page }) => { const t = useLoaderData(); return (
-

Changed

+

Changed

) } @@ -289,9 +278,36 @@ test("HMR", async ({ page }) => { await page.waitForLoadState("networkidle"); let h1 = page.getByText("Changed"); - await h1.waitFor({ timeout: 5000 }); - expect(h1).toHaveCSS("color", "rgb(255, 255, 255)"); - expect(h1).toHaveCSS("background-color", "rgb(0, 0, 0)"); + await h1.waitFor({ timeout: 2000 }); + + // Assert original styles are applied + expect(h1).toHaveCSS("color", "rgb(0, 0, 0)"); + expect(h1).toHaveCSS("background-color", "rgb(255, 255, 255)"); + + // make content and style changed to index route + let newCssModule = ` + .test { + background: black; + color: white; + } + `; + fs.writeFileSync(cssModulePath, newCssModule); + + // detect HMR'd style changes + await page.waitForLoadState("networkidle"); + + // Assert updated styles are eventually applied + await expect + .poll(async () => + h1.evaluate((element) => { + let { color, backgroundColor } = getComputedStyle(element); + return { color, backgroundColor }; + }) + ) + .toEqual({ + color: "rgb(255, 255, 255)", + backgroundColor: "rgb(0, 0, 0)", + }); // verify that `` value was persisted (i.e. hmr, not full page refresh) expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); From 5507895f3a752a11594c8e76868336c232086e60 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 10:29:19 +1100 Subject: [PATCH 04/22] Use styles on original test index route --- integration/hmr-test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 1cab458a5b2..17ce7dc3eff 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -142,11 +142,12 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/_index.tsx": js` import { useLoaderData } from "@remix-run/react"; + import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Index Title

+

Index Title

) } From d933a6ace9d786201a016e57af0da591d5af5123 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 10:32:13 +1100 Subject: [PATCH 05/22] Remove unused test ID --- integration/hmr-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 17ce7dc3eff..e0ca70d4b30 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -268,7 +268,7 @@ test("HMR", async ({ page }) => { const t = useLoaderData(); return (
-

Changed

+

Changed

) } From 03287a04fe1c474efe2cb625328b498267639986 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 10:52:52 +1100 Subject: [PATCH 06/22] Temporarily roll back CSS HMR test --- integration/hmr-test.ts | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index e0ca70d4b30..4fa77d31406 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -27,7 +27,6 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "dev:app": `cross-env NODE_ENV=development nodemon --watch build/ ./server.js`, }, dependencies: { - "@remix-run/css-bundle": "0.0.0-local-version", "@remix-run/node": "0.0.0-local-version", "@remix-run/react": "0.0.0-local-version", "cross-env": "0.0.0-local-version", @@ -102,14 +101,12 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/root.tsx": js` import type { LinksFunction } from "@remix-run/node"; import { Link, Links, LiveReload, Meta, Outlet, Scripts } from "@remix-run/react"; - import { cssBundleHref } from "@remix-run/css-bundle"; import Counter from "./components/counter"; import styles from "./tailwind.css"; export const links: LinksFunction = () => [ { rel: "stylesheet", href: styles }, - ...cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : [], ]; export default function Root() { @@ -142,12 +139,11 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/_index.tsx": js` import { useLoaderData } from "@remix-run/react"; - import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Index Title

+

Index Title

) } @@ -258,17 +254,14 @@ test("HMR", async ({ page }) => { let originalIndex = fs.readFileSync(indexPath, "utf8"); let counterPath = path.join(projectDir, "app", "components", "counter.tsx"); let originalCounter = fs.readFileSync(counterPath, "utf8"); - let cssModulePath = path.join(projectDir, "app", "styles.module.css"); - let originalCssModule = fs.readFileSync(cssModulePath, "utf8"); let newIndex = ` import { useLoaderData } from "@remix-run/react"; - import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Changed

+

Changed

) } @@ -281,42 +274,12 @@ test("HMR", async ({ page }) => { let h1 = page.getByText("Changed"); await h1.waitFor({ timeout: 2000 }); - // Assert original styles are applied - expect(h1).toHaveCSS("color", "rgb(0, 0, 0)"); - expect(h1).toHaveCSS("background-color", "rgb(255, 255, 255)"); - - // make content and style changed to index route - let newCssModule = ` - .test { - background: black; - color: white; - } - `; - fs.writeFileSync(cssModulePath, newCssModule); - - // detect HMR'd style changes - await page.waitForLoadState("networkidle"); - - // Assert updated styles are eventually applied - await expect - .poll(async () => - h1.evaluate((element) => { - let { color, backgroundColor } = getComputedStyle(element); - return { color, backgroundColor }; - }) - ) - .toEqual({ - color: "rgb(255, 255, 255)", - backgroundColor: "rgb(0, 0, 0)", - }); - // verify that `` value was persisted (i.e. hmr, not full page refresh) expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); await page.waitForSelector(`#root-counter:has-text("inc 1")`); // undo change fs.writeFileSync(indexPath, originalIndex); - fs.writeFileSync(cssModulePath, originalCssModule); await page.getByText("Index Title").waitFor({ timeout: 2000 }); expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); await page.waitForSelector(`#root-counter:has-text("inc 1")`); From 450c400158459a86f933edc546690e5cbb8a6b37 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 11:12:50 +1100 Subject: [PATCH 07/22] Add static bundled CSS to HMR test --- integration/hmr-test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 4fa77d31406..8c4b5b5b575 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -94,19 +94,21 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/styles.module.css": css` .test { color: black; - background: white; + background: orange; } `, "app/root.tsx": js` import type { LinksFunction } from "@remix-run/node"; import { Link, Links, LiveReload, Meta, Outlet, Scripts } from "@remix-run/react"; + import { cssBundleHref } from "@remix-run/css-bundle"; import Counter from "./components/counter"; import styles from "./tailwind.css"; export const links: LinksFunction = () => [ { rel: "stylesheet", href: styles }, + ...cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : [], ]; export default function Root() { @@ -139,11 +141,12 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/_index.tsx": js` import { useLoaderData } from "@remix-run/react"; + import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Index Title

+

Index Title

) } @@ -257,11 +260,12 @@ test("HMR", async ({ page }) => { let newIndex = ` import { useLoaderData } from "@remix-run/react"; + import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Changed

+

Changed

) } From 01d68fd677abdab13905b1f0cd8cce9c364ea86f Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 11:29:30 +1100 Subject: [PATCH 08/22] Debug test --- integration/hmr-test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 8c4b5b5b575..994ea31436f 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -202,7 +202,7 @@ let bufferize = (stream: Readable): (() => string) => { test("HMR", async ({ page }) => { // uncomment for debugging - // page.on("console", (msg) => console.log(msg.text())); + page.on("console", (msg) => console.log("PAGE: " + msg.text())); page.on("pageerror", (err) => console.log(err.message)); let appServerPort = await getPort({ port: makeRange(3080, 3089) }); @@ -276,7 +276,7 @@ test("HMR", async ({ page }) => { await page.waitForLoadState("networkidle"); let h1 = page.getByText("Changed"); - await h1.waitFor({ timeout: 2000 }); + await h1.waitFor({ timeout: 10000 }); // verify that `` value was persisted (i.e. hmr, not full page refresh) expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); From 572dc5823fc538b2ad70f13e3a0afb6e10983287 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 11:47:03 +1100 Subject: [PATCH 09/22] Roll back app build check --- packages/remix-dev/compiler/compileBrowser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 16e9eb311b5..158f2960f10 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -139,7 +139,7 @@ const createEsbuildConfig = ( NodeModulesPolyfillPlugin(), ].filter(isNotNull); - if (build === "app" && mode === "development" && config.future.unstable_dev) { + if (mode === "development" && config.future.unstable_dev) { // TODO prebundle deps instead of chunking just these ones let isolateChunks = [ require.resolve("react"), From 7bd098d517aab29284dac630f7f946ad6f9c1874 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 11:48:54 +1100 Subject: [PATCH 10/22] Roll back console debug --- integration/hmr-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 994ea31436f..df11710b719 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -202,7 +202,7 @@ let bufferize = (stream: Readable): (() => string) => { test("HMR", async ({ page }) => { // uncomment for debugging - page.on("console", (msg) => console.log("PAGE: " + msg.text())); + // page.on("console", (msg) => console.log(msg.text())); page.on("pageerror", (err) => console.log(err.message)); let appServerPort = await getPort({ port: makeRange(3080, 3089) }); From 53e42ae4a37025a1e66ead930a464ece25771357 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 12:09:57 +1100 Subject: [PATCH 11/22] Temporarily move test CSS to static file --- integration/hmr-test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index df11710b719..d3b08c596c0 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -141,12 +141,11 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/_index.tsx": js` import { useLoaderData } from "@remix-run/react"; - import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Index Title

+

Index Title

) } @@ -154,10 +153,11 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/about.tsx": js` import Counter from "../components/counter"; + import styles from "~/styles.module.css"; export default function About() { return (
-

About Title

+

About Title

) @@ -260,12 +260,11 @@ test("HMR", async ({ page }) => { let newIndex = ` import { useLoaderData } from "@remix-run/react"; - import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Changed

+

Changed

) } From cad36b2d80ef72f905cf93251b4e73d28c4a864f Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 12:10:22 +1100 Subject: [PATCH 12/22] Reinstate app build check --- packages/remix-dev/compiler/compileBrowser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 158f2960f10..16e9eb311b5 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -139,7 +139,7 @@ const createEsbuildConfig = ( NodeModulesPolyfillPlugin(), ].filter(isNotNull); - if (mode === "development" && config.future.unstable_dev) { + if (build === "app" && mode === "development" && config.future.unstable_dev) { // TODO prebundle deps instead of chunking just these ones let isolateChunks = [ require.resolve("react"), From 9d66c98393d542c40a6225db93ace85a24aeab90 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 12:26:02 +1100 Subject: [PATCH 13/22] Remove CSS usage from test --- integration/hmr-test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index d3b08c596c0..eef3de80d80 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -153,11 +153,10 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/routes/about.tsx": js` import Counter from "../components/counter"; - import styles from "~/styles.module.css"; export default function About() { return (
-

About Title

+

About Title

) From 80dec78bab024d0daf27b0563b5cde5a7211b8ac Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Fri, 17 Mar 2023 12:43:30 +1100 Subject: [PATCH 14/22] Add css-bundle to test deps --- integration/hmr-test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index eef3de80d80..a94c9e54f64 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -27,6 +27,7 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "dev:app": `cross-env NODE_ENV=development nodemon --watch build/ ./server.js`, }, dependencies: { + "@remix-run/css-bundle": "0.0.0-local-version", "@remix-run/node": "0.0.0-local-version", "@remix-run/react": "0.0.0-local-version", "cross-env": "0.0.0-local-version", From 4bbedf1107fc231e37511259d6a781c951f2fea5 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Sat, 18 Mar 2023 05:54:36 +1100 Subject: [PATCH 15/22] Fix CSS build, convert promise to channel --- packages/remix-dev/compiler/compileBrowser.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 16e9eb311b5..6f374eeb758 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -6,7 +6,8 @@ import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfil import postcss from "postcss"; import postcssDiscardDuplicates from "postcss-discard-duplicates"; -import type { WriteChannel } from "../channel"; +import type { Channel } from "../channel"; +import { createChannel } from "../channel"; import type { RemixConfig } from "../config"; import type { AssetsManifest } from "./assets"; import { createAssetsManifest } from "./assets"; @@ -80,10 +81,10 @@ const isCssBundlingEnabled = (config: RemixConfig): boolean => config.future.unstable_vanillaExtract ); -let cssBundleHrefPromise: Promise; +let cssBundleHrefChannel: Channel; // Allow plugins to access the latest value of the CSS bundle during rebuilds -const getCssBundleHref = () => cssBundleHrefPromise; +const getCssBundleHref = () => cssBundleHrefChannel.read(); const createEsbuildConfig = ( build: "app" | "css", @@ -116,7 +117,7 @@ const createEsbuildConfig = ( let plugins: esbuild.Plugin[] = [ deprecatedRemixPackagePlugin(options.onWarning), - build === "css" ? cssBundleUpdatePlugin({ getCssBundleHref }) : null, + build === "app" ? cssBundleUpdatePlugin({ getCssBundleHref }) : null, isCssBundlingEnabled(config) && isCssBuild ? cssBundleEntryModulePlugin(config) : null, @@ -242,6 +243,8 @@ export const createBrowserCompiler = ( return; } + cssBundleHrefChannel = createChannel(); + // The types aren't great when combining write: false and incremental: true // so we need to assert that it's an incremental build cssCompiler = (await (!cssCompiler @@ -276,6 +279,7 @@ export const createBrowserCompiler = ( ); if (!cssBundleFile) { + cssBundleHrefChannel.write(undefined); return; } @@ -323,10 +327,18 @@ export const createBrowserCompiler = ( return cssBundleHref; }; - cssBundleHrefPromise = cssBuildTask(); + let cssBuildTaskPromise = cssBuildTask(); + + cssBuildTaskPromise + .then((cssBundleHref) => { + cssBundleHrefChannel.write(cssBundleHref); + }) + .catch(() => { + cssBundleHrefChannel.write(undefined); + }); let [cssBundleHref, metafile] = await Promise.all([ - cssBundleHrefPromise, + cssBuildTaskPromise, appBuildTask(), ]); From 8eebb22ea9fbcccfbb98955e8b1cf1f84709ac40 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Sat, 18 Mar 2023 05:59:40 +1100 Subject: [PATCH 16/22] Revert to original CSS bundle HMR test --- integration/hmr-test.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index a94c9e54f64..bd08171da42 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -94,8 +94,7 @@ let fixture = (options: { port: number; appServerPort: number }) => ({ "app/styles.module.css": css` .test { - color: black; - background: orange; + color: initial; } `, @@ -257,25 +256,38 @@ test("HMR", async ({ page }) => { let originalIndex = fs.readFileSync(indexPath, "utf8"); let counterPath = path.join(projectDir, "app", "components", "counter.tsx"); let originalCounter = fs.readFileSync(counterPath, "utf8"); + let cssModulePath = path.join(projectDir, "app", "styles.module.css"); + let originalCssModule = fs.readFileSync(cssModulePath, "utf8"); + + // make content and style changed to index route + let newCssModule = ` + .test { + background: black; + color: white; + } + `; + fs.writeFileSync(cssModulePath, newCssModule); let newIndex = ` import { useLoaderData } from "@remix-run/react"; + import styles from "~/styles.module.css"; export default function Index() { const t = useLoaderData(); return (
-

Changed

+

Changed

) } `; fs.writeFileSync(indexPath, newIndex); - // detect HMR'd content + // detect HMR'd content and style changes await page.waitForLoadState("networkidle"); - let h1 = page.getByText("Changed"); - await h1.waitFor({ timeout: 10000 }); + await h1.waitFor({ timeout: 2000 }); + expect(h1).toHaveCSS("color", "rgb(255, 255, 255)"); + expect(h1).toHaveCSS("background-color", "rgb(0, 0, 0)"); // verify that `` value was persisted (i.e. hmr, not full page refresh) expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); @@ -283,6 +295,7 @@ test("HMR", async ({ page }) => { // undo change fs.writeFileSync(indexPath, originalIndex); + fs.writeFileSync(cssModulePath, originalCssModule); await page.getByText("Index Title").waitFor({ timeout: 2000 }); expect(await page.getByLabel("Root Input").inputValue()).toBe("asdfasdf"); await page.waitForSelector(`#root-counter:has-text("inc 1")`); From 633fa37cb46e8fa5233295e8d7bb6b83d12df8de Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Sat, 18 Mar 2023 06:03:19 +1100 Subject: [PATCH 17/22] Only apply CSS bundle update plugin for HMR --- packages/remix-dev/compiler/compileBrowser.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 6f374eeb758..260e5094129 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -117,7 +117,6 @@ const createEsbuildConfig = ( let plugins: esbuild.Plugin[] = [ deprecatedRemixPackagePlugin(options.onWarning), - build === "app" ? cssBundleUpdatePlugin({ getCssBundleHref }) : null, isCssBundlingEnabled(config) && isCssBuild ? cssBundleEntryModulePlugin(config) : null, @@ -158,6 +157,10 @@ const createEsbuildConfig = ( }; plugins.push(hmrPlugin({ remixConfig: config })); + + if (isCssBundlingEnabled(config)) { + plugins.push(cssBundleUpdatePlugin({ getCssBundleHref })); + } } return { From 28351fe12f45dc3a5d710ac31ba975f19f07632d Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Sat, 18 Mar 2023 06:15:15 +1100 Subject: [PATCH 18/22] Fix type error --- packages/remix-dev/compiler/compileBrowser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 260e5094129..4d242b4e275 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -6,7 +6,7 @@ import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfil import postcss from "postcss"; import postcssDiscardDuplicates from "postcss-discard-duplicates"; -import type { Channel } from "../channel"; +import type { Channel, WriteChannel } from "../channel"; import { createChannel } from "../channel"; import type { RemixConfig } from "../config"; import type { AssetsManifest } from "./assets"; From 9840d20be2b20565d49b02ad623e4633c5ba297c Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Sat, 18 Mar 2023 06:18:40 +1100 Subject: [PATCH 19/22] Remove redundant channel read alias --- packages/remix-dev/compiler/compileBrowser.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 4d242b4e275..9ef9dd76969 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -83,9 +83,6 @@ const isCssBundlingEnabled = (config: RemixConfig): boolean => let cssBundleHrefChannel: Channel; -// Allow plugins to access the latest value of the CSS bundle during rebuilds -const getCssBundleHref = () => cssBundleHrefChannel.read(); - const createEsbuildConfig = ( build: "app" | "css", config: RemixConfig, @@ -159,7 +156,11 @@ const createEsbuildConfig = ( plugins.push(hmrPlugin({ remixConfig: config })); if (isCssBundlingEnabled(config)) { - plugins.push(cssBundleUpdatePlugin({ getCssBundleHref })); + plugins.push( + cssBundleUpdatePlugin({ + getCssBundleHref: cssBundleHrefChannel.read, + }) + ); } } From b60db443a576695ca636841064af09fa7829c62d Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 20 Mar 2023 07:26:28 +1100 Subject: [PATCH 20/22] Move all CSS href channel access into CSS build --- packages/remix-dev/compiler/compileBrowser.ts | 165 +++++++++--------- 1 file changed, 83 insertions(+), 82 deletions(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index 9ef9dd76969..fca7c590b29 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -82,6 +82,7 @@ const isCssBundlingEnabled = (config: RemixConfig): boolean => ); let cssBundleHrefChannel: Channel; +let getCssBundleHref = () => cssBundleHrefChannel.read(); const createEsbuildConfig = ( build: "app" | "css", @@ -158,7 +159,7 @@ const createEsbuildConfig = ( if (isCssBundlingEnabled(config)) { plugins.push( cssBundleUpdatePlugin({ - getCssBundleHref: cssBundleHrefChannel.read, + getCssBundleHref, }) ); } @@ -249,98 +250,98 @@ export const createBrowserCompiler = ( cssBundleHrefChannel = createChannel(); - // The types aren't great when combining write: false and incremental: true - // so we need to assert that it's an incremental build - cssCompiler = (await (!cssCompiler - ? esbuild.build({ - ...createEsbuildConfig("css", remixConfig, options, onLoader), - metafile: true, - incremental: true, - write: false, - }) - : cssCompiler.rebuild())) as esbuild.BuildIncremental; + try { + // The types aren't great when combining write: false and incremental: true + // so we need to assert that it's an incremental build + cssCompiler = (await (!cssCompiler + ? esbuild.build({ + ...createEsbuildConfig("css", remixConfig, options, onLoader), + metafile: true, + incremental: true, + write: false, + }) + : cssCompiler.rebuild())) as esbuild.BuildIncremental; + + invariant( + cssCompiler.metafile, + "Expected CSS compiler metafile to be defined. This is likely a bug in Remix. Please open an issue at https://github.com/remix-run/remix/issues/new" + ); - invariant( - cssCompiler.metafile, - "Expected CSS compiler metafile to be defined. This is likely a bug in Remix. Please open an issue at https://github.com/remix-run/remix/issues/new" - ); + let outputFiles = cssCompiler.outputFiles || []; + + let isCssBundleFile = ( + outputFile: esbuild.OutputFile, + extension: ".css" | ".css.map" + ): boolean => { + return ( + path.dirname(outputFile.path) === + remixConfig.assetsBuildDirectory && + path.basename(outputFile.path).startsWith("css-bundle") && + outputFile.path.endsWith(extension) + ); + }; + + let cssBundleFile = outputFiles.find((outputFile) => + isCssBundleFile(outputFile, ".css") + ); - let outputFiles = cssCompiler.outputFiles || []; + if (!cssBundleFile) { + cssBundleHrefChannel.write(undefined); + return; + } - let isCssBundleFile = ( - outputFile: esbuild.OutputFile, - extension: ".css" | ".css.map" - ): boolean => { - return ( - path.dirname(outputFile.path) === remixConfig.assetsBuildDirectory && - path.basename(outputFile.path).startsWith("css-bundle") && - outputFile.path.endsWith(extension) - ); - }; + let cssBundlePath = cssBundleFile.path; - let cssBundleFile = outputFiles.find((outputFile) => - isCssBundleFile(outputFile, ".css") - ); + let cssBundleHref = + remixConfig.publicPath + + path.relative( + remixConfig.assetsBuildDirectory, + path.resolve(cssBundlePath) + ); - if (!cssBundleFile) { + cssBundleHrefChannel.write(cssBundleHref); + + let { css, map } = await postcss([ + // We need to discard duplicate rules since "composes" + // in CSS Modules can result in duplicate styles + postcssDiscardDuplicates(), + ]).process(cssBundleFile.text, { + from: cssBundlePath, + to: cssBundlePath, + map: options.sourcemap && { + prev: outputFiles.find((outputFile) => + isCssBundleFile(outputFile, ".css.map") + )?.text, + inline: false, + annotation: false, + sourcesContent: true, + }, + }); + + await fse.ensureDir(path.dirname(cssBundlePath)); + + await Promise.all([ + fse.writeFile(cssBundlePath, css), + options.mode !== "production" && map + ? fse.writeFile(`${cssBundlePath}.map`, map.toString()) // Write our updated source map rather than esbuild's + : null, + ...outputFiles + .filter((outputFile) => !/\.(css|js|map)$/.test(outputFile.path)) + .map(async (asset) => { + await fse.ensureDir(path.dirname(asset.path)); + await fse.writeFile(asset.path, asset.contents); + }), + ]); + + return cssBundleHref; + } catch (error) { cssBundleHrefChannel.write(undefined); - return; + throw error; } - - let cssBundlePath = cssBundleFile.path; - - let { css, map } = await postcss([ - // We need to discard duplicate rules since "composes" - // in CSS Modules can result in duplicate styles - postcssDiscardDuplicates(), - ]).process(cssBundleFile.text, { - from: cssBundlePath, - to: cssBundlePath, - map: options.sourcemap && { - prev: outputFiles.find((outputFile) => - isCssBundleFile(outputFile, ".css.map") - )?.text, - inline: false, - annotation: false, - sourcesContent: true, - }, - }); - - await fse.ensureDir(path.dirname(cssBundlePath)); - - await Promise.all([ - fse.writeFile(cssBundlePath, css), - options.mode !== "production" && map - ? fse.writeFile(`${cssBundlePath}.map`, map.toString()) // Write our updated source map rather than esbuild's - : null, - ...outputFiles - .filter((outputFile) => !/\.(css|js|map)$/.test(outputFile.path)) - .map(async (asset) => { - await fse.ensureDir(path.dirname(asset.path)); - await fse.writeFile(asset.path, asset.contents); - }), - ]); - - let cssBundleHref = - remixConfig.publicPath + - path.relative( - remixConfig.assetsBuildDirectory, - path.resolve(cssBundlePath) - ); - - return cssBundleHref; }; let cssBuildTaskPromise = cssBuildTask(); - cssBuildTaskPromise - .then((cssBundleHref) => { - cssBundleHrefChannel.write(cssBundleHref); - }) - .catch(() => { - cssBundleHrefChannel.write(undefined); - }); - let [cssBundleHref, metafile] = await Promise.all([ cssBuildTaskPromise, appBuildTask(), From 60a4910e92d1baf19bc772c9377e9efc9a7cd087 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 20 Mar 2023 09:19:22 +1100 Subject: [PATCH 21/22] Refactor --- packages/remix-dev/compiler/compileBrowser.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index fca7c590b29..b09a2abddcd 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -157,11 +157,7 @@ const createEsbuildConfig = ( plugins.push(hmrPlugin({ remixConfig: config })); if (isCssBundlingEnabled(config)) { - plugins.push( - cssBundleUpdatePlugin({ - getCssBundleHref, - }) - ); + plugins.push(cssBundleUpdatePlugin({ getCssBundleHref })); } } @@ -248,8 +244,6 @@ export const createBrowserCompiler = ( return; } - cssBundleHrefChannel = createChannel(); - try { // The types aren't great when combining write: false and incremental: true // so we need to assert that it's an incremental build @@ -340,10 +334,13 @@ export const createBrowserCompiler = ( } }; - let cssBuildTaskPromise = cssBuildTask(); + // Reset the channel to co-ordinate the CSS and app builds + if (isCssBundlingEnabled(remixConfig)) { + cssBundleHrefChannel = createChannel(); + } let [cssBundleHref, metafile] = await Promise.all([ - cssBuildTaskPromise, + cssBuildTask(), appBuildTask(), ]); From d089f9c1b58aa942336ed3db8c1511cfb9fa0a67 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Mon, 20 Mar 2023 13:22:26 -0400 Subject: [PATCH 22/22] Clean up --- packages/remix-dev/compiler/compileBrowser.ts | 2 ++ packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/remix-dev/compiler/compileBrowser.ts b/packages/remix-dev/compiler/compileBrowser.ts index b09a2abddcd..8692c7e089a 100644 --- a/packages/remix-dev/compiler/compileBrowser.ts +++ b/packages/remix-dev/compiler/compileBrowser.ts @@ -82,6 +82,8 @@ const isCssBundlingEnabled = (config: RemixConfig): boolean => ); let cssBundleHrefChannel: Channel; + +// This function gives esbuild access to the latest channel value on rebuilds let getCssBundleHref = () => cssBundleHrefChannel.read(); const createEsbuildConfig = ( diff --git a/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts b/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts index 29d444a3f30..6fc9298f6d9 100644 --- a/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts +++ b/packages/remix-dev/compiler/plugins/cssBundleUpdatePlugin.ts @@ -16,7 +16,7 @@ export function cssBundleUpdatePlugin({ getCssBundleHref: () => Promise; }): Plugin { return { - name: "css-bundle-update-plugin", + name: pluginName, async setup(build) { let isRebuild = false; build.onEnd(() => {