🐛 fix(build): make package tree-shakeable and Node-safe via unbundle - #167
Merged
Conversation
The browser build emitted a single mega-bundle (es/index.js) whose top-level contained unconditional side-effect calls (init_helper(), init_hotkey(), init_plugin(), init_debug()). Because pure utility exports (isPureUrl, getHotkeyById, createDebugLogger, scrollIntoView, KeyEnum, ...) lived in the same module as those calls, any import from '@lobehub/editor' forced the whole bundle to evaluate, dragging in the entire editor and DOM globals. In a Node/SSR environment this referenced `document` at import time and crashed — a pure function import pulled 7-20MB of code. Enable `unbundle: true` for the browser build group so output mirrors the source module structure. Each export becomes its own file and the barrel is a plain re-export, restoring per-module tree-shaking. Importing a pure function now resolves to a ~1KB standalone module with no top-level DOM. Also declare remark, remark-gfm and remark-math as runtime dependencies (remark moved from devDependencies). They are imported by the markdown plugin but were previously undeclared, so unbundle mode emitted their transitive graph (micromark/mdast-util/vfile/...) as ~864KB of files under es/node_modules. Declaring them keeps them external. Verified (consumer tree-shake + Node import): - isPureUrl 20MB→1KB, getHotkeyById 7MB→10KB, all run in Node - es/node_modules 864KB→28KB (type-only stubs), es/ 3.9MB→2.6MB - headless + markdown round-trip still works in Node
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
github-actions Bot
pushed a commit
that referenced
this pull request
May 29, 2026
### [Version 4.15.2](v4.15.1...v4.15.2) <sup>Released on **2026-05-29**</sup> #### 🐛 Bug Fixes - **build**: Make package tree-shakeable and Node-safe via unbundle. <br/> <details> <summary><kbd>Improvements and Fixes</kbd></summary> #### What's fixed * **build**: Make package tree-shakeable and Node-safe via unbundle, closes [#167](#167) ([5f61f5b](5f61f5b)) </details> <div align="right"> [](#readme-top) </div>
Member
|
🎉 This PR is included in version 4.15.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Importing a pure function from
@lobehub/editor(e.g.isPureUrl,getHotkeyById,createDebugLogger,scrollIntoView,KeyEnum) dragged the entire editor + DOM globals into the bundle and crashed in Node/SSR with a top-leveldocumentreference.Root cause
The browser build emitted a single mega-bundle
es/index.jswhose top-level held unconditional side-effect calls:These come from rolldown's lazy-init wrappers for cross-chunk modules. Because the pure exports lived in the same module as those calls, using any export forced
es/index.jsto be included, and the top-levelinit_*()calls cannot be tree-shaken — so the whole editor (anddocumentaccess) loaded eagerly.Measured from the published artifact (consumer tree-shake):
isPureUrl→ 20MB,getHotkeyById→ 7MB, both referencingdocument. The source itself was perfectly tree-shakeable; the build artifact was not.Fix
unbundle: truefor the browser build group so output mirrors the source module structure. Each export becomes its own file andindex.jsis a plain re-export barrel — restoring per-module tree-shaking exactly like the source.remark,remark-gfm,remark-mathas runtimedependencies(remarkmoved from devDependencies). They are imported by the markdown plugin but were undeclared, so unbundle mode emitted their transitive graph (micromark / mdast-util / vfile / …) as ~864KB underes/node_modules. Declaring them keeps them external.Verification (consumer tree-shake + Node import)
isPureUrldocument· Node crashgetHotkeyByIdcreateDebugLoggeres/node_moduleses/totales/index.js: 250KB mega-bundle → 12.5KB re-export barrelheadless+ markdown round-trip still works in Nodetype-check✅ ·lint:circular✅ (no cycles)Notes / follow-ups
es/node_modules(28KB) is purely@types/mdast+@types/unist(.d.tsonly, self-contained). Could be removed by declaring those@types/*as dependencies if desired.