evanw / evanw/esbuild

CSS is wrongly present in bundle when the CSS import is done in an unused nested JS import

Open
#2,933 6 comments 9 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
40.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

test.jsx is my entry point. It imports just `Pink` JSX file, but it does this through an named import from a high level 'all' file, which includes more exported functions.

In the resulting bundled dist/index.css I am expected to see the CSS that the 'Pink' JSX file imports, aka `pink.css`
but not the CSS from the other exported but unused modules.

``` bash

[kkoukiou@sequioa test-esbuild-css-treeshaking]$ tail -n +1 test.jsx all/*
==> test.jsx <==
import * as React from 'react'
import * as Server from 'react-dom/server'
import { Pink } from './all'

console.log(Server.renderToString())

==> all/blue.css <==
.mycolor {
color: blue;
}

==> all/Blue.jsx <==
import * as React from 'react';

import "./blue.css";

export const Blue = () => {
return "

test
";
};

==> all/index.js <==
export * from './Pink';
export * from './Blue';

==> all/pink.css <==
.mycolor {
color: pink;
}

==> all/Pink.jsx <==
import * as React from 'react';

import "./pink.css";

export const Pink = () => {
return "

test
";
};

```

However the resulting dist/test.css file contains the CSS which I am expecting to be tree-shaked.
```
[kkoukiou@sequioa test-esbuild-css-treeshaking]$ cat dist/test.css
/* pink.css */
.mycolor {
color: pink;
}

/* blue.css */
.mycolor {
color: blue;
}

```
The esbuild is used here like this: `./node_modules/.bin/esbuild test.jsx --bundle --outdir=dist
`

And lastly the package.json for the complete reproducer:
```
[kkoukiou@sequioa test-esbuild-css-treeshaking]$ cat package.json
{
"devDependencies": {
"esbuild": "^0.17.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
```

Note: when importing with 'import { Pink } from './all/Pink' it works as expected.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the case with test.jsx, all/index.js, all/Pink.jsx, and all/Blue.jsx using the shown esbuild command. Compare the generated CSS with the imports reachable from the named Pink export. Done means the bundle contains pink.css but excludes blue.css while preserving the direct-import behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, javascript, react
Domain
build-system, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.