aws-sdk-js icon indicating copy to clipboard operation
aws-sdk-js copied to clipboard

Vite apps will not build or run while using Amplify libraries with AWS-SDK

Open ErikCH opened this issue 4 years ago • 37 comments

Confirm by changing [ ] to [x] below to ensure that it's a bug:

Describe the bug Customers using the Amplify library are not able to use Vite, a native ESM no-bundle dev server, for Vue, React and Preact. After installing the package customers trying to run the dev server will get this error.

Uncaught ReferenceError: global is not defined
    at index.js:43
    at aws-amplify.js?v=b14c5c6f:14
    at AuthenticationHelper.js:17

Users trying to build their app will get this error.

2: import { ProviderError } from "@aws-sdk/property-provider";
3: import { Buffer } from "buffer";
4: import { request } from "http";
            ^
5: /**
6:  * @internal
error during build:
Error: 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
    at error ...

After further research with the Amplify team we have found a workaround as illustrated in 7499.

This workaround explicitly tells Vite, which uses rollup, to alias the runtimeConfig to the runtimeConfig.browser file.

We believe the problem is that Vite doesn't respect the browser field in @aws-sdk/client- package.json. This is a deliberate action made on the maintainers behalf, as outlined here.

vitejs/vite#2329 okta/okta-auth-js#641

This is what we learned as discussed from this comment here.

  1. @aws-sdk/credential-provider-imds is only required by @aws-sdk/credential-provider-node
  2. @aws-sdk/credential-provider-node is defined in runtimeConfig.ts within the @aws-sdk/client-* packages.`

Is it possible for the @aws-sdk/client libraries to update their package.json's so Vite, and other ESM bundlers would correctly use the correct browser packages, and not the Node built-ins, since it's not respecting the browser field? The maintainer has recommended using exports as one possible solution.

Anecdotally, this issue might also exist with Snowpack, another ESM dev server, however, it has a workaround by using the --polyfill-node pollyfill argument, that Vite does not have.

Is the issue in the browser/Node.js? Browse

SDK version number Example: latest

To Reproduce (observed behavior) I have a repo with the work around here. To reproduce the issue remove the alias from the vite config, and the <script> tag in the index.html.

Or create a new vite app

$ yarn create @vitejs/app
$ cd new-vite-app
$ yarn

Install amplify

yarn add aws-amplify

Add amplify to main.js file

import Amplify, { Auth } from 'aws-amplify';

Amplify.configure({});

Run the server and then try to build the server

yarn run dev
yarn run build

Expected behavior Dev server and builds should run without errors, or needing to add global and exports into script tag for HTML.

ErikCH avatar Mar 23 '21 17:03 ErikCH

any update on this? I have the exact same issue using SvelteKit

half2me avatar Jun 01 '21 16:06 half2me

@ErikCH <script> var global = global || window; var Buffer = Buffer || []; var process = process || { env: { DEBUG: undefined }, version: [] }; </script>

please add these code to index.html,maybe can fix it.

woniupapa avatar Jun 05 '21 08:06 woniupapa

@ErikCH https://stackoverflow.com/questions/66912795/in-vite-vue3-ts-project-aws-amplify-failed-to-resolve-components

woniupapa avatar Jun 05 '21 08:06 woniupapa

Vite actually respects the browser field. But it only reads from the package root.

However, these problematic packages have more than one package.json.

For example, the @aws-sdk/client-cognito-identity has a package.json under the dist/es/ directory. https://unpkg.com/browse/@aws-sdk/[email protected]/dist/es/package.json And that's what it expects the bundlers to read. It is respected in webpack but not in vite.

To be fair, this is undocumented behavior. The browser field spec never says which package.json a bundler should read.

The SDK can fix this issue by removing the nested package.jsons and use the full path in the root package.json:

"browser": {
  "./dist/cjs/runtimeConfig": "./dist/cjs/runtimeConfig.browser",
  "./dist/es/runtimeConfig": "./dist/es/runtimeConfig.browser"
}

haoqunjiang avatar Jul 09 '21 15:07 haoqunjiang

@sodatea thank you for the sync up and update on this.

attached the screenshot for reference: Screen Shot 2021-07-09 at 11 40 24 AM


update:

  1. notice that if you upgrade to the latest vite 2.4.1, the nested package.json issue will be solved.
  2. this is because the esbuild used by vite can recognize the nested package.json (during building at pre-bundling stage stage).
  3. even esbuild can recognize the nested package.json, "vite should handle the resolving..to support vite plugin and to be compatible with rollup plugin, so as to ensure the consistency between dev and build"..quoted from sodatea.
  4. related nodejs spec https://nodejs.org/api/packages.html#packages_conditions_definitions

hkjpotato avatar Jul 09 '21 15:07 hkjpotato

Related to https://github.com/aws/aws-sdk-js-v3/issues/2564

ajredniwja avatar Sep 30 '21 10:09 ajredniwja

I don't have a runtimeConfig.js file, what is it? What do I put in it?

chovyprognos avatar Oct 20 '21 23:10 chovyprognos

I'm getting this error:

> 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js

chovyprognos avatar Oct 27 '21 19:10 chovyprognos

Hi @chovyprognos , while this is being worked on, have you tried this work around? IN this documentation. https://ui.docs.amplify.aws/ui/getting-started/installation?platform=vue

ErikCH avatar Oct 27 '21 20:10 ErikCH

I'm having this issue trying to build sveltekit site with vite and aws-amplify @ErikCH thanks for sending that im sure some variation of that is what I'll need for sveltekit.

P.S. I've been watching your youtube for long time so when I come across issues and search only to see you always being a solutions guy two steps ahead of me for aws-amplify issues I'm just like man Erik is a man of the people. Keep it up

24jr avatar Nov 03 '21 09:11 24jr

@24jr Have you tried these three steps mentioned in aws-amplify/amplify-js#9639

This workaround for aws-amplify in SvelteKit has been working for me for sometime now. Let me know if I can help if you're facing any specific issues afterwards.

kaleabmelkie avatar Nov 03 '21 15:11 kaleabmelkie

@kaleabmelkie well that is for vue do you know how I do that in sveltekit? this is what svelte.config.js was by default

/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// hydrate the <div id="svelte"> element in src/app.html
		target: '#svelte'
	}
};

export default config;

then I add the adapter like this

/** @type {import('@sveltejs/kit').Config} */
import adapter from '@sveltejs/adapter-node';

