build(sdkjs): fix webpack migration bundle bloat, CI, and coverage gaps - #65
build(sdkjs): fix webpack migration bundle bloat, CI, and coverage gaps#65MonaAghili wants to merge 6 commits into
Conversation
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
273b47f to
f787b36
Compare
TL;DRApprove with reservations. Build-tooling-only PR (no editor/application code touched); the four bugs it claims to fix are real fixes. One concrete defect ships in every output file and should be fixed before merge: the Full review1. Every shipped file's license banner literally contains the text
|
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
d9103a0 to
de2b1dd
Compare
Signed-off-by: Mona LatifAghili <mona.laghili@gmail.com>
d30684d to
c3abc4d
Compare
|
@moodyjmz please review again. |
TL;DRApprove. All five findings from my 23 July review are properly fixed — I verified each against the diff rather than taking the re-review request on trust, and CI is green on the exact head SHA ( My remaining reservations are not about this PR's code. They're merge sequencing: a certain file collision with #68, and the interaction with the 584-commit upstream sync sitting in #21. Details below. Verification of the five earlier findings#1 sentinel leaking into every shipped file — fixed, and fixed correctly.
#2 bare-global fragility — addressed as suggested. The WARNING block above #3 CI not running on this PR — fixed and proven. #4 #5 Babel cache key — fixed. New since my last pass, checked: Looked like a bug, isn't — recording so nobody "fixes" it later. The sentinel strip at stage 5000 runs after Merge sequencing — two collisions1. Worth knowing: the 2. The bigger sequencing questionThis PR deletes I'd merge #21 first, then this. Not a criticism of the work — a consequence of the order. Related: #66 ( Caveats on this reviewI did not run an independent second pass on this one. The conclusion I'd most want a cold reader on is my earlier finding #2 — the webpack single-module inlining behaviour that the bare-global model depends on. That rests on empirical build observation rather than plain source reading, and the WARNING comment added here is only as good as that premise. Disclosure: #67 and #68 are mine, so read the sequencing notes with that in mind. Nice work on the fixes — the sentinel one especially, since the obvious shortcut (strip before injection) would have quietly re-broken bug #1. |
Request: port web-apps' verify stageNot a blocker, and not a criticism of the approach — the opposite. Now that I understand this is deliberately modelled on web-apps rather than a fresh toolchain choice, the pattern-match holds up well: per-product configs plus a shared factory ( But the copy stops one phase short. web-apps has a verification tier this PR doesn't:
The specific ask: an sdkjs Worth noting Cheap version if a full port is too much scope for this PR: a single script that parses Separately, and flagging it now rather than springing it later: there's a second gap I'd like to discuss, which is that nothing in this PR's CI exercises DoctRenderer or x2t at all — every check is browser QUnit via |
IE support is being dropped — two consequences for this PR@MonaAghili — decision from our side: we can drop IE support entirely. That resolves a question left open in the earlier review and has two consequences here, one immediate and one worth a discussion. 1. The Babel ES5 pass can go — independent of anything else
With no IE target, that transpile has no consumer. Removing it:
This is a subtraction, needs no toolchain change, and I would take it on its own merits. 2. With ES5 off the table, esbuild becomes viableThree of the more intricate parts of this PR exist to make webpack behave like a concatenator: esbuild 0.25.12 does all three natively: True top level, no wrapper, identifiers untouched, banner prepended — no sentinel required. The three minify flags are separate ( ES5 was the blocker and it is now gone: Caveats, so this is a fair comparison rather than a pitch:
The parallelism win and the per-product-config + shared-factory pattern stand either way — those are the strongest parts of this PR and I am not questioning them. The question is narrower: whether the concatenation half is worth ~5,500 lines of webpack machinery now that the ES5 constraint is gone. Your call on whether that is worth exploring in this PR, a follow-up, or not at all. If the webpack route is still better on grounds I have not considered, I would rather hear that than have you re-open a settled decision. 3. Follow-up, needs careThe |
Copyright headers on the new build filesSeparate, small point — and to be clear up front, this is inherited from web-apps rather than anything introduced here. I've raised the equivalent issue against web-apps so it gets fixed in both places. Every Euro-Office-authored file added by this PR carries:
There's a CI catch that has to be fixed first. license_header = b'Copyright Ascensio System'
Suggested order:
/**
* SPDX-FileCopyrightText: 2026 Euro-Office contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/I couldn't find an established SPDX example in the Euro-Office tree to copy exactly, so treat that string as a proposal rather than the house form — worth confirming before applying it across files. Note there's already a dual-attribution string in this PR at That's the right shape for generated bundles, which genuinely contain both parties' work. For new source files that contain only Euro-Office work, a plain Euro-Office header is the accurate one. Happy for this to be a follow-up rather than growing this PR — but the |
Summary
Fixes four bugs/gaps found in review of the Grunt→webpack migration (
feature/migration-to-webpack-sdkjs), scoped strictly to build tooling / CI — no application code is touched in this PR.Fixes
1. Terser was duplicating every file's license header into the bundle
build/webpack.sdk.factory.mjsconfigured Terser to preserve comments matching/AGPL|Copyright|Ascensio|License/i, intending to keep just the single license banner injected byBannerPlugin. But every one of the ~400+ concatenated source files carries an identical AGPL/Copyright header, so the regex preserved all of them instead of just the one banner.Verified before/after on the word bundle: 307 → 1 occurrences of the copyright text in
sdk-all.js, banner still present and intact.Fix: added a unique sentinel (
@@license-banner@@) tobuild/license.headerand match only that in Terser'sformat.comments.Note:
BannerPlugininjects the banner before Terser runs (webpack stageADDITIONS(-100) vs Terser'sOPTIMIZE_SIZE(400)), so a naivecomments: falsestrips the banner too — confirmed by building and grepping the output. The sentinel is required, not optional.2. Desktop/mobile silently lost their lighter minification tier
Old
build-desktop.bat/build-mobile.commandran Closure'sWHITESPACE_ONLY; the new pipeline funneled all platforms through the same Tersercompresspass, meaning desktop/mobile now get more aggressive minification than before with no explicit decision behind it.Fix:
compressis nowfalseforSDK_PLATFORM=desktop|mobile, restoring the old lighter tier. Verified by building withSDK_PLATFORM=desktop: output is larger than the web build (2.44 MiB vs 2.29 MiB min chunk), confirming the lighter pass is active.3.
check-build.ymlPR trigger filter was droppedpull_request.branches(fork,develop,release/**,hotfix/**) was removed during the CI-runner rewrite, so the workflow now runs on PRs targeting any branch. Restored.4. Only
wordhad a compiled-bundle regression testThe only CI check that runs QUnit against the actual webpack-built output (
tests/common/api/api.html, underCOMPILED=1) coveredwordonly.cell/slide/visiohad no equivalent — a bundle-specific regression (bad concat order, a stripped directive, etc.) in any of those three could pass CI undetected.Verified the four editors' bootstrap ("min") chunks are genuinely distinct file sets (word: 42 files incl.
pdf/api.js; cell: 38 files incl.cell/api.js,cell/model/CollaborativeEditing.js; etc.) — so this isn't redundant coverage.Fix: added
tests/common/api/api-cell.html,api-slide.html,api-visio.html, reusing the existingapi.jstest (it only exercises editor-agnosticAscCommon.*APIs, notAscWord/AscCommonExcel, so it's safe against the documentedCOMPILED=1limitation), wired into the same CI step.Also documented (no functional change)
output.publicPathis intentionally unset today (no code-splitting/import()in this config); added a comment so the next person addingsplitChunksknows to set it then.Test plan
npm test --prefix build— 32/32 build-tooling unit tests passnpm run build --prefix build— all four editors (word/cell/slide/visio) build successfullySDK_PLATFORM=desktop npm run build --prefix build— builds successfully, confirms lighter minify branch is exercisedCOMPILED=1 npm run develop --prefix build— regenerates all fourscripts.js, each correctly bootstrap-onlycheck-build.ymlYAML validatednode_modulesin this environment)Out of scope
Four other findings from the same review are not included here since they're unrelated application-code changes riding along in the migration branch (a spreadsheet checkbox feature, its
CControlcontroller-initialization guards, dead code inTableId.js, and a branding string change) — these belong in a separate PR reviewed on their own merits.