Proposal: filename-based dist folder control for multi-clientlib components
I have a working implementation of the features described below, including tests and documentation. If this proposal is approved, I can open a PR with the full change ready to review.
AEM requires one folder per clientlib. A component with publish, author, and feature variants needs multiple clientlibs, meaning multiple source folders today, just to satisfy the clientlibs folder constraint.
This proposes three new flags that would let the build read the folder structure from the filename, so all files for a component stay together in source and fan out correctly in dist.
A separate flag would also generate the clientlib metadata files (.content.xml, js.txt) for webpack splitChunks groups, and checkChunk would expose the source filename to test functions so chunk grouping can follow the same naming convention.
New options
All would default to false / []. Existing projects would be unaffected unless they opt in.
Filename-based dist folders (config.general)
| Option |
What it does |
sourceKey: string or string[] |
Match one or multiple source suffixes (e.g. 'clientlibs' or ['clientlibs', 'publishlibs', 'authorlibs']) |
sourceKeyAsDistFolder: true |
Promote the matched sourceKey suffix to a dist subfolder |
fileNameDotSuffixesAsDistFolder: true |
Promote dot-segments between name and sourceKey suffix to dist subfolders |
excludeFileNameDotSuffixes: string[] |
Opt specific values out of folder promotion (migration safety valve) |
Split chunks clientlibs (config.clientlibs)
| Option |
What it does |
generateSplitChunksClientlibs: true |
Auto-generate .content.xml + js.txt for webpack splitChunks / runtimeChunk output folders |
This would be independent of the filename-based flags above. checkChunk would also expose module.resource (the full file path including filename) to splitChunks cache group test functions, making it possible to also route files by name convention into dedicated chunk groups.
The idea
All files for a component live in one folder (not mandatory). One ls returns the complete picture of what it does and how it splits, useful for developers navigating the codebase and for AI tools that rely on directory context to understand component scope.
When an AI needs context to fix or extend a component, one directory read is enough instead of correlating multiple parallel trees, which means fewer tool calls and less context consumed.
sourceKey: ['clientlibs', 'publishlibs', 'authorlibs'],
sourceKeyAsDistFolder: true,
fileNameDotSuffixesAsDistFolder: true,
excludeFileNameDotSuffixes: ['clientlibs']
src/components/cmp/v1/cmp/
cmp.main.publishlibs.js ← The main cmp functionality
cmp.main.publishlibs.scss ← The default cmp styles
cmp.main.authorlibs.js ← The main cmp author functionality when needed
cmp.main.authorlibs.scss. ← The default cmp author styles overwrites
cmp.layout1.publishlibs.scss ← loaded only when needed based on cmp config
cmp.layout1.authorlibs.scss ← some layout/feature might need author css overwrites
cmp.layout2.publishlibs.scss ← loaded only when needed based on cmp config
cmp.tracking.clientlibs.js ← loaded if tracking is enabled
cmp.dialog.clientlibs.js ← loaded as extra clientlib in dialog
cmp.dialog.clientlibs.scss ← loaded as extra clientlib in dialog
cmp.editor.clientlibs.scss ← custom granite editor toolbars widgets
dist/components/cmp/v1/cmp
main/
publishlibs/
.content.xml
js.txt
css.txt
cmp.bundle.js
cmp.bundle.css
authorlibs/
.content.xml
js.txt
css.txt
cmp.bundle.js
cmp.bundle.css
layout1/
publishlibs/
.content.xml
css.txt
cmp.layout1.bundle.css
authorlibs/
.content.xml
css.txt
cmp.layout1.bundle.css
layout2/
publishlibs/
.content.xml
css.txt
cmp.layout2.bundle.css
tracking/
.content.xml
js.txt
cmp.tracking.bundle.js
dialog/
.content.xml
js.txt
css.txt
cmp.dialog.bundle.js
cmp.dialog.bundle.css
editor/
.content.xml
css.txt
cmp.editor.bundle.css
Scope
Core logic - utils/generateEntries.js, utils/checkChunk.js
Tasks - tasks/clientlibs.js (split chunks support), tasks/styles.js (watcher compatibility with array sourceKey and new flags)
Config - config/general.config.js, config/clientlibs.config.js, config/optimization.config.js
Tests - new fixture sets for feature-segments and multi-sourcekey scenarios, covering all flag combinations
Proposal: filename-based dist folder control for multi-clientlib components
I have a working implementation of the features described below, including tests and documentation. If this proposal is approved, I can open a PR with the full change ready to review.
AEM requires one folder per clientlib. A component with publish, author, and feature variants needs multiple clientlibs, meaning multiple source folders today, just to satisfy the clientlibs folder constraint.
This proposes three new flags that would let the build read the folder structure from the filename, so all files for a component stay together in source and fan out correctly in dist.
A separate flag would also generate the clientlib metadata files (
.content.xml,js.txt) for webpacksplitChunksgroups, andcheckChunkwould expose the source filename totestfunctions so chunk grouping can follow the same naming convention.New options
All would default to
false/[]. Existing projects would be unaffected unless they opt in.Filename-based dist folders (
config.general)sourceKey: string or string[]'clientlibs'or['clientlibs', 'publishlibs', 'authorlibs'])sourceKeyAsDistFolder: truefileNameDotSuffixesAsDistFolder: trueexcludeFileNameDotSuffixes: string[]Split chunks clientlibs (
config.clientlibs)generateSplitChunksClientlibs: true.content.xml+js.txtfor webpacksplitChunks/runtimeChunkoutput foldersThis would be independent of the filename-based flags above.
checkChunkwould also exposemodule.resource(the full file path including filename) tosplitChunkscache grouptestfunctions, making it possible to also route files by name convention into dedicated chunk groups.The idea
All files for a component live in one folder (not mandatory). One
lsreturns the complete picture of what it does and how it splits, useful for developers navigating the codebase and for AI tools that rely on directory context to understand component scope.When an AI needs context to fix or extend a component, one directory read is enough instead of correlating multiple parallel trees, which means fewer tool calls and less context consumed.
Scope
Core logic -
utils/generateEntries.js,utils/checkChunk.jsTasks -
tasks/clientlibs.js(split chunks support),tasks/styles.js(watcher compatibility with arraysourceKeyand new flags)Config -
config/general.config.js,config/clientlibs.config.js,config/optimization.config.jsTests - new fixture sets for feature-segments and multi-sourcekey scenarios, covering all flag combinations