[DONE] Webpack Module Code Splitting — DynamicScriptHandler + executeRaw + connectedToDocument-Patch. 20 neue Tests ✅, 0 Regression ✅ #36
Labels
No labels
bug
docs
feature
housekeeping
html-spec
performance
react-compat
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
glow-all/true-headless-browser#36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problembeschreibung
Unser ScriptLoader (src/js/script-loader.ts) handhabt aktuell alle statischen
<script>-Tags, die vomIncrementalParser.preloadScripts()per Regex-Präscan erfasst werden: inline, classic-blocking, defer, async, module.Webpack-Code-Splitting (und jede andere Form dynamischer Skriptlade-Mechanismen) erzeugt jedoch
<script>-Elemente zur Runtime über JS — nicht statisch im HTML:Diese dynamisch erzeugten Skripte werden vom Präscan NICHT erfasst → sie werden nie von unserem
ScriptLoader.execute()mit dem var-decl-Wrapper ausgeführt → der Chunk-Code läuft entweder im falschen Kontext (Happy DOM) oder gar nicht.Konsequenz: Jede Webpack-App mit
import()-Code-Splitting bricht beim Laden der asynchronen Chunks.Architektur-Analyse
Aktuelle Architektur
Happy DOMs Built-In Script Evaluation
Happy DOMs
HTMLScriptElement.connectedToDocument()(Zeile 348-384) evaluiert bei jedemappendChild/insertBefore:#evaluateScript()→JavaScriptCompiler.compile()→compiled.execute()im Happy-DOM-Window#loadScript(url)→ResourceFetch.fetch()→JavaScriptCompiler→ eval im Happy-DOM-Window#loadModule()/#evaluateModule()— gleiches ProblemDies verursacht:
window,document,fetchzeigen auf Happy DOM, nicht auf unsere isolierten Proxies#loadScriptwird zwar aufgerufen, aber der Chunk-Code sieht nicht unsere IsolationsschichtLösungsansätze
Option A (empfohlen): HTMLScriptElement-Prototyp-Patching + ScriptLoader-Erweiterung
Kernidee: Happy DOMs native Skript-Evaluation deaktivieren → alle Skripte (statische + dynamische) durch unseren ScriptLoader jagen → var-decl IIFE garantiert Isolation.
Teil 1: HTMLScriptElement evaluiert NICHTS mehr selbst
Patch
HTMLScriptElement.prototype[PropertySymbol.connectedToDocument]:disableEvaluation = truesetzen (existierende Property)connectedToDocumentüberschreiben: nur nochsuper.connectedToDocument()→ KEIN#evaluateScript(),#loadScript()etc.Teil 2: Dynamic Script Hook
Neue Datei:
src/js/dynamic-scripts.tsTeil 3: ScriptLoader erweitern
Option B: Nur MutationObserver
Einfacher, aber MutationObserver ist asynchron → Webpack feuert
onloadbevor Observer feuert → Race Condition.Option C: Proxy auf document.createElement('script')
document.createElementdurch Proxy ersetzen → erfasstcreateElement('script')und interceptedsrc-Setter +appendChild.Webpack kann aber auch über
ownerDocument.createElementodercreateElementNSgehen.Entscheidung: Option A (empfohlen)
Kombination aus:
script.src = url-InterceptionAkzeptanzkriterien
document.createElement('script')+src+appendChild→ Inhalt wird gefetcht und ausgeführtdocument.currentScriptzeigt während der Ausführung auf das Script-Elementload-Event wird nach erfolgreicher Ausführung auf dem Script-Element gefeuerterror-Event bei fehlgeschlagenem Fetch__webpack_require__.e()+script.onload-Promise resolved korrektself['webpackChunk_...']global funktioniert mit dynamischen Chunksimport()dynamischem Import)Betroffene Dateien
src/js/script-loader.tsexecuteRaw(code, url?)+fetchContent(url)public +buildVarDecls()src/js/dynamic-scripts.tssrc/runtime-isolation.tssrc/pages/page.tstests/unit/dynamic-scripts.test.tstests/integration/webpack-code-split.test.tstests/fixtures/webpack-split/Dependencies
Querverweise
evaluate.ts— var-injection für page.evaluate()parser.ts— Präscan-Logik für statische SkripteTechnische Risiken
PropertySymbol.connectedToDocumentist intern. Upgrade könnte Struktur ändern. Lösung: Feature-Detection.self/windowautomatisch zu unserem isolierten Window.Performance-Impact
Testplan
Unit-Tests (25+)
Integration-Tests (5+)
E2E-Test (1)
Echter Webpack-Build + Static-Server + Page.goto() → alle Chunks laden
Webpack Module Code Splitting (dynamic import()) — Dynamische <script>-Interception + Ausführung im isolierten Kontextto [DONE] Webpack Module Code Splitting — DynamicScriptHandler + executeRaw + connectedToDocument-Patch. 20 neue Tests ✅, 0 Regression ✅