Skip to content

refactor(development): inline loader trace template as string constant#5869

Open
killagu wants to merge 1 commit intoeggjs:nextfrom
killagu:split/03-development-inline-template
Open

refactor(development): inline loader trace template as string constant#5869
killagu wants to merge 1 commit intoeggjs:nextfrom
killagu:split/03-development-inline-template

Conversation

@killagu
Copy link
Copy Markdown
Contributor

@killagu killagu commented Apr 14, 2026

Summary

Inlines the loader trace HTML template into `plugins/development/src/app/middleware/loader_trace_template.ts` as a string constant. Removes the runtime fs read in `egg_loader_trace.ts` middleware.

Why

This is batch 1, part of a 19-PR split of #5863 (the egg-bundler PR). #5863 is kept open as a tracking reference. This PR is independent of the other batch-1 PRs.

Same motivation as the parallel onerror inline change: turbopack and other static bundlers cannot follow `import.meta.dirname + readFileSync` lookups to plugin template files. Inlining the template as a string constant lets the plugin be statically bundled.

Pure refactor — runtime behavior is identical.

Test plan

  • `pnpm --filter=@eggjs/development test` — 12 passed + 5 skipped (1 unrelated pre-existing watcher-timing flake when full suite runs in parallel; passes in isolation)
  • typecheck clean

Stack context

Other batch-1 PRs (independent, can land in any order):

  • `feat(utils): add setBundleModuleLoader runtime hook`
  • `refactor(onerror): inline error page template as string constant`
  • `refactor(watcher): use direct class imports for event sources`

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Optimized loader trace visualization rendering performance.
    • Exposed loader trace template as a public module.

Inline the loader trace visualization HTML as a string constant in
src/app/middleware/loader_trace_template.ts so the plugin can be
statically bundled by turbopack. Previously the template was read
from disk via `import.meta.dirname + fs.readFile`, which breaks when
modules are embedded in a single bundled chunk.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings April 14, 2026 03:59
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

📝 Walkthrough

Walkthrough

The changes introduce a new template module for loader trace visualization, refactor the loader trace middleware to use a statically imported template instead of dynamic file reading, and configure the new module as a public export in the package.json.

Changes

Cohort / File(s) Summary
Package Export Configuration
plugins/development/package.json
Added new export path ./app/middleware/loader_trace_template mapping to source and build output directories.
Loader Trace Template Module
plugins/development/src/app/middleware/loader_trace_template.ts
New module exporting LOADER_TRACE_TEMPLATE constant containing HTML template with AntV G2 chart configuration for rendering loader trace visualization with time-series data.
Middleware Refactoring
plugins/development/src/app/middleware/egg_loader_trace.ts
Refactored to use statically imported LOADER_TRACE_TEMPLATE instead of dynamically reading loader_trace.html from disk, eliminating async file I/O overhead.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested Reviewers

  • jerryliang64

Poem

🐰 A template once scattered on disk,
Now bundled with modules so brisk!
No async await, no file I/O fret,
Static imports—the optimization we get! 📦✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: inlining the loader trace HTML template from a file into a string constant in the code.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the egg_loader_trace middleware by inlining the HTML visualization template into a new TypeScript module, which eliminates the need for runtime file system reads. The review identified a potential XSS vulnerability where data is injected into the script block, suggesting character escaping as a fix. Additionally, it is recommended to remove the new internal template module from the package exports to keep the public API clean and to update the template's JavaScript to use const instead of var for better practice.

const template = await fs.readFile(templatePath, 'utf8');
const data = await loadTimingData(app);
ctx.body = template.replace('{{placeholder}}', JSON.stringify(data));
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data));
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.

security-high high

Directly injecting JSON.stringify(data) into a <script> block is vulnerable to Cross-Site Scripting (XSS) if any string within data contains the sequence </script>. This would cause the browser to terminate the script block prematurely and potentially execute malicious code. It is recommended to escape the < character to prevent this injection.

