Skip to content

fix(taro-loader): handle cache miss in entry-cache loader when webpack persistent cache hits#18938

Merged
Single-Dancer merged 1 commit intoNervJS:mainfrom
tianqingse6:patch-1
Apr 13, 2026
Merged

fix(taro-loader): handle cache miss in entry-cache loader when webpack persistent cache hits#18938
Single-Dancer merged 1 commit intoNervJS:mainfrom
tianqingse6:patch-1

Conversation

@tianqingse6
Copy link
Copy Markdown
Contributor

@tianqingse6 tianqingse6 commented Mar 3, 2026

这个 PR 做了什么?

修复开启 webpack 持久化缓存(cache: { enable: true })后,当文件没有改动进行二次编译时,entry-cache.js loader 不返回内容导致编译报错的问题。

这个 PR 是什么类型?

这个 PR 涉及以下平台:

  • 所有小程序
  • Web 端(H5)
  • 移动端(React-Native)
  • 鸿蒙(Harmony)
  • 鸿蒙容器(Harmony Hybrid)
  • ASCF 元服务
  • 快应用(QuickApp)
  • 微信小程序
  • 企业微信小程序
  • 京东小程序
  • 百度小程序
  • 支付宝小程序
  • 支付宝 IOT 小程序
  • 钉钉小程序
  • QQ 小程序
  • 飞书小程序
  • 快手小程序
  • 头条小程序

问题描述

开启 webpack 持久化缓存(cache: { enable: true })后,当文件没有改动进行二次编译时,
报错:ModuleBuildError: Module build failed: Error: Final loader (entry-cache.js) didn't return a Buffer or String

相关 Issue: #15001

根因分析

entry-cache.js 作为 inline loader 被 app/page/component loader 使用。流程如下:

  1. app.js loader 将源码存入内存 entryCache Map
  2. 生成的代码通过 import component from '!entry-cache.js?name=app!src/app.ts' 引入
  3. entry-cache.js loader 从 Map 中读取并返回源码

当 webpack 持久化缓存命中时:

  • app.js loader 被跳过(不执行),不会写入 entryCache
  • entry-cache.js loader 仍被执行,此时 entryCache 为空
  • if (name && entryCache.has(name)) 为 false,callback 永远不会被调用
  • webpack 报错

修复方案

添加 else 分支,在缓存未命中时调用 callback(null, '') 兜底。

影响范围

此 bug 在 3.6.x ~ 4.1.11 版本中均存在。

Summary by CodeRabbit

发布说明

  • Bug 修复
    • 优化了加载器的缓存处理:缓存未命中时现在会保证调用回调返回空内容,避免挂起或不响应,提升稳定性与可靠性。
    • 缓存命中行为保持不变,兼容现有流程。

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6ac8523-393b-4c8b-be72-cdfb19bb6c97

📥 Commits

Reviewing files that changed from the base of the PR and between 452ac05 and ce4fb82.

📒 Files selected for processing (1)
  • packages/taro-loader/src/entry-cache.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/taro-loader/src/entry-cache.ts

Walkthrough

entry-cache.ts 中添加了对缓存未命中情况的分支:当 entryCache 中不存在请求的 name 时,loader 会调用异步回调 callback(null, ''),确保所有路径都会触发回调;缓存命中逻辑保持不变。

Changes

Cohort / File(s) Summary
缓存回调备选分支
packages/taro-loader/src/entry-cache.ts
为 cache-miss 添加显式 else 分支:在未命中时调用 callback(null, '')(异步),原有 cache-hit 路径保持不变(下一 tick 删除缓存并返回 content!.sourcecontent!.map)。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • yoyo837
  • tutuxxx

Poem

🐰 代码小径又分行,
缓存有声与无声,
命中取源去打包,
未命中空串来应,
胡萝卜祝能构建成。 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确描述了主要改动:在webpack持久化缓存命中时处理entry-cache加载器的缓存未命中情况。
Linked Issues check ✅ Passed 代码修改完全满足了#15001中的需求:在缓存未命中时添加else分支确保loader始终调用callback,返回有效的字符串或Buffer。
Out of Scope Changes check ✅ Passed 所有修改都在entry-cache.ts文件中,仅添加else分支处理缓存未命中情况,与PR目标完全相关,无超出范围的改动。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

@coderabbitai coderabbitai Bot requested a review from Single-Dancer March 3, 2026 07:57
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
packages/taro-loader/src/entry-cache.ts (1)

6-14: 修复方案正确,但建议区分 name 缺失和缓存未命中两种情况。

当前的 else 分支涵盖了两种场景:

  1. name 参数为空(可能是配置错误)
  2. entryCache 中不存在对应条目(webpack 持久化缓存命中场景)

建议对 name 缺失的情况单独处理,以便在配置错误时能够更早发现问题:

♻️ 建议的改进方案
   if (name && entryCache.has(name)) {
     const content = entryCache.get(name)
     // just in case, delete cache in next tick
     setImmediate(() => entryCache.delete(name))
     callback(null, content!.source, content!.map)
-  } else {
+  } else if (name) {
     // 当 webpack 持久化缓存命中时,entryCache 为空,需要兜底返回空字符串
     callback(null, '')
+  } else {
+    // name 参数缺失,属于配置错误
+    callback(new Error('entry-cache loader: missing "name" option'))
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/taro-loader/src/entry-cache.ts` around lines 6 - 14, The current
else branch conflates a missing name and a cache miss; update the logic in the
entry-cache handler (referencing name, entryCache, setImmediate, callback) to
first check if name is falsy and immediately call callback with a descriptive
Error (or pass an Error to the loader callback) so configuration mistakes
surface early, otherwise (when name is present but entryCache.has(name) is
false) keep the fallback behavior of callback(null, '') for persistent-cache
misses; retain the setImmediate(() => entryCache.delete(name)) only in the
successful cache-hit path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/taro-loader/src/entry-cache.ts`:
- Around line 6-14: The current else branch conflates a missing name and a cache
miss; update the logic in the entry-cache handler (referencing name, entryCache,
setImmediate, callback) to first check if name is falsy and immediately call
callback with a descriptive Error (or pass an Error to the loader callback) so
configuration mistakes surface early, otherwise (when name is present but
entryCache.has(name) is false) keep the fallback behavior of callback(null, '')
for persistent-cache misses; retain the setImmediate(() =>
entryCache.delete(name)) only in the successful cache-hit path.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af08244 and 2c7b0f7.

📒 Files selected for processing (1)
  • packages/taro-loader/src/entry-cache.ts

@Single-Dancer Single-Dancer added this to the 4.1.12 milestone Mar 5, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.07%. Comparing base (bd4ffb7) to head (ce4fb82).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main   #18938   +/-   ##
=======================================
  Coverage   56.07%   56.07%           
=======================================
  Files         447      447           
  Lines       23454    23454           
  Branches     5810     5781   -29     
=======================================
  Hits        13151    13151           
+ Misses       8442     8439    -3     
- Partials     1861     1864    +3     
Flag Coverage Δ
taro-cli 72.85% <ø> (ø)
taro-runtime 58.33% <ø> (ø)
taro-web 53.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 2 files with indirect coverage changes

🚀 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.

@coderabbitai coderabbitai Bot requested a review from yoyo837 March 6, 2026 03:26
This was referenced Mar 7, 2026
When webpack persistent cache hits, entryCache Map is empty, callback was never called. Added else branch to fallback. Closes NervJS#15001
@Single-Dancer Single-Dancer merged commit 438bcb6 into NervJS:main Apr 13, 2026
25 checks passed
This was referenced Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants