remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
30.14k stars 2.55k forks source link

Inconsistent bundling of css assets between builds (Vite, Stylex) #9451

Open predaytor opened 6 months ago

predaytor commented 6 months ago

Reproduction

When using the ?url import, there seems to be a mismatch between the generated assets, resulting in two identical css files (with different hashes), with the mismatched included at the top of the <head/>. It's a vite-plugin-stylex-dev for StyleX css solution.

For some reason I cannot reproduce bug in the sandbox.

This happens occasionally between builds, so maybe it's due to some internal Remix caching. When this mismatch occurs, this line outputs:

✓ 1 resource moved from Remix server build to client resources.
build/client/assets/index-CiOyfy0p.css

Logs:

> remix vite:build

Using vars defined in .dev.vars
Using vars defined in .dev.vars
Using vars defined in .dev.vars
Using vars defined in .dev.vars
vite v5.2.11 building for production...
✓ 827 modules transformed.
Generated an empty chunk: "phone-textfield".
build/client/.vite/manifest.json                            18.13 kB │ gzip:  1.81 kB
build/client/assets/sprite-BdV8AqDD.svg                     30.02 kB │ gzip:  9.43 kB
build/client/assets/index-N3JczSMr.css                     102.92 kB │ gzip: 21.23 kB
build/client/assets/phone-textfield-l0sNRNKZ.js              0.00 kB │ gzip:  0.02 kB
build/client/assets/_app.users.teachers-D0KjJBcV.js          0.13 kB │ gzip:  0.14 kB
build/client/assets/_app.users.removed-Bw8pfhzk.js           0.13 kB │ gzip:  0.14 kB
build/client/assets/_app.users.administrators-zltEt6Gl.js    0.13 kB │ gzip:  0.14 kB
build/client/assets/_app.users.applicants-zltEt6Gl.js        0.13 kB │ gzip:  0.14 kB
build/client/assets/recovery-DNcuDyGd.js                     0.13 kB │ gzip:  0.14 kB
build/client/assets/toggle-button-BRlrV58r.js                0.29 kB │ gzip:  0.23 kB
build/client/assets/data-RBlXXuFm.js                         0.36 kB │ gzip:  0.31 kB
build/client/assets/_app.groups-DRAlv3Dh.js                  0.37 kB │ gzip:  0.29 kB
build/client/assets/_app.applications-DSix6XLc.js            0.37 kB │ gzip:  0.29 kB
build/client/assets/_app.dashboard-DGrcCHYH.js               0.37 kB │ gzip:  0.29 kB
build/client/assets/_app.profile-CDyQESv2.js                 0.37 kB │ gzip:  0.29 kB
build/client/assets/_app.calendar-B-6OaHIp.js                0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.learning-DN9SaJxK.js                0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.report-DHEzYFMA.js                  0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.library-BOJ6LJAi.js                 0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.transactions-BwQdegkR.js            0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.history-ocq8kroE.js                 0.37 kB │ gzip:  0.30 kB
build/client/assets/_app.settings-CeF1owLH.js                0.37 kB │ gzip:  0.31 kB
build/client/assets/_app.messages-S8M7tn2Y.js                0.37 kB │ gzip:  0.30 kB
build/client/assets/icon-button--aXbSP48.js                  0.41 kB │ gzip:  0.28 kB
build/client/assets/birthday-datefield-BqNzzUqC.js           0.42 kB │ gzip:  0.33 kB
build/client/assets/icon-D09kYBQN.js                         0.43 kB │ gzip:  0.30 kB
build/client/assets/heading-C_rbyHuK.js                      0.48 kB │ gzip:  0.34 kB
build/client/assets/header-C0nPIVLm.js                       0.65 kB │ gzip:  0.49 kB
build/client/assets/container-B01piXsx.js                    0.70 kB │ gzip:  0.42 kB
build/client/assets/logo-DuT4e1vb.js                         0.75 kB │ gzip:  0.49 kB
build/client/assets/phone-textfield-C-jSd1_r.js              1.00 kB │ gzip:  0.59 kB
build/client/assets/email-textfield-CTVomzYq.js              1.42 kB │ gzip:  0.77 kB
build/client/assets/_app.users_.students._id-B3Yrzq6t.js     1.82 kB │ gzip:  0.95 kB
build/client/assets/_auth.signup-CArL0x5s.js                 2.52 kB │ gzip:  1.18 kB
build/client/assets/_auth-DBv4tsY3.js                        2.77 kB │ gzip:  1.44 kB
build/client/assets/_auth.login-ChIY2W4h.js                  2.84 kB │ gzip:  1.37 kB
build/client/assets/stylex-BOjyk742.js                       2.95 kB │ gzip:  1.35 kB
build/client/assets/route-D9NRnaPk.js                        2.99 kB │ gzip:  1.23 kB
build/client/assets/_app.users_.students.new-DLn0FcZR.js     3.25 kB │ gzip:  1.65 kB
build/client/assets/root-Csrl-H1Q.js                         3.39 kB │ gzip:  1.54 kB
build/client/assets/avatar-CWYAx4KT.js                       3.42 kB │ gzip:  1.40 kB
build/client/assets/form-C70NaR-f.js                         3.98 kB │ gzip:  1.55 kB
build/client/assets/checkbox-CoohEvgQ.js                     4.08 kB │ gzip:  1.33 kB
build/client/assets/route-j0DL5Qgm.js                        4.56 kB │ gzip:  2.21 kB
build/client/assets/input-qekBshbH.js                        6.82 kB │ gzip:  2.00 kB
build/client/assets/password-textfield-Qbj1_dUL.js           8.38 kB │ gzip:  2.30 kB
build/client/assets/jsx-runtime-C7dT0ItP.js                  9.95 kB │ gzip:  3.63 kB
build/client/assets/entry.client-VFfHxz5W.js                11.63 kB │ gzip:  4.09 kB
build/client/assets/route-COXK8fsl.js                       21.87 kB │ gzip:  6.73 kB
build/client/assets/index-CQFX0XzH.js                       36.81 kB │ gzip: 11.07 kB
build/client/assets/components-DxQqOcDi.js                 276.88 kB │ gzip: 87.94 kB
build/client/assets/sprite-D7EuGFbZ.js                     329.70 kB │ gzip: 91.42 kB
✓ built in 2.62s
Using vars defined in .dev.vars
Using vars defined in .dev.vars
vite v5.2.11 building SSR bundle for production...
"chain" is imported from external module "react-aria" but never used in "app/routes/_app.users.students/data.tsx", "app/components/fieldgroup.tsx", "app/components/link.tsx", "app/components/upload-file-field.tsx", "app/components/searchfield.tsx", "app/routes/_app/route.tsx", "app/components/avatar/avatar.tsx", "app/routes/_app.users/user-alert-dialog.tsx" and "app/routes/_app.users.students/route.tsx".
✓ 100 modules transformed.
build/server/.vite/manifest.json           0.51 kB
build/server/assets/sprite-BdV8AqDD.svg   30.02 kB
build/server/assets/index-CiOyfy0p.css   102.92 kB
build/server/index.js                    204.82 kB