Suggested change
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data));
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data).replace(/</g, '\\u003c'));

"./agent": "./src/agent.ts",
"./app": "./src/app.ts",
"./app/middleware/egg_loader_trace": "./src/app/middleware/egg_loader_trace.ts",
"./app/middleware/loader_trace_template": "./src/app/middleware/loader_trace_template.ts",
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.

medium

The loader_trace_template module appears to be an internal implementation detail used only by egg_loader_trace.ts. Exporting it in package.json unnecessarily increases the public API surface of the package. Since it is imported relatively within the package, this export entry should be removed.

"./agent": "./dist/agent.js",
"./app": "./dist/app.js",
"./app/middleware/egg_loader_trace": "./dist/app/middleware/egg_loader_trace.js",
"./app/middleware/loader_trace_template": "./dist/app/middleware/loader_trace_template.js",
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.

medium

As mentioned for the exports field, this internal template module does not need to be exposed in publishConfig.exports.

<div id="mountNode"></div>
<script src="https://gw.alipayobjects.com/os/antv/assets/g2/3.0.9/g2.min.js"></script>
<script>
var data = {{placeholder}};
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.

medium

Use const instead of var for variable declarations to adhere to modern JavaScript best practices and improve maintainability.

Suggested change
var data = {{placeholder}};
const data = {{placeholder}};

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.01%. Comparing base (490f849) to head (f5d9b74).

Additional details and impacted files
@@           Coverage Diff           @@
##             next    #5869   +/-   ##
=======================================
  Coverage   86.00%   86.01%           
=======================================
  Files         667      668    +1     
  Lines       18945    18944    -1     
  Branches     3652     3652           
=======================================
  Hits        16294    16294           
+ Misses       2297     2296    -1     
  Partials      354      354           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/development/src/app/middleware/loader_trace_template.ts (1)

1-2: Align file and exported variable naming with repo conventions.

Please rename the file to hyphen-case and the exported constant to camelCase to match project standards (and then update import/export paths accordingly).

♻️ Suggested rename pattern
-/** Loader trace visualization template - inlined from loader_trace.html */
-export const LOADER_TRACE_TEMPLATE = `<!doctype html>
+/** Loader trace visualization template - inlined from loader_trace.html */
+export const loaderTraceTemplate = `<!doctype html>

And update references, e.g.:

-import { LOADER_TRACE_TEMPLATE } from './loader_trace_template.ts';
+import { loaderTraceTemplate } from './loader-trace-template.ts';

As per coding guidelines, "{packages,plugins}/**/*.{ts,tsx,js,mjs}: Name files in lowercase with hyphens" and "**/*.{ts,tsx}: Name functions and variables in camelCase".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/development/src/app/middleware/loader_trace_template.ts` around lines
1 - 2, The file name and exported constant violate naming conventions: rename
the file from loader_trace_template.ts to loader-trace-template.ts (hyphen-case)
and rename the exported constant LOADER_TRACE_TEMPLATE to loaderTraceTemplate
(camelCase); update all import/export sites that reference
loader_trace_template.ts and LOADER_TRACE_TEMPLATE to use the new file name and
new symbol (loader-trace-template and loaderTraceTemplate) so builds and imports
resolve correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/development/src/app/middleware/egg_loader_trace.ts`:
- Line 16: The current insertion uses raw JSON.stringify(data) into
LOADER_TRACE_TEMPLATE which can allow string fields like </script> to break out;
update the assignment that sets ctx.body (the call using
LOADER_TRACE_TEMPLATE.replace(...)) to first harden the serialization by
escaping it via the framework helper (e.g. use
ctx.helper.escape(JSON.stringify(data))) or equivalent escaping that neutralizes
</script> and other HTML-sensitive characters, then call replace with that
escaped string so the inline script cannot be broken out.

---

