evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
37.92k stars 1.13k forks source link

Optionally disable CSS selectors renaming in local-css across entrypoints #3709

Open astashov opened 5 months ago

astashov commented 5 months ago

Currently, esbuild makes sure that the same CSS names across entrypoints get renamed if they collide. But that results in renaming CSS for the same component that gets reused across multiple bundles, which doesn't work well with server-side rendering.

For example, I'm running esbuild twice to build bundles for server and for client. For server I generate one global server.ts, using platform: "none" in esbuild. For the clients, I specify multiple entrypoints - one per each page (main.ts, reviews.ts, etc).

Then, main.ts and reviews.ts use a shared component, e.g. <Menu /> which uses CSS modules. So main.css is generated with .menu_label, .menu_item, etc. and reviews.css is generated with .menu_label2, menu_item2, etc.

But when I server-render the pages, since I only have one bundle server.ts, that doesn't know anything about renamed classes, it generates pages with .menu_label (and not .menu_label2) both for Main and Reviews pages, so Reviews pages gets broken.

Would it be possible to provide an option to only rename collides within one entrypoint? Or maybe there's some another approach exists?

Thanks so much for all your great work on esbuild!

jrabausch commented 4 months ago

Hi there,

I have a similar issue regarding CSS modules. For example, I have a app.module.css that is used by the server.js bundle to generate dynamic html:

import styles from 'app.module.css';

return `<div class="${styles.main}"></div>`;

Now for the client side app.js bundle, I would like to use the same CSS module to work with the class names:

import styles from 'app.module.css';

const element = document.querySelector(`.${styles.main}`);

Now obviously two CSS files are generated. If nothing gets renamed, everything is fine and I only use one of them. But if renaming happens, like when I try to minify the client app.js bundle, the class names do not match the ones used by the server.js bundle.

Is there a way to solve this? A nice solution would be the possibility to define different platforms for entry points. So the server and client code could be generated with shared dependencies and within one build run.

Kind regards Johannes