export default {
	kit: {
    target: '#svelte',
		adapter: adapter({
			// default options are shown
			out: 'build',
			precompress: false,
			env: {
				host: 'HOST',
				port: 'PORT'
			},
		})
	}
};

now I need to add the resolve part

/** @type {import('@sveltejs/kit').Config} */
import adapter from '@sveltejs/adapter-node';

export default {
	kit: {
    target: '#svelte',
		adapter: adapter({
			// default options are shown
			out: 'build',
			precompress: false,
			env: {
				host: 'HOST',
				port: 'PORT'
			},
      resolve: {
        alias: {
          './runtimeConfig': './runtimeConfig.browser',
        },
      },
		})
	}
};

this is not working but something like this do you by chance know?

24jr avatar Nov 03 '21 16:11 24jr

The 'resolve' is not meant to be inside the adpater's options. It should be directly inside the 'kit.vite' object.

kaleabmelkie avatar Nov 03 '21 16:11 kaleabmelkie

@24jr Here's how it might look for your config:

import adapter from '@sveltejs/adapter-node'

/** @type {import('@sveltejs/kit').Config} */
export default {
  kit: {
    target: '#svelte',

    adapter: adapter({
      // default options are shown
      out: 'build',
      precompress: false,
      env: {
        host: 'HOST',
        port: 'PORT'
      },
    }),

    vite: {
      resolve: {
        alias: {
          './runtimeConfig': './runtimeConfig.browser',
        },
      },
    },
  },
}

P.S. it should work with any or no svelte adapters. (I've tried it with adapter-static, adapter-vercel & without any adapters).

kaleabmelkie avatar Nov 03 '21 16:11 kaleabmelkie

@kaleabmelkie Wow extremely helpful. I'm not well versed on what adapter is other than that is translates svelte code to a simple clean build of what is actually used. When you say without any adapters is there a built in default and dont need to import others necessarily? Like such? (which still gave 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js )

/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		// hydrate the <div id="svelte"> element in src/app.html
		target: '#svelte'
	},
  vite: {
    resolve: {
      alias: {
        './runtimeConfig': './runtimeConfig.browser',
      },
    },
  },
};

export default config;

Now using adapter-node how you did successfully created the build files however there must be issue with how I'm using amplify-configure getting red 'Amplify.configure is not a function' on completion of build and when run npm run preview

Run npm run preview to preview your production build locally.

> Using @sveltejs/adapter-node
> Amplify.configure is not a function

which I am using in my __layout.svelte file like

<script context="module">
  import "../app.css";
  import Layout from "$lib/views/Layout/index.svelte";
  import Amplify from "aws-amplify";
  import awsExports from "../aws-exports";
  Amplify.configure({ ...awsExports, ssr: true });
  import { initAuth } from "$lib/components/Auth/store";
  initAuth();
