Skip to content

Commit

Permalink
fix(remix-dev/vite): bundle CSS from client entry (#8143)
Browse files Browse the repository at this point in the history
Co-authored-by: Pedro Cattori <[email protected]>
  • Loading branch information
markdalgleish and pcattori authored Nov 28, 2023
1 parent 2d3e1d8 commit c043a66
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 71 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-hotels-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

Bundle CSS imported in client entry file in Vite plugin
40 changes: 34 additions & 6 deletions integration/vite-css-build-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ test.describe("Vite CSS build", () => {
],
});
`,
"app/entry.client.tsx": js`
import "./entry.client.css";
import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
`,
"app/root.tsx": js`
import { Links, Meta, Outlet, Scripts } from "@remix-run/react";
Expand All @@ -70,6 +86,12 @@ test.describe("Vite CSS build", () => {
);
}
`,
"app/entry.client.css": css`
.client-entry {
background: pink;
padding: ${TEST_PADDING_VALUE};
}
`,
"app/routes/_index/styles-bundled.css": css`
.index_bundled {
background: papayawhip;
Expand Down Expand Up @@ -118,12 +140,14 @@ test.describe("Vite CSS build", () => {
export default function IndexRoute() {
return (
<div id="index">
<div data-css-modules className={cssModulesStyles.index}>
<div data-css-linked className="index_linked">
<div data-css-bundled className="index_bundled">
<div data-css-vanilla-global className="index_vanilla_global">
<div data-css-vanilla-local className={stylesVanillaLocal.index}>
<h2>CSS test</h2>
<div data-client-entry className="client-entry">
<div data-css-modules className={cssModulesStyles.index}>
<div data-css-linked className="index_linked">
<div data-css-bundled className="index_bundled">
<div data-css-vanilla-global className="index_vanilla_global">
<div data-css-vanilla-local className={stylesVanillaLocal.index}>
<h2>CSS test</h2>
</div>
</div>
</div>
</div>
Expand All @@ -146,6 +170,10 @@ test.describe("Vite CSS build", () => {
test("renders styles", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/");
await expect(page.locator("#index [data-client-entry]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
);
await expect(page.locator("#index [data-css-modules]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
Expand Down
64 changes: 58 additions & 6 deletions integration/vite-css-dev-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ test.describe("Vite CSS dev", () => {
],
});
`,
"app/entry.client.tsx": js`
import "./entry.client.css";
import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
`,
"app/root.tsx": js`
import { Links, Meta, Outlet, Scripts, LiveReload } from "@remix-run/react";
Expand All @@ -64,6 +80,12 @@ test.describe("Vite CSS dev", () => {
);
}
`,
"app/entry.client.css": css`
.client-entry {
background: pink;
padding: ${TEST_PADDING_VALUE};
}
`,
"app/styles-bundled.css": css`
.index_bundled {
background: papayawhip;
Expand Down Expand Up @@ -113,12 +135,14 @@ test.describe("Vite CSS dev", () => {
return (
<div id="index">
<input />
<div data-css-modules className={cssModulesStyles.index}>
<div data-css-linked className="index_linked">
<div data-css-bundled className="index_bundled">
<div data-css-vanilla-global className="index_vanilla_global">
<div data-css-vanilla-local className={stylesVanillaLocal.index}>
<h2>CSS test</h2>
<div data-client-entry className="client-entry">
<div data-css-modules className={cssModulesStyles.index}>
<div data-css-linked className="index_linked">
<div data-css-bundled className="index_bundled">
<div data-css-vanilla-global className="index_vanilla_global">
<div data-css-vanilla-local className={stylesVanillaLocal.index}>
<h2>CSS test</h2>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -169,6 +193,10 @@ test.describe("Vite CSS dev", () => {
await page.goto(`http://localhost:${devPort}/`, {
waitUntil: "networkidle",
});
await expect(page.locator("#index [data-client-entry]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
);
await expect(page.locator("#index [data-css-modules]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
Expand Down Expand Up @@ -205,6 +233,10 @@ test.describe("Vite CSS dev", () => {
// Ensure no errors on page load
expect(pageErrors).toEqual([]);

await expect(page.locator("#index [data-client-entry]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
);
await expect(page.locator("#index [data-css-modules]")).toHaveCSS(
"padding",
TEST_PADDING_VALUE
Expand Down Expand Up @@ -300,8 +332,28 @@ test.describe("Vite CSS dev", () => {
UPDATED_TEST_PADDING_VALUE
);

// Ensure CSS updates were handled by HMR
await expect(input).toHaveValue("stateful");

// The following change triggers a full page reload, so we check it after all the checks for HMR state preservation
let clientEntryCssContents = await fs.readFile(
path.join(projectDir, "app/entry.client.css"),
"utf8"
);
await fs.writeFile(
path.join(projectDir, "app/entry.client.css"),
clientEntryCssContents.replace(
TEST_PADDING_VALUE,
UPDATED_TEST_PADDING_VALUE
),
"utf8"
);

await expect(page.locator("#index [data-client-entry]")).toHaveCSS(
"padding",
UPDATED_TEST_PADDING_VALUE
);

expect(pageErrors).toEqual([]);
});
});
Expand Down
21 changes: 21 additions & 0 deletions packages/remix-dev/vite/import-vite-esm-sync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// This file is used to avoid CJS deprecation warnings in Vite 5 since
// @remix-run/dev currently compiles to CJS. By using this interface, we only
// ever access the Vite package via a dynamic import which forces the ESM build.
// "importViteAsync" is expected be called up-front in the first async plugin
// hook, which then unlocks "importViteEsmSync" for use anywhere in the plugin
// and its utils. This file won't be needed when this package is ESM only.

import invariant from "../invariant";

// eslint-disable-next-line @typescript-eslint/consistent-type-imports
type Vite = typeof import("vite");
let vite: Vite | undefined;

export async function preloadViteEsm(): Promise<void> {
vite = await import("vite");
}

export function importViteEsmSync(): Vite {
invariant(vite, "importViteEsmSync() called before preloadViteEsm()");
return vite;
}
Loading

0 comments on commit c043a66

Please sign in to comment.