子路径的模式
对于具有少量导出或导入的包,我们建议显式地列出每个导出子路径条目。
但是对于具有大量子路径的包,这可能会导致 package.json
膨胀和维护问题。
对于这些用例,可以使用子路径导出模式:
// ./node_modules/es-module-package/package.json
{
"exports": {
"./features/*.js": "./src/features/*.js"
},
"imports": {
"#internal/*.js": "./src/internal/*.js"
}
}
*
映射公开嵌套的子路径,因为它只是字符串替换语法。
然后,右侧 *
的所有实例都将替换为该值,包括它是否包含任何 /
分隔符。
import featureX from 'es-module-package/features/x.js';
// 加载 ./node_modules/es-module-package/src/features/x.js
import featureY from 'es-module-package/features/y/y.js';
// 加载 ./node_modules/es-module-package/src/features/y/y.js
import internalZ from '#internal/z.js';
// 加载 ./node_modules/es-module-package/src/internal/z.js
这是直接静态匹配和替换,无需对文件扩展名进行任何特殊处理。
在映射两边包含 "*.js"
限制了暴露的包导出到只有 JS 文件。
导出的静态可枚举属性由导出模式维护,因为可以通过将右侧目标模式视为针对包内文件列表的 **
glob 来确定包的各个导出。
因为导出目标中禁止 node_modules
路径,所以这个扩展只依赖包本身的文件。
要从模式中排除私有子文件夹,可以使用 null
目标:
// ./node_modules/es-module-package/package.json
{
"exports": {
"./features/*.js": "./src/features/*.js",
"./features/private-internal/*": null
}
}
import featureInternal from 'es-module-package/features/private-internal/m.js';
// 抛出: ERR_PACKAGE_PATH_NOT_EXPORTED
import featureX from 'es-module-package/features/x.js';
// 加载 ./node_modules/es-module-package/src/features/x.js
For packages with a small number of exports or imports, we recommend
explicitly listing each exports subpath entry. But for packages that have
large numbers of subpaths, this might cause package.json
bloat and
maintenance issues.
For these use cases, subpath export patterns can be used instead:
// ./node_modules/es-module-package/package.json
{
"exports": {
"./features/*.js": "./src/features/*.js"
},
"imports": {
"#internal/*.js": "./src/internal/*.js"
}
}
*
maps expose nested subpaths as it is a string replacement syntax
only.
All instances of *
on the right hand side will then be replaced with this
value, including if it contains any /
separators.
import featureX from 'es-module-package/features/x.js';
// Loads ./node_modules/es-module-package/src/features/x.js
import featureY from 'es-module-package/features/y/y.js';
// Loads ./node_modules/es-module-package/src/features/y/y.js
import internalZ from '#internal/z.js';
// Loads ./node_modules/es-module-package/src/internal/z.js
This is a direct static matching and replacement without any special handling
for file extensions. Including the "*.js"
on both sides of the mapping
restricts the exposed package exports to only JS files.
The property of exports being statically enumerable is maintained with exports
patterns since the individual exports for a package can be determined by
treating the right hand side target pattern as a **
glob against the list of
files within the package. Because node_modules
paths are forbidden in exports
targets, this expansion is dependent on only the files of the package itself.
To exclude private subfolders from patterns, null
targets can be used:
// ./node_modules/es-module-package/package.json
{
"exports": {
"./features/*.js": "./src/features/*.js",
"./features/private-internal/*": null
}
}
import featureInternal from 'es-module-package/features/private-internal/m.js';
// Throws: ERR_PACKAGE_PATH_NOT_EXPORTED
import featureX from 'es-module-package/features/x.js';
// Loads ./node_modules/es-module-package/src/features/x.js