Skip to content

[2.x] fix: anchor webpack-config extension source detection to the real src directory#4770

Open
PrimateCoder wants to merge 1 commit into
flarum:2.xfrom
PrimateCoder:fix/webpack-anchor-src-detection
Open

[2.x] fix: anchor webpack-config extension source detection to the real src directory#4770
PrimateCoder wants to merge 1 commit into
flarum:2.xfrom
PrimateCoder:fix/webpack-anchor-src-detection

Conversation

@PrimateCoder

Copy link
Copy Markdown

Fixes a build failure in js-packages/webpack-config that occurs when an extension (or core) is checked out under a filesystem path that itself contains a src segment (e.g. ~/src/my-ext).

Problem

The webpack config identifies an extension's own source files (under its src/ dir) using loose "src" matching in several places:

  • index.cjs: loader rules use include: /src/ — a regex matching the substring "src" anywhere in a module's absolute path.
  • RegisterAsyncChunksPlugin.cjs: module.resource.split(path.sep).includes('src') and module.resource.includes('/src/').
  • autoChunkNameLoader.cjs: absolutePathToImport.includes('src') then .split('src/')[1].

When the project lives under a path containing a src segment, the absolute paths of node_modules files also contain "src", so:

  1. The auto-export loader runs on third-party modules (e.g. @babel/runtime/helpers/esm/defineProperty.js, which contains export { _defineProperty as default }) and emits invalid flarum.reg.add('…', { _defineProperty as default: … }), failing the build with Module parse failed: Unexpected token.
  2. RegisterAsyncChunksPlugin treats node_modules modules as extension source and throws TypeError: Cannot read properties of undefined (reading 'includes') when such a module's _source._value is undefined.
  3. autoChunkNameLoader splits on the first src/ in the path, so an extension with dynamic imports gets chunk names that leak the checkout path (e.g. acme/js/… instead of forum/Lazy).

This doesn't reproduce in normal CI checkouts because their paths don't contain a src segment — which is why it's easy to miss.

Fix

Anchor every "is this file part of the extension's src?" check to the extension's actual src directory (path.resolve(process.cwd(), 'src'), or the loader's this.rootContext) and match by directory prefix instead of loose substring/segment matching. Also hardens a _source._value?. access with optional chaining.

This is a no-op for checkouts not under a src path (where /src/ only ever matched the project's own src). process.cwd() is already the basis for entry points, the output dir, and composer.json / package.json resolution throughout this config, so this introduces no new assumption.

Tests

Adds tests/srcPathAnchoring.test.js (self-contained; does not depend on the monorepo composer.json):

  • the source-loader rules use an absolute <cwd>/src include rather than a /src/ regex, and do not match node_modules under an unrelated …/src/… path;
  • autoChunkNameLoader produces chunk names relative to the extension's src even when the checkout path contains a src segment;
  • external (ext: / flarum/) imports still convert to flarum.reg.asyncModuleImport(...).

These fail against the pre-fix code and pass after it.

Verification

Built a real Flarum 2.x extension whose checkout path contains a src segment: the build previously failed with both errors above and now succeeds. A dynamic import yields addChunkModule('…','…','<ns>','forum/Lazy') (correctly src-relative) with no checkout-path leakage, and the produced bundle is otherwise byte-identical.

… dir

The config identifies an extension's own source files (under its `src/`
dir) using loose "src" matching: `include: /src/` in index.cjs,
`resource.split(path.sep).includes('src')` / `resource.includes('/src/')`
in RegisterAsyncChunksPlugin, and `absolutePathToImport.includes('src')`
in autoChunkNameLoader.

When a project is checked out under a path that itself contains a "src"
segment (e.g. ~/src/my-ext), node_modules paths also contain "src", so:
the auto-export loader runs on third-party modules (e.g. @babel/runtime
helpers) and emits invalid flarum.reg.add(...) (build fails with "Module
parse failed"); RegisterAsyncChunksPlugin treats node_modules as
extension source and throws "Cannot read properties of undefined
(reading 'includes')"; and autoChunkNameLoader produces chunk names that
leak the checkout path.

Anchor all of these to the extension's actual src directory
(path.resolve(process.cwd(), 'src') / this.rootContext) using directory
prefix matching, and harden the _source._value access. No-op for
checkouts not under a "src" path. Adds regression tests.
@PrimateCoder PrimateCoder requested a review from a team as a code owner June 19, 2026 03:15
@PrimateCoder PrimateCoder changed the title fix: anchor webpack-config extension source detection to the real src directory [2.x] fix: anchor webpack-config extension source detection to the real src directory Jun 19, 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

Development

Successfully merging this pull request may close these issues.

1 participant