Comments (6)
Hi @jd-carroll ,
Are you consuming the SDK through ES modules (i.e., using import
instead of require
)? Modern bundlers can be configured to include only the code that is actually used in your application, even if other modules are imported.
What is your bundler configuration?
Thanks,
Ran
from aws-sdk-js-v3.
Mark those modules are external while bundling. Then they will sit in a split chunk that should never be imported if you are indeed providing credentials.
That reduces the size of the parsed and executed code. If you actually have a space limitation in the Lambda with regard to the 128kb, you can mark the external modules as empty, which varies depending on the bundler, so that they are split into a chunk and that chunk is deleted or empty.
from aws-sdk-js-v3.
@kuhe - Right, that is currently the only way to accomplish this.
@RanVaknin - Of course, including setting mainFields to ['module', 'main']
. Let me know if you need help with the esbuild command to bundle the demo lambda function below (you'll also need to make sure you are minimizing the code)
Here is a simple example:
import { AssumeRoleCommand, STSClient } from '@aws-sdk/client-sts';
export const handler = async () => {
const client = new STSClient({
region: 'us-west-2',
credentials: {
accessKeyId: 'fake-access-key-id',
secretAccessKey: 'fake-secret-access-key'
}
});
await client.send(
new AssumeRoleCommand({ RoleArn: 'arn:aws:iam::123456789012:role/demo', RoleSessionName: 'session1' })
);
};
The bundled lambda function from esbuild
looks like:
If we look at just @aws-sdk/*
, that has:
There are a couple of problems here
Problem 1: Non "excludable" code paths
The first problem is that bundler has no way of knowing that the credential providers are unneccessary. This boils down into two parts:
credentialDefaultProvider
is deprecated
I believe the more appropriate use iscredentials
as I have in the example. You are also able to give a provider forcredentials
. However the issue is that theruntimeConfig
forSTSClient
(and likely all clients) has:
export const getRuntimeConfig = (config) => {
...
return {
...config,
...
credentialDefaultProvider: config?.credentialDefaultProvider ?? credentialDefaultProvider,
...
So if you do not set credentialDefaultProvider
there is a hard import of the @aws-sdk/credential-provider-node
httpAuthSchemes
always usescredentialDefaultProvider
But even if you set thecredentialDefaultProvider
in the client config. ThehttpAuthSchemes
always uses thecredentialDefaultProvider
from the import, i.e.:
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
So you would also need to do something like:
const client = new STSClient({
region: 'us-west-2',
credentials: {
accessKeyId: 'fake-access-key-id',
secretAccessKey: 'fake-secret-access-key'
},
credentialDefaultProvider: undefined,
httpAuthSchemes: [
{
schemeId: 'aws.auth#sigv4',
identityProvider: (ipc) =>
ipc.getIdentityProvider('aws.auth#sigv4') ||
(() => Promise.resolve({ expiration: new Date(Date.now() + 1000) })),
signer: new AwsSdkSigV4Signer()
},
{
schemeId: 'smithy.api#noAuth',
identityProvider: (ipc) => ipc.getIdentityProvider('smithy.api#noAuth') || (async () => ({})),
signer: new NoAuthSigner()
}
]
});
But even doing all that, doesn't seem to make any difference.
Only if I completely comment out the credentialDefaultProvider
and httpAuthSchemes
from the getRuntimeConfig
will the @aws-sdk/credential-provider-node
be treeshook from the bundle.
I tried a couple of different ways to add a default credentialDefaultProvider
into the config while still allowing it to be tree shaken, but none seemed to work. My guess would be that it needs to be something more like:
const combined = {
...clientSharedValues,
...config,
runtime: "node",
...,
};
if (!combined.credentialDefaultProvider) {
combined.credentialDefaultProvider = getCredentialDefaultProvider();
}
return result;
Where the import of @aws-sdk/credential-provider-node
is moved one level deep into the getCredentialDefaultProvider
method call. All that to say, the code flow is too complex for static analysis to identify that credentialDefaultProvider
is not necessary.
Problem 2: Incorrect exports conditions
The other item you should notice is that not 100% of the code is ESM. And if we look at where the non-ESM code is coming from (by clicking on the percentages), some of it is coming from @aws-sdk
The issue is that the exports
from @aws-sdk/core
are setup incorrectly. For example, the "default" export from core
looks like:
"main": "./dist-cjs/index.js",
"module": "./dist-es/index.js",
"types": "./dist-types/index.d.ts",
"exports": {
".": {
"node": "./dist-cjs/index.js",
"import": "./dist-es/index.js",
"require": "./dist-cjs/index.js",
"types": "./dist-types/index.d.ts"
},
The problem is that bundlers will prefer "exports"
over any top-level "mian"
/ "module"
and when bundling for a lambda we are setting the platform to be node
which forces the conditions ['node', 'default']
when evaluating the exports.
The result is that any ESM module importing core
will only ever receive the cjs
bundle.
The exports should be structured like:
"main": "./dist-cjs/index.js",
"module": "./dist-es/index.js",
"types": "./dist-types/index.d.ts",
"exports": {
".": {
"node": {
"import": "./dist-es/index.js",
"require": "./dist-cjs/index.js"
},
"import": "./dist-es/index.js",
"require": "./dist-cjs/index.js",
"types": "./dist-types/index.d.ts"
},
Or really, the node
is probably unnecessary, so it should really just be:
"main": "./dist-cjs/index.js",
"module": "./dist-es/index.js",
"types": "./dist-types/index.d.ts",
"exports": {
".": {
"import": "./dist-es/index.js",
"require": "./dist-cjs/index.js",
"types": "./dist-types/index.d.ts"
},
The impact of including core
as a CJS module is only minor, the real issue is @aws-sdk/credential-provider-node
. Once these are resolved, it would be good to reach out to fast-xml-parser
to see if they can release an ESM version of the module in addition to the CJS.
Going back to the first problem... I suspect that even the example solution I suggest may not be enough to indicate to the bundle that @aws-sdk/credential-provider-node
can be treeshaken from the bundle (without significant code changes).
Which brings me back to my original suggestion in that there should be a new "Raw" client which has bare-bones configuration and requires the user to provide other necessary configuration details, such as credentials.
from aws-sdk-js-v3.
Please make a pre-bundle build step that replaces the runtimeConfig.ts file with one that does not contain @aws-sdk/credential-provider-node
if that is what you need.
The use-case is not common enough to provide an official variant from the AWS SDK.
Regarding exports
:
"exports": {
".": {
"import": "./dist-es/index.js",
"require": "./dist-cjs/index.js",
"types": "./dist-types/index.d.ts"
},
There is a reason the node
exports overrides import
.
We only offer our CJS distribution for Node.js because our ES distribution is not MJS compliant and It is only for bundlers. We have not analyzed what effect MJS compliance would have on web bundlers. The CJS distribution will likely remain the only or at least preferred Node.js offering for as long as our minimum Node.js version supports CJS-within-ESM but not ESM-within-CJS.
from aws-sdk-js-v3.
Got it. That's unfortunate that we are required to exclude the unnecessary credential providers ourselves, because its a savings of >75kb minimized (so at scale would be pretty meaningful). But all good.
For the esbuild
'ers, as @-kuhe mentioned above, the best/easist thing to do is drop all of those providers into the excludes
of esbuild.
from aws-sdk-js-v3.
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.
from aws-sdk-js-v3.
Related Issues (20)
- @aws-sdk/client-marketplace-metering index.js Error message: Error reporting usage: TypeError: _.getTime is not a function HOT 5
- No matching version found for `@aws-sdk/[email protected]` HOT 1
- Upload doesn't support polyfills/compat shims for Readable/ReadableStream HOT 5
- Typo HOT 1
- Submit job request processing entire bucket. HOT 1
- StartDate, EndDate and ScheduleExpressionTimeZone fields on PutRulesCommand HOT 3
- Link to Lambda Runtimes Page does not show AWS SDK V3 version provided by Lambda HOT 1
- Incompatibility with ESM in @aws-crypto/sha256-browser HOT 1
- SignatureDoesNotMatch HOT 1
- InvalidParameterException: Log event too large HOT 3
- Incorrect interface types in Amazon CloudFront clients HOT 3
- '@smithy/node-http-handler' not included in lambda Node.js 20.x runtime HOT 1
- API Docs: command class signature has meaningless "extends" signature.
- Create validation script for api-extractor.json to consistently publish API docs for public components HOT 1
- @aws-sdk/client-quicksight TypeError: entry.getTime is not a function HOT 2
- AWS SDK DynamoDB affects perfomance of third party library
- JS SDK should try get region automatically from IMDS like other SDK languages do
- UpdateItemCommand should be UpdateCommand HOT 1
- AppSync paginators not present
- Bedrock Converse API missing exports for commonjs HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aws-sdk-js-v3.