Nitpick comments:
In `@plugins/development/src/app/middleware/loader_trace_template.ts`:
- Around line 1-2: The file name and exported constant violate naming
conventions: rename the file from loader_trace_template.ts to
loader-trace-template.ts (hyphen-case) and rename the exported constant
LOADER_TRACE_TEMPLATE to loaderTraceTemplate (camelCase); update all
import/export sites that reference loader_trace_template.ts and
LOADER_TRACE_TEMPLATE to use the new file name and new symbol
(loader-trace-template and loaderTraceTemplate) so builds and imports resolve
correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 79bfc717-0fa3-4976-b5f8-264fd4b68b87

📥 Commits

Reviewing files that changed from the base of the PR and between 490f849 and f5d9b74.

📒 Files selected for processing (3)
  • plugins/development/package.json
  • plugins/development/src/app/middleware/egg_loader_trace.ts
  • plugins/development/src/app/middleware/loader_trace_template.ts

const template = await fs.readFile(templatePath, 'utf8');
const data = await loadTimingData(app);
ctx.body = template.replace('{{placeholder}}', JSON.stringify(data));
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data));
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.

⚠️ Potential issue | 🟠 Major

Escape serialized data before injecting it into inline <script>.

Raw JSON.stringify(data) can include </script> in string fields and break out of the script tag during HTML parsing. Please harden the serialization before replace(...).

🔒 Suggested hardening
-    ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data));
+    const serializedData = JSON.stringify(data)
+      .replace(/</g, '\\u003C')
+      .replace(/>/g, '\\u003E')
+      .replace(/&/g, '\\u0026')
+      .replace(/\u2028/g, '\\u2028')
+      .replace(/\u2029/g, '\\u2029');
+    ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', serializedData);

As per coding guidelines, "Use 'ctx.helper.escape()' and framework security helpers to prevent XSS attacks in template rendering and output".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', JSON.stringify(data));
const serializedData = JSON.stringify(data)
.replace(/</g, '\\u003C')
.replace(/>/g, '\\u003E')
.replace(/&/g, '\\u0026')
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
ctx.body = LOADER_TRACE_TEMPLATE.replace('{{placeholder}}', serializedData);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/development/src/app/middleware/egg_loader_trace.ts` at line 16, The
current insertion uses raw JSON.stringify(data) into LOADER_TRACE_TEMPLATE which
can allow string fields like </script> to break out; update the assignment that
sets ctx.body (the call using LOADER_TRACE_TEMPLATE.replace(...)) to first
harden the serialization by escaping it via the framework helper (e.g. use
ctx.helper.escape(JSON.stringify(data))) or equivalent escaping that neutralizes
</script> and other HTML-sensitive characters, then call replace with that
escaped string so the inline script cannot be broken out.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors @eggjs/development’s loader-trace middleware to inline the HTML template as a TypeScript string constant, removing the runtime filesystem read so the plugin can be statically bundled (e.g., by turbopack).

Changes:

  • Added LOADER_TRACE_TEMPLATE constant containing the inlined loader-trace HTML.
  • Updated egg_loader_trace middleware to use the inlined template instead of reading loader_trace.html at runtime.
  • Exposed the new template module via package.json subpath exports.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
plugins/development/src/app/middleware/loader_trace_template.ts Introduces the inlined HTML template as an exported string constant.
plugins/development/src/app/middleware/egg_loader_trace.ts Switches middleware rendering from fs.readFile() to the inlined template constant.
plugins/development/package.json Adds a new exported subpath for the template module (src + dist).

@@ -0,0 +1,51 @@
/** Loader trace visualization template - inlined from loader_trace.html */
Comment on lines 31 to 33
"./app/middleware/egg_loader_trace": "./src/app/middleware/egg_loader_trace.ts",
"./app/middleware/loader_trace_template": "./src/app/middleware/loader_trace_template.ts",
"./config/config.default": "./src/config/config.default.ts",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants