Skip to content

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

Open
tianqingse6 wants to merge 1 commit intoNervJS:mainfrom
tianqingse6:patch-1
Open

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

Conversation

@tianqingse6
Copy link
Copy Markdown

@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: 02093b36-f949-4b4d-b3b4-a2a2f4cf7a90

📥 Commits

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

📒 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 会以空字符串调用异步回调,确保回调在所有路径上都会被触发。(不改变导出签名)

Changes

Cohort / File(s) Summary
缓存回调备选分支
packages/taro-loader/src/entry-cache.ts
新增 else 分支处理 cache-miss:当 entryCache 不包含请求的 name 时,调用异步回调并传入空字符串,原有 cache-hit 路径保持不变(继续在下一 tick 删除缓存并返回内容)。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • yoyo837

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 PR标题'fix(taro-loader): handle cache miss in entry-cache loader when webpack persistent cache hits'清晰准确地反映了核心改动:处理webpack持久化缓存命中时entry-cache加载器的缓存未命中场景。
Linked Issues check ✅ Passed 代码改动完全满足关联issue #15001的要求:在缓存未命中时调用callback(null, '')确保加载器总是返回有效结果,解决'didn't return a Buffer or String'错误。
Out of Scope Changes check ✅ Passed 所有改动都限制在entry-cache.ts文件内,仅添加else分支处理缓存未命中,完全在关联issue的修复范围内,无超出范围的改动。
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
  • Post copyable unit tests in a comment

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.31%. Comparing base (a305e4c) to head (3a8eb36).
⚠️ Report is 2 commits behind head on main.

❌ Your project check has failed because the head coverage (56.31%) is below the target coverage (75.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main   #18938   +/-   ##
=======================================
  Coverage   56.31%   56.31%           
=======================================
  Files         447      447           
  Lines       23352    23352           
  Branches     5786     5776   -10     
=======================================
  Hits        13150    13150           
+ Misses       8371     8368    -3     
- Partials     1831     1834    +3     
Flag Coverage Δ
taro-cli 72.85% <ø> (ø)
taro-runtime 60.27% <ø> (ø)
taro-web 53.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 6 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.

When webpack persistent cache hits, entryCache Map is empty, callback was never called. Added else branch to fallback. Closes NervJS#15001
@coderabbitai coderabbitai bot requested a review from yoyo837 March 6, 2026 03:26
This was referenced Mar 7, 2026
This was referenced Mar 7, 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