Skip to content

[OP-20422] Bundle with esbuild instead of webpack (1/2) - #139

Open
myabc wants to merge 2 commits into
code-maintenance/OP-18993-typescript-pluginsfrom
code-maintenance/OP-20422-esbuild
Open

myabc wants to merge 2 commits into
code-maintenance/OP-18993-typescript-pluginsfrom
code-maintenance/OP-20422-esbuild

Conversation

@myabc

@myabc myabc commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

https://community.openproject.org/wp/OP-20422

What are you trying to accomplish?

First of two PRs that turn this repository into an npm package, so that OpenProject core can install the editor instead of carrying a committed build. This one only swaps the bundler: webpack is replaced by esbuild. The output still goes into the core checkout, so the new bundle can be tested against core's suite on its own, before the way it is delivered changes. Stacked on #137.

What approach did you choose and why?

CKEditor 48 ships prebuilt ESM, and the sources import no CSS. Webpack's CSS, PostCSS and style loaders were dead configuration; what it really did was strip types, inline icons as strings, bundle, add the licence banner and minify. esbuild does all of that without loaders, and it is the bundler core uses.

  • bin/build.mjs replaces webpack.config.js. The bundle is an ES module instead of UMD and still assigns window.OPClassicEditor, window.OPConstrainedEditor and window.OPEditorWatchdog.
  • bin/verify-build.mjs pins what a usable build is: licence banner, the three globals, a source map that leads back to the TypeScript sources, a stylesheet, the locales, and size budgets. It was written against the webpack build first, and runs in CI.
  • esbuild follows the source maps of dependencies back to their original sources, which doubled our source map to 14 MB. A small plugin drops those maps, so ours points at the files we bundle, as it did with webpack.
  • bin/clean.sh is removed. It quoted its globs, so it never deleted anything.
  • Eleven dev dependencies go away (261 packages in the lockfile).
webpack esbuild
ckeditor.js 1,405,787 bytes 1,455,370 bytes (+3.5%)
ckeditor.js.map 7.7 MB 8.2 MB
Build time about 3 s about 0.1 s

Verification

CI does not run for this PR, because the workflow only triggers for PRs that target master. Run locally: npm run build, npm run verify:build, npm test (20 suites, 256 passed, 7 skipped, as before), npm run lint, npm run typecheck.

The behavioural test is core's suite, through a paired core PR that carries the build from this branch. That PR is opf/openproject#25889.

AI involvement

Directed: written by Claude Code from a design agreed with @myabc, then reviewed adversarially by Codex.

myabc added 2 commits October 8, 2026 10:54
Pins what a usable build is before the bundler changes: licence
banner, the three window globals, a source map that points at the
TypeScript sources, a stylesheet, the locales and a size budget.

https://community.openproject.org/wp/OP-20422
CKEditor 48 ships prebuilt ESM and the sources import no CSS, so
webpack only stripped types, inlined icons, bundled and minified.
esbuild does all of that without loaders and matches the bundler
core uses. The output location is unchanged, which lets core's suite
test the new bundle through the usual paired pull request.

esbuild follows the source maps of dependencies, which doubled ours
to 14 MB. A plugin drops them, so the map points at the bundled
files as it did with webpack, and the build check gains a budget.

https://community.openproject.org/wp/OP-20422
@myabc
myabc added this pull request to stack #138 October 8, 2026 09:24
@myabc
myabc marked this pull request as ready for review October 8, 2026 10:56
Copilot AI balanced review requested due to automatic review settings October 8, 2026 10:56
@myabc
myabc requested a review from a team October 8, 2026 10:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The declared Node compatibility is invalid and the new build verifier can accept missing globals or an empty stylesheet.

1 open finding
What changed in this PR

Replaces webpack with esbuild while preserving the editor artifacts consumed by OpenProject core.

Changes:

  • Adds esbuild bundling and build verification scripts.
  • Updates CI, npm scripts, documentation, and asset-loader comments.
  • Removes webpack tooling and refreshes dependencies.
File Description
.github/​workflows/​ci.yml Verifies generated artifacts in CI.
README.md Documents esbuild workflows.
bin/​build.mjs Implements esbuild bundling and watch mode.
bin/​clean.sh Removes ineffective cleanup script.
bin/​verify-build.mjs Validates generated artifacts and budgets.
eslint.config.mjs Removes deleted webpack configuration.
package-lock.json Updates the dependency lockfile.
package.json Replaces webpack dependencies and scripts.
src/​plugins/​op-help-link-plugin/​op-help-link-plugin.ts Updates SVG-loader documentation.
src/​plugins/​op-source-code.plugin.ts Updates SVG-loader documentation.
src/​types.d.ts Generalizes bundler documentation.
webpack.config.js Removes webpack configuration.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread package.json
"watch": "node bin/build.mjs --watch",
"lint": "eslint .",
"typecheck": "tsc --noEmit",
"verify:build": "node bin/verify-build.mjs",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants