Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
2 tasks done
samkingco opened this issue May 10, 2023 · 9 comments
Open
2 tasks done

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

samkingco opened this issue May 10, 2023 · 9 comments
Labels
nextjs Issue related to NextJS

Comments

@samkingco
Copy link

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
Copy link

This is true for Solid Start as well

@mattcompiles mattcompiles added nextjs Issue related to NextJS and removed pending triage labels May 15, 2023
@mattcompiles
Copy link
Contributor

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

@dpnolte
Copy link

dpnolte commented May 24, 2023

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
Copy link
Contributor

shuding commented May 26, 2023

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
Copy link
Contributor

shuding commented May 29, 2023

vercel/next.js#50406 should fix this!

timneutkens pushed a commit to vercel/next.js that referenced this issue May 30, 2023
This PR fixes a couple of categories of CSS issues in App Router, that
come from the same root cause.

### 1. Duplicated styles being loaded in different layers

This issue has been described in
vanilla-extract-css/vanilla-extract#1088 (comment).
If a CSS module (or a global CSS) is referenced in multiple layers (e.g.
a layout and a page), it will be bundled into multiple CSS assets
because each layer is considered as a separate entry.

<img width="1141" alt="CleanShot-2023-05-26-GoB9Rhcs@2x"
src="https://github.com/vercel/next.js/assets/3676859/8e0f5346-ee64-4553-950a-7fb44f769efc">

As explained in that issue, we have to bundle all CSS modules into one
chunk to avoid a big number of requests.

### 2. CSS ordering issues (conflicts)

This is likely causing #48120.
When the layer-based bundling and ordering logic applies to CSS, it can
potentially cause non-deterministic order. In this example, button A in
the layout should be in blue. However when button B is imported by the
page, button A becomes red. This is an inconsistent experience and can
be hard to debug and fix.

<img width="1090" alt="CleanShot-2023-05-26-Ar4MN5rP@2x"
src="https://github.com/vercel/next.js/assets/3676859/4328d5d7-23af-4c42-bedf-30f8f062d96a">
hydRAnger pushed a commit to hydRAnger/next.js that referenced this issue Jun 12, 2023
This PR fixes a couple of categories of CSS issues in App Router, that
come from the same root cause.

### 1. Duplicated styles being loaded in different layers

This issue has been described in
vanilla-extract-css/vanilla-extract#1088 (comment).
If a CSS module (or a global CSS) is referenced in multiple layers (e.g.
a layout and a page), it will be bundled into multiple CSS assets
because each layer is considered as a separate entry.

<img width="1141" alt="CleanShot-2023-05-26-GoB9Rhcs@2x"
src="https://github.com/vercel/next.js/assets/3676859/8e0f5346-ee64-4553-950a-7fb44f769efc">

As explained in that issue, we have to bundle all CSS modules into one
chunk to avoid a big number of requests.

### 2. CSS ordering issues (conflicts)

This is likely causing vercel#48120.
When the layer-based bundling and ordering logic applies to CSS, it can
potentially cause non-deterministic order. In this example, button A in
the layout should be in blue. However when button B is imported by the
page, button A becomes red. This is an inconsistent experience and can
be hard to debug and fix.

<img width="1090" alt="CleanShot-2023-05-26-Ar4MN5rP@2x"
src="https://github.com/vercel/next.js/assets/3676859/4328d5d7-23af-4c42-bedf-30f8f062d96a">
@okonet
Copy link
Contributor

okonet commented Oct 13, 2023

@shuding it seems to still happen on Next@13.5.4

CleanShot 2023-10-13 at 10 33 00@2x

@thdwlsgus0
Copy link

@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
Copy link

I just faced this problem on next@14.0.2.

@askoufis
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
nextjs Issue related to NextJS
Projects
None yet
Development

No branches or pull requests

9 participants