-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Webpack: Improve performance of module-mocking plugins #33169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Conversation
|
View your CI Pipeline Execution ↗ for commit 180015d
☁️ Nx Cloud last updated this comment at |
📝 WalkthroughWalkthroughRuntime injector now lazy-caches the mocker runtime, avoids emitting/prepending the runtime asset when already present, and forwards HtmlWebpackPlugin errors to the callback. Mock plugin adds mtime-based invalidation, tracks candidate specifiers to skip unnecessary extraction, and short-circuits when no mocks. Preview config watch ignores node_modules and the resolved output directory. The custom webpack preset disables the module-mocking workflow by commenting out the mock loader and both mock plugins. Changes
Sequence Diagram(s)mermaid mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (1)
12-13: Minor typo in comment."includiweng" should be "including".
- * This ensures the `sb` object is available globally before any other scripts, includiweng the + * This ensures the `sb` object is available globally before any other scripts, including the
🧹 Nitpick comments (2)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (1)
62-72: Consider guardingemitAssetto avoid duplicate asset warnings.The
includescheck on line 70 prevents duplicate entries indata.assets.js, butemitAssetis called unconditionally on every hook invocation. In watch mode or with multiple HTML files, this could attempt to emit an asset that already exists, potentially causing warnings or errors.Consider checking if the asset exists before emitting:
- compilation.emitAsset( - runtimeAssetName, - new compiler.webpack.sources.RawSource(runtimeScriptContent) - ); + if (!compilation.getAsset(runtimeAssetName)) { + compilation.emitAsset( + runtimeAssetName, + new compiler.webpack.sources.RawSource(runtimeScriptContent) + ); + }code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (1)
136-144: Consider adding type safety and debug logging for filesystem access.The
as anycast loses type safety. While the defensive optional chaining is appropriate (not all webpack file systems implementstatSync), a debug log on failure would aid troubleshooting.private getPreviewConfigMtime(compiler: Compiler): number | undefined { + const logger = compiler.getInfrastructureLogger(PLUGIN_NAME); try { - const fs = compiler.inputFileSystem as any; + const fs = compiler.inputFileSystem as { statSync?: (path: string) => { mtime?: Date } }; const stat = fs.statSync?.(this.options.previewConfigPath); return stat?.mtime?.getTime?.(); - } catch { + } catch (e) { + logger.debug(`Could not stat preview config: ${e}`); return undefined; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts(3 hunks)code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use camelCase for variable and function names
Files:
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.tscode/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Enable TypeScript strict mode
Export functions from modules for testing purposes
Files:
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.tscode/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
**/*.{ts,tsx,js,jsx,json,html,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx,json,html,mjs}: Use ESLint and Prettier for code style enforcement
Run 'yarn prettier --write ' to format code after making changes
Run 'yarn lint:js:cmd ' to check for ESLint issues after making changes
Files:
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.tscode/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
code/**/!(*.test).{ts,tsx,js,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/!(*.test).{ts,tsx,js,mjs}: Use 'logger' from 'storybook/internal/node-logger' for server-side (Node.js) logging, not console.log/console.warn/console.error
Use 'logger' from 'storybook/internal/client-logger' for client-side (browser) logging, not console.log/console.warn/console.error
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.tscode/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
🧠 Learnings (15)
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:47.649Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.649Z
Learning: Applies to **/*.test.{ts,tsx} : Use 'vi.mock()' to mock external dependencies like file system and loggers in unit tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `vi.mock()` with the `spy: true` option for all package and file mocks in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without `vi.mocked()` in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with `vi.mocked()` in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the `spy: true` option in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of `beforeEach` blocks in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Implement mock behaviors in `beforeEach` blocks in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Place all mocks at the top of the test file before any test cases
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Each mock implementation should return a Promise for async functions in Vitest
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
🧬 Code graph analysis (2)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (1)
code/core/src/mocking-utils/runtime.ts (1)
getMockerRuntime(13-28)
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (1)
test-storybooks/portable-stories-kitchen-sink/react-vitest-3/pre-e2e.js (1)
fs(3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: normal
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (7)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (3)
16-16: LGTM on the caching approach.Caching the runtime script avoids repeated
esbuild.buildSynccalls on each compilation, which is a good performance optimization given thatgetMockerRuntime()bundles synchronously.
56-57: Good use of lazy initialization pattern.The nullish coalescing assignment (
??=semantics via?? (this.cachedRuntime = ...)) ensures the runtime is only generated once per plugin instance.
74-76: Good fix for error propagation.Previously, exceptions would leave the async callback hanging. Now the error is properly forwarded to webpack's compilation pipeline via
cb(error as Error).code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (4)
52-53: LGTM on the new state fields.The
candidateSpecifiersset enables O(1) lookup for filtering irrelevant module requests, andlastPreviewMtimeenables the mtime-based cache invalidation. Both are well-typed.
72-79: Effective mtime-based invalidation logic.The early return when
mTimePreviewConfig <= lastPreviewMtimecorrectly avoids redundant re-extraction. The fallback behavior whenmTimePreviewConfigisundefined(re-extract) is also correct for robustness.
80-89: LGTM on the mock map construction.Using
flatMapto register both the full path and extension-stripped path enables matching regardless of how the importer specifies the extension. UpdatingcandidateSpecifiersand logging the count improves observability.
98-107: Remove the early guard check or add path normalization to handle aliased/mapped imports.The guard at line 105 returns early if
resource.requestis not incandidateSpecifiers, which stores the originalsb.mock()paths. However, this check is too strict and blocks valid mocks when:
- Imports use path aliases or tsconfig mappings that differ from how
sb.mock()was called- Webpack normalizes paths differently (e.g.,
./file.tsvs./file)The fallback resolution logic (lines 109–115) could handle these cases via
resolveWithExtensions()andmockMaplookup by absolute path, but it's never reached due to the early return.Options:
- Remove the early guard to let all imports attempt resolution
- Store normalized/resolved paths in
candidateSpecifiersalongside original paths- Normalize both
resource.requestand candidate paths before comparison
| logger.info(`Mock map updated with ${this.mockMap.size / 2} mocks.`); | ||
| this.candidateSpecifiers = new Set(resolved.map((m) => m.path)); | ||
| this.lastPreviewMtime = mTimePreviewConfig; | ||
| logger.info(`Mock map updated with ${resolved.length} mocks.`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
little reminder, now that you're touching this file, to either:
- not show the log when the count is 0
- only show the log if the current count is 0 and previous count wasn't 0 (so you don't keep showing "updated 0 mocks" every time)
0ede16e to
ce88eed
Compare
There was a problem hiding this 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
♻️ Duplicate comments (1)
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (1)
71-88: Verify mtime behavior during initial compilation.The mtime-based invalidation logic looks sound. However, consider this edge case: during the initial compilation (
beforeRun),this.lastPreviewMtimeisundefined, so the check on line 73 will be false and extraction will proceed correctly.On subsequent watch compilations, if the preview config hasn't changed, the early return on line 77 will skip re-extraction as intended.
Regarding line 88: As noted in the past review comment, consider either:
- Not showing the log when
resolved.lengthis 0- Only showing when transitioning from non-zero to zero
To verify the mtime comparison works correctly across different file systems and scenarios, run:
#!/bin/bash # Verify that inputFileSystem.statSync is available in webpack rg -n "inputFileSystem" --type=ts -C3 -g '!node_modules'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts(3 hunks)code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use camelCase for variable and function names
Files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Enable TypeScript strict mode
Export functions from modules for testing purposes
Files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
**/*.{ts,tsx,js,jsx,json,html,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx,json,html,mjs}: Use ESLint and Prettier for code style enforcement
Run 'yarn prettier --write ' to format code after making changes
Run 'yarn lint:js:cmd ' to check for ESLint issues after making changes
Files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
code/**/!(*.test).{ts,tsx,js,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/!(*.test).{ts,tsx,js,mjs}: Use 'logger' from 'storybook/internal/node-logger' for server-side (Node.js) logging, not console.log/console.warn/console.error
Use 'logger' from 'storybook/internal/client-logger' for client-side (browser) logging, not console.log/console.warn/console.error
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
🧠 Learnings (15)
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:47.649Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.649Z
Learning: Applies to **/*.test.{ts,tsx} : Use 'vi.mock()' to mock external dependencies like file system and loggers in unit tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `vi.mock()` with the `spy: true` option for all package and file mocks in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the `spy: true` option in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock implementations should match the expected return type of the original function
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mock implementations outside of `beforeEach` blocks in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without `vi.mocked()` in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:47.649Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.649Z
Learning: Applies to code/**/!(*.test).{ts,tsx,js,mjs} : Use 'logger' from 'storybook/internal/node-logger' for server-side (Node.js) logging, not console.log/console.warn/console.error
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:47.649Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.649Z
Learning: Applies to code/**/!(*.test).{ts,tsx,js,mjs} : Use 'logger' from 'storybook/internal/client-logger' for client-side (browser) logging, not console.log/console.warn/console.error
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required properties and methods that the test subject uses in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:47.649Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.649Z
Learning: Applies to **/*.{ts,tsx} : Export functions from modules for testing purposes
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
📚 Learning: 2025-11-24T17:49:59.268Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.268Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with `vi.mocked()` in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
🧬 Code graph analysis (1)
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (1)
code/core/src/mocking-utils/resolve.ts (2)
isExternal(112-118)getIsExternal(58-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: normal
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (4)
code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts (4)
11-11: LGTM! Correct logger import.The import follows coding guidelines by using the node-logger for server-side logging in this webpack plugin.
53-54: LGTM! Well-designed optimization state.These private fields support mtime-based invalidation and early filtering, improving performance by avoiding unnecessary mock re-extraction and module resolution.
107-109: LGTM! Smart early-exit optimization.The logic correctly filters external modules that aren't being mocked, while still allowing relative/local paths to proceed to full resolution. This is necessary because external specifiers (like
'lodash') are consistent across all imports, but relative specifiers (like'../utils/api') vary by importer location.
136-144: I'll verify the review comment by investigating webpack's type definitions forinputFileSystemand assessing the type safety concern.
<function_calls>
#!/bin/bashFirst, check the file to understand the context
cat -n code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts | sed -n '130,150p'
</function_calls>
<function_calls>
#!/bin/bashCheck webpack version in package.json
fd -n "package.json" code/builders/builder-webpack5 | head -1 | xargs cat | grep -A2 -B2 '"webpack'
</function_calls>
<function_calls>
#!/bin/bashSearch for InputFileSystem type in webpack or the file itself
rg -n "InputFileSystem|inputFileSystem" code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts -C5
</function_calls>
<function_calls>
web_search for webpack InputFileSystem type interface definition
</function_calls>
| // Early filter only for external specifiers. Relative/local specifiers need resolution | ||
|
|
||
| // Early filter only for external specifiers. Relative/local specifiers need resolution |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate comment.
The comment "Early filter only for external specifiers. Relative/local specifiers need resolution" appears twice (lines 104-105 and 106).
Apply this diff to remove the duplication:
const isExternal = getIsExternal(path, importer);
- // Early filter only for external specifiers. Relative/local specifiers need resolution
-
// Early filter only for external specifiers. Relative/local specifiers need resolution
if (isExternal && !this.candidateSpecifiers.has(path)) {📝 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.
| // Early filter only for external specifiers. Relative/local specifiers need resolution | |
| // Early filter only for external specifiers. Relative/local specifiers need resolution | |
| const isExternal = getIsExternal(path, importer); | |
| // Early filter only for external specifiers. Relative/local specifiers need resolution | |
| if (isExternal && !this.candidateSpecifiers.has(path)) { |
🤖 Prompt for AI Agents
In code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts around
lines 104-106, there is a duplicated comment "Early filter only for external
specifiers. Relative/local specifiers need resolution"; remove the duplicate so
the comment appears only once (keep a single instance in the most appropriate
place) and ensure surrounding spacing/formatting remains consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (1)
10-14: Fix typo in JSDoc comment."includiweng" should be "including".
/** * A Webpack plugin that injects the module mocker runtime script into the preview iframe's HTML. - * This ensures the `sb` object is available globally before any other scripts, includiweng the + * This ensures the `sb` object is available globally before any other scripts, including the * Storybook preview bundle, are executed. */
🧹 Nitpick comments (1)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (1)
62-73: Guard logic is correct; consider relocating the comment for clarity.The asset emission guard correctly prevents duplicates. However, the comment on lines 70-72 describes the
unshiftoperation inside the if block but is positioned outside it, making it appear to describe the callback instead.if (!compilation.getAsset(runtimeAssetName)) { compilation.emitAsset( runtimeAssetName, new compiler.webpack.sources.RawSource(runtimeScriptContent) ); + // Prepend the name of our new asset to the list of JavaScript files. + // HtmlWebpackPlugin will automatically create a <script> tag for it + // and place it at the beginning of the body scripts. data.assets.js.unshift(runtimeAssetName); } - // Prepend the name of our new asset to the list of JavaScript files, once. - // HtmlWebpackPlugin will automatically create a <script> tag for it - // and place it at the beginning of the body scripts. cb(null, data);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts(2 hunks)code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use camelCase for variable and function names
Files:
code/builders/builder-webpack5/src/preview/iframe-webpack.config.tscode/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Enable TypeScript strict mode
Export functions from modules for testing purposes
Files:
code/builders/builder-webpack5/src/preview/iframe-webpack.config.tscode/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts
**/*.{ts,tsx,js,jsx,json,html,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx,json,html,mjs}: Use ESLint and Prettier for code style enforcement
Run 'yarn prettier --write ' to format code after making changes
Run 'yarn lint:js:cmd ' to check for ESLint issues after making changes
Files:
code/builders/builder-webpack5/src/preview/iframe-webpack.config.tscode/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts
code/**/!(*.test).{ts,tsx,js,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/!(*.test).{ts,tsx,js,mjs}: Use 'logger' from 'storybook/internal/node-logger' for server-side (Node.js) logging, not console.log/console.warn/console.error
Use 'logger' from 'storybook/internal/client-logger' for client-side (browser) logging, not console.log/console.warn/console.error
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/builders/builder-webpack5/src/preview/iframe-webpack.config.tscode/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts
🪛 ast-grep (0.40.0)
code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
[warning] 132-132: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${resolvedOutputDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: normal
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (4)
code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts (2)
47-47: LGTM! Correctly resolves the output directory.The resolved absolute path is needed for the watchOptions.ignored configuration to prevent rebuild loops.
130-134: LGTM! Properly prevents rebuild loops with escaped regex pattern.The change correctly ignores both
node_modulesand the output directory in watch mode. The regex escaping using.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')is the standard pattern for escaping special characters.Regarding the static analysis ReDoS warning: this is a false positive in this context since
resolvedOutputDircomes from developer configuration (theoutputDiroption), not runtime user input. The path is properly escaped and the pattern is straightforward.code/builders/builder-webpack5/src/plugins/webpack-inject-mocker-runtime-plugin.ts (2)
16-16: LGTM!The lazy caching pattern using nullish coalescing with assignment is idiomatic and correctly avoids redundant
getMockerRuntime()calls across compilations.Also applies to: 56-57
74-77: LGTM!Properly forwarding errors to the callback ensures Webpack can handle and report failures during asset tag generation.
289b99b to
5c0c277
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts (1)
62-65: Ensure early return if module-mocking is disabled.Since all three module-mocking components are disabled (lines 45-55, 60, 65), the early return at lines 38-40 becomes the only functional guard. However, the function still continues to line 66, setting up empty plugin arrays unnecessarily.
Consider making the early return more explicit:
// If there's no preview file, there's nothing to mock. + // Module-mocking is currently disabled in this preset. if (!previewConfigPath) { return config; } - config.plugins = config.plugins || []; + // config.plugins = config.plugins || []; // 1. Add the loader to normalize sb.mock(import(...)) calls.Or remove the entire function body since it effectively does nothing:
export async function webpackFinal(config: Configuration, options: Options) { - const previewConfigPath = findConfigFile('preview', options.configDir); - - // If there's no preview file, there's nothing to mock. - if (!previewConfigPath) { - return config; - } - - config.plugins = config.plugins || []; - - // ... all commented code ... - + // Module-mocking workflow temporarily disabled (see PR #33169) return config; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use camelCase for variable and function names
Files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Enable TypeScript strict mode
Export functions from modules for testing purposes
Files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
**/*.{ts,tsx,js,jsx,json,html,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx,json,html,mjs}: Use ESLint and Prettier for code style enforcement
Run 'yarn prettier --write ' to format code after making changes
Run 'yarn lint:js:cmd ' to check for ESLint issues after making changes
Files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
code/**/!(*.test).{ts,tsx,js,mjs}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
code/**/!(*.test).{ts,tsx,js,mjs}: Use 'logger' from 'storybook/internal/node-logger' for server-side (Node.js) logging, not console.log/console.warn/console.error
Use 'logger' from 'storybook/internal/client-logger' for client-side (browser) logging, not console.log/console.warn/console.error
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size
Files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `vi.mock()` with the `spy: true` option for all package and file mocks in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the `spy: true` option in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use type-safe mocking with `vi.mocked()` in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without `vi.mocked()` in Vitest tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T17:49:47.659Z
Learning: Applies to **/*.test.{ts,tsx} : Use 'vi.mock()' to mock external dependencies like file system and loggers in unit tests
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid inline mock implementations within test cases in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid direct function mocking without `vi.mocked()` in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
📚 Learning: 2025-11-24T17:49:59.279Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-11-24T17:49:59.279Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking without the `spy: true` option in Vitest tests
Applied to files:
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: normal
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (1)
code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts (1)
12-13: Document the intentional temporary disable with clear rationale; mismatch between PR title ("improve performance") and actual changes (complete disable via revert) requires clarification.The code currently disables the entire module-mocking workflow by commenting out all three components (loader, WebpackMockPlugin, and WebpackInjectMockerRuntimePlugin) in the webpack5 builder's custom preset. While the "Temporarily disabled" comments indicate this is intentional rather than accidental code, there's a significant mismatch:
- PR title states: "Improve performance of module-mocking plugins"
- Actual changes: Complete disable via revert (disables all plugin instantiation)
The plugin files themselves still exist with active code, and e2e tests for module-mocking still reference it, creating confusion about the intended end state. If this temporary disable is intentional:
- Add a detailed comment explaining why module-mocking is disabled (e.g., isolating a regression, feature rollback, testing baseline)
- Include a tracking issue or TODO linking to when/how this will be re-enabled
- Consider whether the PR title should reflect the actual changes ("Revert module-mocking integration" or similar)
If the plugins are meant to stay disabled, remove the orphaned code instead of leaving it commented.
| // Temporarily disabled: module-mocking transform | ||
| // config.module!.rules!.push({ | ||
| // test: /preview\.(t|j)sx?$/, | ||
| // use: [ | ||
| // { | ||
| // loader: fileURLToPath( | ||
| // import.meta.resolve('@storybook/builder-webpack5/loaders/storybook-mock-transform-loader') | ||
| // ), | ||
| // }, | ||
| // ], | ||
| // }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove commented code or add clear TODO with timeline.
Commented code blocks should not remain in the codebase without clear explanation. Either:
- Remove this code entirely if the module-mocking workflow is permanently disabled in this preset
- Add a TODO comment with context explaining why it's temporarily disabled, when it will be re-enabled, and under what conditions
Consider adding configuration to conditionally enable/disable module-mocking:
- // Temporarily disabled: module-mocking transform
- // config.module!.rules!.push({
- // test: /preview\.(t|j)sx?$/,
- // use: [
- // {
- // loader: fileURLToPath(
- // import.meta.resolve('@storybook/builder-webpack5/loaders/storybook-mock-transform-loader')
- // ),
- // },
- // ],
- // });
+ // TODO: Re-enable module-mocking after performance testing (see PR #33169)
+ // const enableModuleMocking = options.features?.moduleMocking ?? false;
+ // if (enableModuleMocking) {
+ // config.module!.rules!.push({
+ // test: /preview\.(t|j)sx?$/,
+ // use: [
+ // {
+ // loader: fileURLToPath(
+ // import.meta.resolve('@storybook/builder-webpack5/loaders/storybook-mock-transform-loader')
+ // ),
+ // },
+ // ],
+ // });
+ // }📝 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.
| // Temporarily disabled: module-mocking transform | |
| // config.module!.rules!.push({ | |
| // test: /preview\.(t|j)sx?$/, | |
| // use: [ | |
| // { | |
| // loader: fileURLToPath( | |
| // import.meta.resolve('@storybook/builder-webpack5/loaders/storybook-mock-transform-loader') | |
| // ), | |
| // }, | |
| // ], | |
| // }); | |
| // TODO: Re-enable module-mocking after performance testing (see PR #33169) | |
| // const enableModuleMocking = options.features?.moduleMocking ?? false; | |
| // if (enableModuleMocking) { | |
| // config.module!.rules!.push({ | |
| // test: /preview\.(t|j)sx?$/, | |
| // use: [ | |
| // { | |
| // loader: fileURLToPath( | |
| // import.meta.resolve('@storybook/builder-webpack5/loaders/storybook-mock-transform-loader') | |
| // ), | |
| // }, | |
| // ], | |
| // }); | |
| // } |
🤖 Prompt for AI Agents
In code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts around
lines 45 to 55, there is a commented-out module-mocking transform block left
without explanation; either remove the dead code or replace it with a clear TODO
that states why it’s disabled, the expected re-enable date/conditions, and
owner, or implement a config flag to enable/disable it at runtime (e.g., read a
preset option or env var) and wrap the loader registration in that conditional
so the intent and lifecycle are explicit.
| // This plugin scans the preview file and sets up rules to swap modules. | ||
| config.plugins.push(new WebpackMockPlugin({ previewConfigPath })); | ||
| // Temporarily disabled: module-mocking plugin | ||
| // config.plugins.push(new WebpackMockPlugin({ previewConfigPath })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all webpack preset files
echo "=== Finding all preset files in webpack5 builder ==="
fd -t f "preset" code/builders/builder-webpack5/src --type ts --type js
echo ""
echo "=== Listing presets directory ==="
ls -la code/builders/builder-webpack5/src/presets/ 2>/dev/null || echo "Directory structure check"Repository: storybookjs/storybook
Length of output: 591
🏁 Script executed:
#!/bin/bash
# Find all preset files with correct syntax
echo "=== Finding preset files ==="
fd -e ts -e js "preset" code/builders/builder-webpack5/src
echo ""
echo "=== Checking WebpackMockPlugin usage in presets ==="
rg -n "WebpackMockPlugin|WebpackInjectMockerRuntimePlugin" code/builders/builder-webpack5/src/presets/ -A 2 -B 2
echo ""
echo "=== All plugin references in the builder ==="
rg -n "WebpackMockPlugin|WebpackInjectMockerRuntimePlugin" code/builders/builder-webpack5/src --type ts --type js -B 2 -A 2Repository: storybookjs/storybook
Length of output: 7748
🏁 Script executed:
#!/bin/bash
# Check preview-preset.ts content
echo "=== Content of preview-preset.ts ==="
cat -n code/builders/builder-webpack5/src/presets/preview-preset.ts
echo ""
echo "=== Check for plugin usage in preview-preset ==="
rg -n "WebpackMockPlugin|WebpackInjectMockerRuntimePlugin" code/builders/builder-webpack5/src/presets/preview-preset.ts -B 3 -A 3
echo ""
echo "=== Search for TODO or issue refs related to these plugins ==="
rg -n "TODO|FIXME|disabled|temporarily" code/builders/builder-webpack5/src/presets/custom-webpack-preset.tsRepository: storybookjs/storybook
Length of output: 1503
🏁 Script executed:
#!/bin/bash
echo "=== Full custom-webpack-preset.ts ==="
cat -n code/builders/builder-webpack5/src/presets/custom-webpack-preset.tsRepository: storybookjs/storybook
Length of output: 4257
🏁 Script executed:
#!/bin/bash
echo "=== Checking WebpackMockPlugin for mtime improvements ==="
rg -n "mtime|lastPreviewMtime|invalidat" code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts -B 2 -A 2
echo ""
echo "=== Checking full WebpackMockPlugin implementation ==="
wc -l code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts
echo ""
echo "=== Key parts of WebpackMockPlugin ==="
head -60 code/builders/builder-webpack5/src/plugins/webpack-mock-plugin.ts | tail -20Repository: storybookjs/storybook
Length of output: 1941
Perfect. I've now gathered all the necessary information to verify the review comment. Let me provide the final rewritten comment:
Document the relationship between plugin improvements and disabling.
The PR improves WebpackMockPlugin performance with mtime-based invalidation (lines 54, 71–87 in webpack-mock-plugin.ts) and candidate tracking, yet the entire module-mocking feature remains disabled in custom-webpack-preset.ts with "Temporarily disabled" comments (lines 45–65). This creates a disconnect:
- Only 2 webpack presets exist; preview-preset.ts doesn't use these plugins
- custom-webpack-preset.ts is the only preset that should enable them
- Improvements won't be utilized while disabled
Clarify: Are these optimizations ready for re-enablement, or is there a specific blocker? If this is work-in-progress, consider adding a GitHub issue reference or timeline for completion.
🤖 Prompt for AI Agents
In code/builders/builder-webpack5/src/presets/custom-webpack-preset.ts around
lines 58 to 60, the module-mocking plugin is disabled but related performance
improvements exist in webpack-mock-plugin.ts; update the file to document the
current state and next steps by either re-enabling the plugin if the mtime-based
invalidation and candidate tracking are ready, or adding a clear TODO comment
and a GitHub issue/timeline reference that explains the blocker and when it will
be re-enabled; ensure the comment clarifies that this preset is the only place
the plugin would be used and that preview-preset.ts does not apply, so reviewers
know whether to expect the improvements to be active or tracked elsewhere.
Closes #
What I did
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.🦋 Canary release
This pull request has been released as version
0.0.0-pr-33169-sha-180015d5. Try it out in a new sandbox by runningnpx [email protected] sandboxor in an existing project withnpx [email protected] upgrade.More information
0.0.0-pr-33169-sha-180015d5valentin/fix-hmr-for-webpack-users180015d51764233056)To request a new release of this pull request, mention the
@storybookjs/coreteam.core team members can create a new canary release here or locally with
gh workflow run --repo storybookjs/storybook publish.yml --field pr=33169Summary by CodeRabbit
Bug Fixes
Performance
Stability
Chores
✏️ Tip: You can customize this high-level summary in your review settings.