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

Improve tree-shaking of external libraries #17767

Open
filipsobol opened this issue Jan 17, 2025 · 2 comments
Open

Improve tree-shaking of external libraries #17767

filipsobol opened this issue Jan 17, 2025 · 2 comments
Labels
type:improvement This issue reports a possible enhancement of an existing feature.

Comments

@filipsobol
Copy link
Member

filipsobol commented Jan 17, 2025

Issue

As described in #16395, we use a few external libraries that are not tree-shakeable. This unnecessarily increases the bundle size in projects that don't make use of them. This includes:

  • ui — depends on color-convert and color-name, which are only needed with plugins using color picker.
  • markdown-gfm — depends on marked and turndown, which are only needed when the Markdown plugin is used.
  • real-time-collaboration — depends on socket.io, protobufjs, and many others, which are only needed when RTC features are used.

Our code in these packages is already fully tree-shakeable, but because these dependencies are not, they are kept in the bundle. The only way to prevent these dependencies from always being bundled that I'm aware of (except for replacing these libraries with others that are tree-shakeable) is to add sideEffects field to package.json files of our packages depending on these libraries.

The sideEffects field

The sideEffects field in a package.json file indicates whether the entire package or specific files within it have side effects when imported, which helps bundlers with tree-shaking to remove unused code more effectively.

Solution

If a file with side effects is not added to the sideEffects array, it may be tree-shaken away, causing issues or breaking the editor entirely. That is why I would avoid adding this field to all of our packages, but only as a last resort to these that have non-tree-shakeable external libraries. We also have to be careful to include in the array all the files that have side effects like:

  • *.css files
  • build/**/*.js files (build and translations)
  • dist/translations/*.umd.js

The result

Adding these fields to ui, markdown-gfm, and real-time-collaboration reduces the bundle size by up to 140 KiB in Vite/Rollup and 130 KiB in esbuild. The following, darkened dependencies were removed from Rollup and esbuild builds with the following code:

import 'ckeditor5';
import 'ckeditor5-premium-features';

Image

Testing

To make sure that this change doesn't introduce any regressions, we need to test all three packages mentioned above and see if they work properly in old and new installation methods. While unlikely, it's possible that too much code will be tree-shaken away, breaking these features or their styles.

@filipsobol filipsobol added the type:improvement This issue reports a possible enhancement of an existing feature. label Jan 17, 2025
@filipsobol
Copy link
Member Author

filipsobol commented Jan 17, 2025

The tests/**/*.js entry must also be added to the sideEffects array because otherwise webpack used in Karma is tree-shaking all the tests. Unfortunately, it's not possible to disable tree-shaking in this setup because the karma-webpack plugin always removes the optimization key from the configuration.

Update: This can be worked around using webpack plugin. See ckeditor/ckeditor5-dev#1060.

@filipsobol
Copy link
Member Author

We've decided to implement this improvement in two steps. In the first step, we will add the sideEffects field to the markdown-gfm plugin and a new integration we will release soon. This allows us to test the waters on low-impact packages, before implementing the same in ui and real-time-collaboration packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:improvement This issue reports a possible enhancement of an existing feature.
Projects
None yet
Development

No branches or pull requests

1 participant