✓ 1 asset moved from Remix server build to client assets.
build/client/assets/index-CiOyfy0p.css

✓ built in 862ms

https://github.com/remix-run/remix/blob/2e65318b15df407b31b101362e03729e61ec5622/packages/remix-dev/vite/plugin.ts#L1441-L1454


Знімок екрана 2024-05-16 о 11 37 54 Знімок екрана 2024-05-16 о 11 40 38

Original issue: https://github.com/nonzzz/vite-plugin-stylex/issues/25

System Info

System:
    OS: macOS 14.4
    CPU: (8) arm64 Apple M1
    Memory: 74.84 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.9.0 - /usr/local/bin/node
    Yarn: 1.22.22 - /usr/local/bin/yarn
    npm: 10.1.0 - /usr/local/bin/npm
    pnpm: 9.1.0 - /usr/local/bin/pnpm
    bun: 1.0.12 - ~/.bun/bin/bun
  Browsers:
    Chrome: 124.0.6367.208
    Chrome Canary: 126.0.6478.1
    Safari: 17.4
    Safari Technology Preview: 17.4
  npmPackages:
    @remix-run/cloudflare: ^2.9.2 => 2.9.2 
    @remix-run/cloudflare-pages: ^2.9.2 => 2.9.2 
    @remix-run/dev: ^2.9.2 => 2.9.2 
    @remix-run/react: ^2.9.2 => 2.9.2 
    vite: ^5.2.11 => 5.2.11

