-
Notifications
You must be signed in to change notification settings - Fork 632
Description
Checkboxes for prior research
- I've gone through Developer Guide and API reference
- I've checked AWS Forums and StackOverflow.
- I've searched for previous similar issues and didn't find any solution.
Describe the bug
I am using the AWS v3 SDK in the browser, and it seems like the SDK does not recognize the environment it is running in. Naturally, in the browser there is no access to Node internals like fs
, path
, etc etc. However, it still seems to be searching for a file on the file system for credentials, even though it is being executed in the browser and I am providing it credentials.
I am providing credentials through my own custom endpoint, but when this code executes in my React application, the Webpack bundle builds fine, but fails at run-time with the following error:
Uncaught (in promise) TypeError: Cannot destructure property 'readFile' of 'fs_1.promises' as it is undefined.
at ./node_modules/@aws-sdk/shared-ini-file-loader/dist-cjs/getSSOTokenFromFile.js (getSSOTokenFromFile.js:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/shared-ini-file-loader/dist-cjs/index.js (index.js:7:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/credential-provider-ini/dist-cjs/fromIni.js (fromIni.js:4:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/credential-provider-ini/dist-cjs/index.js (index.js:4:1)
Why is my SDK in the browser calling fs
methods? This doesn't make sense to me. Am I misunderstanding or missing something in the configuration?
SDK version number
@aws-sdk/client-cloudwatch:^3.358.0
Which JavaScript Runtime is this issue in?
Browser
Details of the browser/Node.js/ReactNative version
Chrome: 115.0.5790.102
Reproduction Steps
Webpack Config:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
module.exports = {
entry: path.resolve("src/index.tsx"),
output: {
path: path.resolve(__dirname, "../dist"),
},
module: {
rules: [
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: "url-loader",
options: { limit: false },
},
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.js$/,
enforce: "pre",
use: ["source-map-loader"],
exclude: /node_modules/
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: "./public/index.html" }),
new NodePolyfillPlugin(),
],
resolve: {
mainFields: ["browser", "main", "module"],
extensions: [".tsx", ".ts", ".js"],
fallback: {
"fs": false,
"child_process": false,
"path": require.resolve("path-browserify"),
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"assert": require.resolve("assert"),
"http": require.resolve("stream-http"),
"http2": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"os": require.resolve("os-browserify"),
"url": require.resolve("url")
}
},
};
TS File for Client:
import { CloudwatchClient } from "@aws-sdk/cloudwatch-client";
const getCredentials = async () => {
const res = await fetch(`/credentials/endpoint`);
const json = await res.json();
return json();
}
export const initializeFooClient = async () => {
const credentials = await getCredentials();
const fooClient = new CloudwatchClient({
region: "us-east-2",
credentials: async () => {
return {
...credentials
};
}
});
return { fooClient };
}};
React Component:
import { initializeFooClient } from "xyz";
const TestComponent = () => {
useEffect(() => {
const initalizeClient = async () => {
// redacted the URL, but it does exist and works when I send a cURL request
await initializeFooClient();
};
initalizeClient();
}, []);
Observed Behavior
Get this error
Uncaught (in promise) TypeError: Cannot destructure property 'readFile' of 'fs_1.promises' as it is undefined.
at ./node_modules/@aws-sdk/shared-ini-file-loader/dist-cjs/getSSOTokenFromFile.js (getSSOTokenFromFile.js:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/shared-ini-file-loader/dist-cjs/index.js (index.js:7:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/credential-provider-ini/dist-cjs/fromIni.js (fromIni.js:4:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@aws-sdk/credential-provider-ini/dist-cjs/index.js (index.js:4:1)
Why is my SDK v3 in the browser calling fs
methods? Should it not know at run-time that it is running in a browser environment? Is there something wrong with my webpack configuration? The target for my webpack config is also defaulted to web
.
Expected Behavior
It should initialize the SDK with the credentials I am providing, and should also know that it should not look for a file on the file system, as it is running in the browser 😕
Possible Solution
No response
Additional Information/Context
I have tried adding the following in my package.json
, and it did not work:
"browser": {
"crypto": false,
"fs": false,
"path": false,
"os": false,
"net": false,
"stream": false,
"tls": false
},
I have tried adding fallbacks in my webpack config, and that also does not work.