@@ -298,14 +298,14 @@ package. It is not a strong encapsulation since a direct require of any
298298absolute subpath of the package such as
299299` require('/path/to/node_modules/pkg/subpath.js') ` will still load ` subpath.js ` .
300300
301- #### Subpath exports
301+ ### Subpath exports
302302
303- When using the ` "exports" ` field, custom subpaths can be defined along
304- with the main entry point by treating the main entry point as the
305- ` "." ` subpath:
303+ > Stability: 1 - Experimental
306304
307- <!-- eslint-skip -->
308- ``` js
305+ When using the ` "exports" ` field, custom subpaths can be defined along with the
306+ main entry point by treating the main entry point as the ` "." ` subpath:
307+
308+ ``` json
309309{
310310 "main" : " ./main.js" ,
311311 "exports" : {
@@ -315,8 +315,7 @@ with the main entry point by treating the main entry point as the
315315}
316316```
317317
318- Now only the defined subpath in ` "exports" ` can be imported by a
319- consumer:
318+ Now only the defined subpath in ` "exports" ` can be imported by a consumer:
320319
321320``` js
322321import submodule from ' es-module-package/submodule' ;
@@ -330,30 +329,46 @@ import submodule from 'es-module-package/private-module.js';
330329// Throws ERR_PACKAGE_PATH_NOT_EXPORTED
331330```
332331
333- Entire folders can also be mapped with package exports:
332+ ### Subpath export patterns
334333
335- <!-- eslint-skip -->
336- ``` js
334+ > Stability: 1 - Experimental
335+
336+ Explicitly listing each exports subpath entry is recommended for packages with
337+ a small number of exports. But for packages that have very large numbers of
338+ subpaths this can start to cause package.json bloat and maintenance issues.
339+
340+ For these use cases, subpath export patterns can be used instead:
341+
342+ ``` json
337343// ./node_modules/es-module-package/package.json
338344{
339345 "exports" : {
340- " ./features/" : " ./src/features/"
346+ "./features/* " : " ./src/features/*.js "
341347 }
342348}
343349```
344350
345- With the above, all modules within the ` ./src/features/ ` folder
346- are exposed deeply to ` import ` and ` require ` :
351+ The left hand matching pattern must always end in ` * ` . All instances of ` * ` on
352+ the right hand side will then be replaced with this value, including if it
353+ contains any ` / ` separators.
347354
348355``` js
349- import feature from ' es-module-package/features/x.js ' ;
356+ import featureX from ' es-module-package/features/x' ;
350357// Loads ./node_modules/es-module-package/src/features/x.js
358+
359+ import featureY from ' es-module-package/features/y/y' ;
360+ // Loads ./node_modules/es-module-package/src/features/y/y.js
351361```
352362
353- When using folder mappings, ensure that you do want to expose every
354- module inside the subfolder. Any modules which are not public
355- should be moved to another folder to retain the encapsulation
356- benefits of exports.
363+ This is a direct static replacement without any special handling for file
364+ extensions. In the previous example, ` pkg/features/x.json ` would be resolved to
365+ ` ./src/features/x.json.js ` in the mapping.
366+
367+ The property of exports being statically enumerable is maintained with exports
368+ patterns since the individual exports for a package can be determined by
369+ treating the right hand side target pattern as a ` ** ` glob against the list of
370+ files within the package. Because ` node_modules ` paths are forbidden in exports
371+ targets, this expansion is dependent on only the files of the package itself.
357372
358373#### Package exports fallbacks
359374
@@ -1741,7 +1756,8 @@ The resolver can throw the following errors:
17411756> 1. Set _mainExport_ to _exports_ \[_ " ." _ \].
17421757> 1. If _mainExport_ is not ** undefined ** , then
17431758> 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1744- > _packageURL_, _mainExport_, _" " _, ** false ** , _conditions_).
1759+ > _packageURL_, _mainExport_, _" " _, ** false ** , ** false ** ,
1760+ > _conditions_).
17451761> 1. If _resolved_ is not ** null ** or ** undefined ** , then
17461762> 1. Return _resolved_ .
17471763> 1. Otherwise , if _exports_ is an Object and all keys of _exports_ start with
@@ -1775,29 +1791,43 @@ _isImports_, _conditions_)
17751791> 1. If _matchKey_ is a key of _matchObj_ , and does not end in _ " *" _ , then
17761792> 1. Let _target_ be the value of _matchObj_ \[_matchKey_ \].
17771793> 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1778- > _packageURL_, _target_, _" " _, _isImports_, _conditions_).
1794+ > _packageURL_, _target_, _" " _, ** false ** , _isImports_, _conditions_).
17791795> 1. Return the object _ { resolved, exact: ** true ** }_ .
1780- > 1. Let _expansionKeys_ be the list of keys of _matchObj_ ending in _ " /" _ ,
1781- > sorted by length descending .
1796+ > 1. Let _expansionKeys_ be the list of keys of _matchObj_ ending in _ " /" _
1797+ > or _ " * " _ , sorted by length descending .
17821798> 1. For each key _expansionKey_ in _expansionKeys_ , do
1799+ > 1. If _expansionKey_ ends in _ " *" _ and _matchKey_ starts with but is
1800+ > not equal to the substring of _expansionKey_ excluding the last _ " *" _
1801+ > character , then
1802+ > 1. Let _target_ be the value of _matchObj_ \[_expansionKey_ \].
1803+ > 1. Let _subpath_ be the substring of _matchKey_ starting at the
1804+ > index of the length of _expansionKey_ minus one .
1805+ > 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1806+ > _packageURL_, _target_, _subpath_, ** true ** , _isImports_,
1807+ > _conditions_).
1808+ > 1. Return the object _ { resolved, exact: ** true ** }_ .
17831809> 1. If _matchKey_ starts with _expansionKey_ , then
17841810> 1. Let _target_ be the value of _matchObj_ \[_expansionKey_ \].
17851811> 1. Let _subpath_ be the substring of _matchKey_ starting at the
17861812> index of the length of _expansionKey_ .
17871813> 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1788- > _packageURL_, _target_, _subpath_, _isImports_, _conditions_).
1814+ > _packageURL_, _target_, _subpath_, ** false ** , _isImports_,
1815+ > _conditions_).
17891816> 1. Return the object _ { resolved, exact: ** false ** }_ .
17901817> 1. Return the object _ { resolved: ** null ** , exact: ** true ** }_ .
17911818
1792- ** PACKAGE_TARGET_RESOLVE ** (_packageURL_, _target_, _subpath_, _internal_ ,
1793- _conditions_)
1819+ ** PACKAGE_TARGET_RESOLVE ** (_packageURL_, _target_, _subpath_, _pattern_ ,
1820+ _internal_, _conditions_)
17941821
17951822> 1. If _target_ is a String , then
1796- > 1. If _subpath_ has non - zero length and _target_ does not end with _ " / " _ ,
1797- > throw an _Invalid Module Specifier_ error .
1823+ > 1. If _pattern_ is ** false ** , _subpath_ has non - zero length and _target_
1824+ > does not end with _ " / " _ , throw an _Invalid Module Specifier_ error .
17981825> 1. If _target_ does not start with _ " ./" _ , then
17991826> 1. If _internal_ is ** true ** and _target_ does not start with _ " ../" _ or
18001827> _ " /" _ and is not a valid URL , then
1828+ > 1. If _pattern_ is ** true ** , then
1829+ > 1. Return ** PACKAGE_RESOLVE ** (_target_ with every instance of
1830+ > _" *" _ replaced by _subpath_, _packageURL_ + _" /" _)_ .
18011831> 1. Return ** PACKAGE_RESOLVE ** (_target_ + _subpath_,
18021832> _packageURL_ + _" /" _)_ .
18031833> 1. Otherwise , throw an _Invalid Package Target_ error .
@@ -1809,8 +1839,12 @@ _conditions_)
18091839> 1. Assert : _resolvedTarget_ is contained in _packageURL_ .
18101840> 1. If _subpath_ split on _ " /" _ or _ " \\ " _ contains any _ " ." _ , _ " .." _ or
18111841> _ " node_modules" _ segments , throw an _Invalid Module Specifier_ error .
1812- > 1. Return the URL resolution of the concatenation of _subpath_ and
1813- > _resolvedTarget_ .
1842+ > 1. If _pattern_ is ** true ** , then
1843+ > 1. Return the URL resolution of _resolvedTarget_ with every instance of
1844+ > _ " *" _ replaced with _subpath_ .
1845+ > 1. Otherwise ,
1846+ > 1. Return the URL resolution of the concatenation of _subpath_ and
1847+ > _resolvedTarget_ .
18141848> 1. Otherwise , if _target_ is a non - null Object , then
18151849> 1. If _exports_ contains any index property keys , as defined in ECMA - 262
18161850> [6.1 .7 Array Index ][], throw an _Invalid Package Configuration_ error .
@@ -1819,16 +1853,18 @@ _conditions_)
18191853> then
18201854> 1. Let _targetValue_ be the value of the _p_ property in _target_ .
18211855> 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1822- > _packageURL_, _targetValue_, _subpath_, _internal_, _conditions_).
1856+ > _packageURL_, _targetValue_, _subpath_, _pattern_, _internal_,
1857+ > _conditions_).
18231858> 1. If _resolved_ is equal to ** undefined ** , continue the loop .
18241859> 1. Return _resolved_ .
18251860> 1. Return ** undefined ** .
18261861> 1. Otherwise , if _target_ is an Array , then
18271862> 1. If _target .length is zero , return ** null ** .
18281863> 1. For each item _targetValue_ in _target_ , do
18291864> 1. Let _resolved_ be the result of ** PACKAGE_TARGET_RESOLVE ** (
1830- > _packageURL_, _targetValue_, _subpath_, _internal_, _conditions_),
1831- > continuing the loop on any _Invalid Package Target_ error .
1865+ > _packageURL_, _targetValue_, _subpath_, _pattern_, _internal_,
1866+ > _conditions_), continuing the loop on any _Invalid Package Target_
1867+ > error .
18321868> 1. If _resolved_ is ** undefined ** , continue the loop .
18331869> 1. Return _resolved_ .
18341870> 1. Return or throw the last fallback resolution ** null ** return or error .
0 commit comments