-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
docs: add information about "sideEffects" #10691
base: main
Are you sure you want to change the base?
Conversation
|
This looks really good. The main thing I noted while looking at this is that most Svelte users use Vite and the Vite docs say nothing about |
Thanks! Sounds good, I've opened an issue, we can see what they say. |
I do see mention of side effects in rollup's docs, but I can't find it in Vite's either. |
Co-authored-by: Willow (GHOST) <ghostdevbusiness@gmail.com>
Co-authored-by: Willow (GHOST) <ghostdevbusiness@gmail.com>
Co-authored-by: Willow (GHOST) <ghostdevbusiness@gmail.com>
|
||
By adding `"sideEffects": false` in the `package.json`, you're signaling to the bundler that your package doesn't include any modules with side effects. This information can help the bundler to be more aggressive in eliminating unused exports from the final bundle, a process known as tree-shaking. This results in smaller and more efficient bundles. | ||
|
||
> In the case of a Svelte component library, this prevents CSS from components that are not being used from being included in the final build. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm that setting sideEffects false for Svelte files doesn't have any unintended consequences, eg. even imported components not getting their CSS included?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm definitely not an expert on this, but I have tested with my library and everything is working as expected. I looked at a few other libraries with styles and have found they have this specified as well.
This is the only way I found to prevent the issue of all of the CSS being bundled, but open to suggestions if there is a better way to prevent this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is correct.
Carbon Svelte ships pre-compiled CSS stylesheets that the consumer imports in their app. The sideEffects: ['css/*.css']
field is necessary explicitly for bundlers that tree shake when building for production.
One example is webpack. From the webpack docs:
Note that any imported file is subject to tree shaking. This means if you use something like css-loader in your project and import a CSS file, it needs to be added to the side effect list so it will not be unintentionally dropped in production mode:
In the case of Carbon, if the user has the following:
import "carbon-components-svelte/css/all.css";
When building for production, Webpack will exclude that file if sideEffects
does not explicitly include those CSS files. As a result, the stylesheet will be unexpectedly tree-shaken.
On the contrary, if the CSS stylesheet is imported in the Button
component (that is then used by the consumer), it will not be excluded as it becomes a part of the dependency tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like perhaps our recommendation should be to set "sideEffects": ["**/*.css"]
? I think that would lead to the desired outcome (webpack-contrib/mini-css-extract-plugin#118 (comment)). Most users will simply be distributing .svelte
files in which case I suppose there would be no .css
to match and so generally "sideEffects": false
would be equivalent, but "sideEffects": ["**/*.css"]
could be a little safer and avoid users running into trouble as soon as they add .css
. I would love for others to confirm or test this as I don't have a ton of expertise in this area
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works, I published my test repo and added this example in case this helps: https://github.com/rossrobino/side-effects-test
You can see the build outputs with sideEffects set to false
, true
, and ["**/*.css"]
.
It can be tested by editing node_modules/drab/package.json
.
The imported Breakpoint
component in +page.svelte
has no CSS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
components using scoped styles exported through a barrel index.js files are the ones having the problem. Their css is added even if you never use them as soon as you import a single one from a barrel, all the css gets included
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I just tried setting sideEffects: ["**/*.css"]
in the site-kit
package and the built CSS for kit.svelte.dev in this repo seemed to have gotten much larger as a result. I'm not sure which CSS exactly changed. It will take some more investigation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this is weird. sideEffects: false
in site-kit
massively increases the CSS for kit.svelte.dev (the same as doing sideEffects: ["**/*.css"]
). E.g. you can see the :root
CSS ends up in 0.css
in addition to one of the _layout
CSS files. Omitting the sideEffects
field or putting sideEffects: []
result in smaller CSS output. I don't know how that makes any sense because what's the difference between sideEffects: false
and sideEffects: []
? I filed an issue in Vite for this: vitejs/vite#14558
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is weird. For what it's worth I'm seeing the same in my tester. When I set sideEffects: []
, output is the same as sideEffects: true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vitejs/vite#16152 was merged to fix this. I'm guessing that will be a part of Vite 5.2. We can revisit this docs PR once that's out
see this issue in vite vitejs/vite#4389 (via #10633) A blanket recommendation for Before we change the documentation i'd like to see a repository demonstrating that and how it works. Other options to explore:
"exports": {
"svelte": {
"import": {
"./Foo.svelte": "./src/components/Foo.svelte"
}
}
} (I did experiment with globs in exports map a while ago but back then it was buggy for *.svelte) |
I agree they shouldn't, so think it would be nice to make that the recommendation. I think this PR both mentions the dangers of getting it wrong and shows how to explicitly list the files with side effects where it says "Make sure that
We could mention that would also address the issue in this section. I don't think we should go as far as recommending users always do it as it seems to be a case-by-case basis as to which might be the better design for a library |
did some investigation here: sveltejs/vite-plugin-svelte#760 there are several ways in vite/rollup to say some module does not have a side effect, but currently the only one working seems to be the package.json field that's mentioned here. So unless there is a change that allows us to declare the virtual css modules from vite-plugin-svelte as free, the suggestion to add If you are using barrel files inside your own application, you can also add this to the package.json in your app and it'll work. |
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Judging from the discussion in #10691 (comment) it seems that bundlers work in weird ways (and may work differently across bundlers?) depending on the value of |
Just throwing my hat into the ring here that this should at least be better advertised due to how focused Sveltekit is on performance. Right now I am maintaining a pretty mature Sveltekit app that imports a core Svelte library everywhere. Implementing this simple trick just gained me like 10 points on my lighthouse scores. |
Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm test
and lint the project withpnpm lint
andpnpm check
Changesets
pnpm changeset
and following the prompts. Changesets that add features should beminor
and those that fix bugs should bepatch
. Please prefix changeset messages withfeat:
,fix:
, orchore:
.sideEffects
I recently discovered that the CSS from every component in my library (you can test by importing from 3.0.6 vs 3.0.7) was being included in the build when only one component was being used. By adding
"sideEffects": false
topackage.json
it was resolved. I figured this would be good to add to the docs to minimize bundle sizes for component libraries.