Used Package Manager

pnpm

Expected Behavior

pnpm build should result in a single css file

Actual Behavior

pnpm build results in identical duplicate of the original css file and includes it in the output html

stewarthsoj commented 6 months ago

I'm not sure if these issues are related but I'm experiencing this too with Tailwind. I only have one CSS file in my Remix project, that being root.css. The build is outputting two CSS files, though slightly different in size.

Build Output
predaytor commented 5 months ago

it seems that after the release of vite@5.2.12 everything is fine, the duplicated css asset was generated in output (still odd), but not included in the application anymore.

predaytor commented 5 months ago

update: Unfortunately, the problem persists. currently some routes load a single css file, others include duplicate.

machour commented 1 month ago

@JoshStwrt I've experienced the same issue, and was able to fix it by changing from a ?url import to a side effect (import "~/app.css"). In this case Remix handle all this and there's no problem.

I'm trying to come up with a reproduce case for the team, but it seems like I'm unable to reproduce it outside my huge private project. Are you able to reproduce the bug?

machour commented 1 month ago

Running a diff on both generated files (after reformatting with prettier), shows the following diffs:

 .bg-gray-500\/20 {
-  background-color: #6b728033;
+  background-color: rgba(107, 114, 128, 0.2);
 }
 .bg-green-50 {
   --tw-bg-opacity: 1;
@@ -2048,7 +2048,7 @@
   background-color: rgb(217 0 0 / var(--tw-bg-opacity));
 }
 .bg-ram\/20 {
-  background-color: #d9000033;
+  background-color: rgba(217, 0, 0, 0.2);
 }
 .bg-red-50 {
   --tw-bg-opacity: 1;
@@ -2059,7 +2059,7 @@
   background-color: rgb(153 27 27 / var(--tw-bg-opacity));
 }
 .bg-slate-900\/80 {
-  background-color: #0f172acc;
+  background-color: rgba(15, 23, 42, 0.8);
 }

something is inconsistent in the manner the tailwind css files are generated

machour commented 1 month ago

Found the culprit, I'm using @vitejs/plugin-legacy to support older devices. As soon as I remove it from vite, the problem goes away:

diff --git a/www/front/vite.config.js b/www/front/vite.config.js
index 71de5e117..47f56c9ba 100644
--- a/www/front/vite.config.js
+++ b/www/front/vite.config.js
@@ -1,6 +1,5 @@
 import { vitePlugin as remix } from "@remix-run/dev";
 import { installGlobals } from "@remix-run/node";
-import legacy from "@vitejs/plugin-legacy";
 import { flatRoutes } from "remix-flat-routes";
 import { defineConfig } from "vite";
 import tsconfigPaths from "vite-tsconfig-paths";
@@ -21,9 +20,6 @@ export default defineConfig({
       },
       routes: async defineRoutes => flatRoutes("routes", defineRoutes),
     }),
-    legacy({
-      targets: ["defaults", "safari >= 12.1", "not IE 11"],
-    }),
     tsconfigPaths(),
   ],
 });

There's an inconsistency somewhere between the client and server build !

machour commented 1 month ago

Reproduce case on the latest remix version: https://github.com/machour/remix-issue-9451

silvenon commented 1 month ago

Seems like @vitejs/plugin-legacy is creating another bundle that's intended to be inserted separately, but perhaps Remix doesn't have a way of handling that, so the server build collects the modern bundle, and the client build hydrates with the legacy bundle, or the other way around.

Maybe Remix's Vite plugin for collecting styles doesn't recognize that one styles are coming from one modern bundle and another from the legacy bundle because the import is named the same.

I'm yet to familiarize myself with FOUC-less Vite dev experience when SSR is involved, I just know that these Vite plugins for styles by frameworks follow a similar gimmick.

I hope that someone comes to the rescue 🤞 In the meantime I'll try to find out what more I can.