</script>

Is that how you did yours? there isnt like a main.js or anything (idk if ssr even doing anything but might be)

24jr avatar Nov 03 '21 18:11 24jr

I used a named Amplify import (instead of the default import) for the 'Amplify.configure is not a function' issue during previews.

See the last part of this comment: aws-amplify/amplify-js#9639

kaleabmelkie avatar Nov 03 '21 22:11 kaleabmelkie

@kaleabmelkie I absolutely appreciate you. Everything is working great. Stay gold

Side note I am having issue building it in aws amplify but that may be diff issue https://github.com/aws-amplify/amplify-console/issues/2318

24jr avatar Nov 04 '21 03:11 24jr

I'm using vite + react + amplify and I'm having the same phenomenon. I tried the script but it didn't improve. Is there an effective solution or workaround?

 <script>
      var global = global || window;
      var Buffer = Buffer || [];
      var process = process || {
        env: { DEBUG: undefined },
        version: []
      };
</script>

reowl666 avatar Nov 11 '21 09:11 reowl666

@yogarasu this is how mine is not sure if will work different than yours

<script>
  // Need this for aws amplify to not give error...idk
	// https://github.com/aws-amplify/amplify-js/issues/7499#issuecomment-804386820
	const isBrowser = () => typeof window !== 'undefined';
	const isGlobal = () => typeof global !== 'undefined';
	var exports = {};
	if (!isGlobal() && isBrowser()) {
		var global = window;
	}
</script>

24jr avatar Nov 12 '21 06:11 24jr

It should not do var exports = {}; It is irrelevant and may cause unknown issues. Only the following will suffice.

<script>
  // Amplify need this to work. See https://github.com/aws/aws-sdk-js/issues/3673
  const isBrowser = () => typeof window !== 'undefined';
  const isGlobal = () => typeof global !== 'undefined';
  if (!isGlobal() && isBrowser()) {
    var global = window;
  }
</script>

jiahao-c avatar Jan 04 '22 04:01 jiahao-c

@ErikCH Hi Erik, thanks for posting this issue, but it seems like the aws-sdk-js team have not had any fixes or updates for a while. Maybe it is because they moved to the new repo https://github.com/aws/aws-sdk-js-v3 . Could you please repost/forward this issue in the new repo, so they can be more aware about this? Thanks so much!

jiahao-c avatar Jan 04 '22 04:01 jiahao-c

Going to a year with this issue? Considering switching to firebase as a much quicker resolution.

eric-2d avatar Jan 18 '22 14:01 eric-2d

I'm getting this error:

> 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js I have the same problem did you manage to solve it ?

youssef-mahdi avatar Feb 07 '22 14:02 youssef-mahdi

This works - Amplify team has the libraries properly switching to the browser context with Webpack, but not with Vite/Rollup.

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import resolve from "@rollup/plugin-node-resolve";
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
    plugins: [
      react(),
      {
        ...resolve({
          preferBuiltins: false,
          browser: true,
        }),
        enforce: 'pre',
        apply: 'build',
      },
      visualizer()
  ],
});

mikhael28 avatar May 19 '22 00:05 mikhael28

I solved this issue thanks to this post: https://stackoverflow.com/questions/70938763/build-problem-with-react-vitejs-and-was-amplify

In vite.config.js add:

resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser',
    },
}

Nizari avatar May 24 '22 09:05 Nizari

https://github.com/nuxt/framework/discussions/2308

mrcego avatar May 25 '22 14:05 mrcego

I solved this issue thanks to this post: https://stackoverflow.com/questions/70938763/build-problem-with-react-vitejs-and-was-amplify

In vite.config.js add:

resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser',
    },
}

Thanks! This is actually what fixed the problem for me.

wcheek avatar Jun 24 '22 01:06 wcheek

Still having the issue even after trying all of the rest of the solutions. I've been using [email protected] (but tried with Vite@latest as well) and React and it appears that Vite and the AWS SDK simply don't work together.

justinfarrelldev avatar Jul 04 '22 05:07 justinfarrelldev

@justinfarrelldev it does... there is something about your config that isn't quite right. Please post your error messages. Delete your .lock files, update your node modules.

mikhael28 avatar Jul 05 '22 17:07 mikhael28

I solved this issue thanks to this post: https://stackoverflow.com/questions/70938763/build-problem-with-react-vitejs-and-was-amplify

Using the full config in this answer also adds the necessary polyfills for Error: AMQJS0010E WebSocket is not supported by this browser. related errors when using the Amplify PubSub library.

elilambnz avatar Jul 28 '22 07:07 elilambnz