Closed kuhe closed 1 month ago
Submodules examples:
./packages/core/src/submodules/addition/add.ts
export const add = (a, b) => a + b;
./packages/core/src/submodules/addition/index.ts
export * from "./add";
./packages/core/src/submodules/multiplication/multiply.ts
// scope/pkg/submodule is used even within the same package.
import { add } from "@aws-sdk/core/addition";
export const multiply = (a, b) => {
let p = 0;
while (b--) p = add(p, a);
return p;
}
./packages/core/src/submodules/multiplication/index.ts
export * from "./multiply";
dist-cjs
, dist-es
file layout./packages/core
dist-cjs/
submodules/
addition/
index.js # submodule index
multiplication/
index.js # submodule index
index.js # deprecated root index
dist-es/
submodules/
addition/
add.js
index.js
multiplication/
multiply.js
index.js
index.js
Submodules have one js
file per submodule for dist-cjs as a prebundle artifact for Node.js initialization time optimization. Because they use canonical @scope/pkg/submodule
imports, no redundancies are included in each bundle. They function equivalently as separate packages would.
In dist-types
and dist-es
, each source file continues to have a corresponding dist file. This allows ESM bundlers and TypeScript to continue working as expected w.r.t. tree-shaking etc.
Consumer code can seamlessly treat submodules the same as different packages.
import { add } from "@aws-sdk/core/addition";
import { multiply } from "@aws-sdk/core/multiplication";
export const power = (a, b) => {
let p = 1;
while (b--) p = multiply(p, a);
return p;
}
@aws-sdk/core
The linter will take care of this automatically. Each module needs the following metadata:
./package.json
{
"exports": {
"./MODULE_NAME": {
"node": "./dist-cjs/submodules/MODULE_NAME/index.js",
"import": "./dist-es/submodules/MODULE_NAME/index.js",
"require": "./dist-cjs/submodules/MODULE_NAME/index.js",
"types": "./dist-types/submodules/MODULE_NAME/index.d.ts"
},
}
}
For import mapping.
(add to files: []
).
./tsconfig.X.json
{
"compilerOptions": {
"paths": {
"@aws-sdk/core/SUBMODULE_NAME": ["./src/submodules/SUBMODULE_NAME/index.ts"],
}
}
}
For cross-submodule imports within the @aws-sdk/core
package.
For an application that does not understand the exports
field, the linter will generate a compatibility redirect file.
./addition.js
/**
* Do not edit:
* This is a compatibility redirect for contexts that do not understand package.json exports field.
*/
module.exports = require("./dist-cjs/submodules/addition/index.js");
The location of this file is in the package root to allow an identical resolution path to actual submodules.
I don't know if any authoritative definitions for the different export conditions, so I don't if it's 'okay' to use import
for code that doesn't include file extensions. I know that dist-es won't work in node, but node will use prefer the node
condition and load dist-cjs.
module
is an alternative condition you could use, I know that webpack and esbuild will use module, and that node won't.
confirmed works as expected in latest webpack, rollup, esbuild, vite, react-native (metro), and Node.js (CJS & MJS)
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.
This PR modifies
@aws-sdk/core
into a special package that exports submodules using thepackage.json
exports
field, available since Node.js 12 and widely supported by bundlers.These submodules preserve the benefits of modularization while also consolidating package sprawl and making it easier to have a consistent single version of core functionality.
@aws-sdk/core
has been moved into submodules@aws-sdk/core
.Testing
internal test code available at commit AwsSdkJavaScriptTest/trees/5be19fdc2a1e0d71515f2a081020478e44fb5f5a
Checklist