vanilla-extract-css / vanilla-extract

Zero-runtime Stylesheets-in-TypeScript
https://vanilla-extract.style
MIT License
9.6k stars 291 forks source link

Shared CSS is bundled multiple times with App Router in Next #1088

Open samkingco opened 1 year ago

samkingco commented 1 year ago

Describe the bug

If you have a component that's shared between a layout.tsx and a page.tsx, then the bundled CSS is output multiple times. This behaviour is different to the pages directory, and results in larger bundle sizes due to duplicate CSS.

Here's a quick screenshot of the Button element in the repo that is share by the layout and the page. You can see the two separate CSS files with the same declarations. This is true of both dev and production builds.

CleanShot 2023-05-10 at 15 38 03@2x

Reproduction

https://github.com/samkingco/vanilla-extract-app-dir

System Info

System:
    OS: macOS 13.2.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 1.31 GB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm
    Watchman: 2022.10.24.00 - /opt/homebrew/bin/watchman
  Browsers:
    Brave Browser: 107.1.45.123
    Chrome: 113.0.5672.92
    Firefox: 109.0
    Safari: 16.3
  npmPackages:
    @vanilla-extract/css: ^1.11.0 => 1.11.0
    @vanilla-extract/next-plugin: ^2.1.2 => 2.1.2
    @vanilla-extract/recipes: ^0.4.0 => 0.4.0
    webpack: 5.74.0 => 5.74.0

Used Package Manager

npm

Logs

No response

Validations

cs-clarence commented 1 year ago

This is true for Solid Start as well

mattcompiles commented 1 year ago

Need to speak to the Next team about how to handle this. Will report back.

dpnolte commented 1 year ago

We've perhaps noticed a similar issue. Using the app router, the transpiled contents from .css.ts files are also included in the client bundle even if the .css.ts file is only imported for server components. As a result, the first js load of a page is increased. The tree shaking of the Vanilla-extract related code seemed to work much better with the page router.

I've created a quick codesandbox: https://codesandbox.io/p/sandbox/quizzical-kate-rfmpri?file=%2F.codesandbox%2Ftasks.json%3A22%2C40

In this sandbox, the next project will be build and print out the file contents in .next/static/chunks/app/page-*.js. It will include the js for page.css.ts even though it is only used for a server component:

{container:function(){return e},container2:function(){return f}}),t(3786);var e="_1ogfafu0",f="_1ogfafu1"}
shuding commented 1 year ago

Hey! This isn't specifically related to vanilla-extract, it's the current behavior if you use global CSS or CSS modules in app/ as well. And we're thinking about improving it.

The tricky part is that a layout and a page will not always render together. It's possible that another page that doesn't contain these styles is under the same layout. In pages/ one route is just one entry so all styles are combined together, but now there're multiple entries that won't always be rendered together.

However, I'll let you know if we make any progress there!

shuding commented 1 year ago

https://github.com/vercel/next.js/pull/50406 should fix this!

okonet commented 1 year ago

@shuding it seems to still happen on Next@13.5.4

CleanShot 2023-10-13 at 10 33 00@2x
thdwlsgus0 commented 1 year ago

@shuding it seems to still happen on Next@13.4.7

I want to solve this problem bb..

스크린샷 2023-11-09 오전 1 39 54
otaviosoares commented 12 months ago

I just faced this problem on next@14.0.2.

askoufis commented 7 months ago

This seems similar to #1276. Apparently next 14.1.3 fixes duplicate styles in prod (they're still present in dev). Your reproduction no longer exists, so I can't test it.