Closed sem4phor closed 6 months ago
ping - added feature-request
label so stalebot skips.
Please don't close this ticket without fixing the underlining issue.
I have the same issue as @radiosilence -- looks like there are workarounds for everything except for @aws-amplify/ui-react
. Replacing the authentication UI components isn't in scope for us for now, so we're stuck for the time being.
@mgerring We ended up replacing it (and eventually replacing Amplify), it isn't a hugely horrible thing to do, took us about a day though we don't cover all states. There are a many other reasons other than this ticket to not use @aws-amplify/ui-react
and also Amplify entirely.
The sooner you migrate to a lightweight promise based wrapper around the parts of amazon-cognito-identity-js
you actually need, the sooner your headaches will disappear :)
@radiosilence is amazon-cognito-identity-js
deprecated though, or did it just get moved? I find varying information on it.
Go to my example repo: https://github.com/armenr/amplify-vitesse-repro
Howdy folks! I've got a working setup for aynone that's trying to get @aws-amplify/ui-components
working with VITE + Vue3 - but it's just slightly hacky, and I stumbled upon it TOTALLY by chance.
Wanna give a shout out to @ErikCH for:
alias: {
"./runtimeConfig": "./runtimeConfig.browser"
}
Wanna give another shoutout to @simlevesque for:
import { defineCustomElements } from '@aws-amplify/ui-components/dist/components/index.js';
defineCustomElements(window);
Are you ready kids?! (SpongeBob reference - feel free to disregard).
I am working off of an increasingly popular (and honestly AMAZING) starter template called Vitesse
Why do I love vitesse? (recommend you go to the repo and see the readme for more extensive details)
amplify.yml
file in your repo)vite.config.ts
You need to add the the ./runtimeConfig
alias
resolve: {
alias: {
'~/': `${path.resolve(__dirname, 'src')}/`,
'./runtimeConfig': './runtimeConfig.browser',
},
},
You need to add vue --> template --> compiler options
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('amplify-'),
sourceMap: true,
},
},
Added this, but not sure if it's needed (please help me test if you'd like!):
// In your imports section
import resolve from '@rollup/plugin-node-resolve'
// in your vite defineConfig --> plugins section
resolve({
browser: true,
preferBuiltins: false, // new!
}),
My entire config -->
import path from 'path'
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Markdown from 'vite-plugin-md'
import Pages from 'vite-plugin-pages'
import Prism from 'markdown-it-prism'
import { VitePWA } from 'vite-plugin-pwa'
import WindiCSS from 'vite-plugin-windicss'
import Layouts from 'vite-plugin-vue-layouts'
import resolve from '@rollup/plugin-node-resolve'
import ViteComponents, { HeadlessUiResolver /* PrimeVueResolver */ } from 'vite-plugin-components'
import VueI18n from '@intlify/vite-plugin-vue-i18n'
import ViteIcons, { ViteIconsResolver } from 'vite-plugin-icons'
// @ts-expect-error missing types
import LinkAttributes from 'markdown-it-link-attributes'
const markdownWrapperClasses = 'prose prose-sm m-auto text-left'
// ViteConfig
export default defineConfig({
resolve: {
alias: {
'~/': `${path.resolve(__dirname, 'src')}/`,
'./runtimeConfig': './runtimeConfig.browser',
},
},
// Load plugins
plugins: [
resolve({
browser: true,
preferBuiltins: false, // new!
}),
Vue({
include: [/\.vue$/, /\.md$/],
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('amplify-'),
sourceMap: true,
},
},
}),
// https://github.com/hannoeru/vite-plugin-pages
Pages({
extensions: ['vue', 'md'],
}),
// https://github.com/JohnCampionJr/vite-plugin-vue-layouts
Layouts(),
// https://github.com/antfu/vite-plugin-md
Markdown({
wrapperClasses: markdownWrapperClasses,
headEnabled: true,
markdownItSetup(md) {
// https://prismjs.com/
md.use(Prism)
md.use(LinkAttributes, {
pattern: /^https?:\/\//,
attrs: {
target: '_blank',
rel: 'noopener',
},
})
},
}),
// https://github.com/antfu/vite-plugin-components
ViteComponents({
// allow auto load markdown components under `./src/components/`
extensions: ['vue', 'md'],
// allow auto import and register components used in markdown
customLoaderMatcher: id => id.endsWith('.md'),
// generate `components.d.ts` for ts support with Volar
globalComponentsDeclaration: true,
// auto import icons
customComponentResolvers: [
// PrimeVueResolver(),
HeadlessUiResolver(),
// https://github.com/antfu/vite-plugin-icons
ViteIconsResolver({
componentPrefix: '',
// enabledCollections: ['hero'],
}),
],
}),
// https://github.com/antfu/vite-plugin-icons
ViteIcons(),
// https://github.com/antfu/vite-plugin-windicss
WindiCSS({
safelist: markdownWrapperClasses,
}),
// https://github.com/antfu/vite-plugin-pwa
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['favicon.svg', 'robots.txt', 'safari-pinned-tab.svg'],
manifest: {
name: 'Beep',
short_name: 'BeepBeep',
theme_color: '#ffffff',
icons: [
{
src: '/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: '/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
},
],
},
}),
// https://github.com/intlify/vite-plugin-vue-i18n
VueI18n({
runtimeOnly: true,
compositionOnly: true,
include: [path.resolve(__dirname, 'locales/**')],
}),
],
// Server conifg
server: {
fs: {
strict: true,
},
},
// Build settings
// build: {
// polyfillDynamicImport: true,
// sourcemap: true,
// rollupOptions: {
// shimMissingExports: true,
// output: {
// manualChunks: undefined,
// inlineDynamicImports: true,
// },
// },
// },
// https://github.com/antfu/vite-ssg
ssgOptions: {
script: 'async',
formatting: 'minify',
},
// OptimizeDeps build settings
optimizeDeps: {
include: ['vue', 'vue-router', '@vueuse/core'],
exclude: ['vue-demi'],
},
})
./modules/Amplify.ts
So, in Vitesse, there's a concept of "modules" that is similar to "boot" files in the Quasar framework.
I created a "module" to load up Amplify on App boot, and this is where I use @simlevesque's import workaround
import Amplify from 'aws-amplify'
import {
applyPolyfills,
// defineCustomElements,
} from '@aws-amplify/ui-components/loader'
import { defineCustomElements } from '@aws-amplify/ui-components/dist/components/index'
// @ts-expect-error missing types
import awsmobile from './../aws-exports'
import { UserModule } from '~/types'
export const install: UserModule = async({ app }) => {
// NOTE: "await" might not be doing anything useful here, at all
// TODO: Revisit/refactor this
await Amplify.configure(awsmobile)
await applyPolyfills()
await defineCustomElements(window)
// NOTE: Uncertain if this is necessary
// TODO: Revisit, test, and remove if not necessary
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('amplify-')
}
Once you get THIS far, you'll see three IMPORTANT errors in your console/terminal
@stenciljs/core
missing a require/exportWe install @stencil/core
directly into our project --> pnpm install @stencil/core
zen-observable
missing a default export
pnpm install https://github.com/abdonrd/zen-observable
Here, we're installing a fork for zen-observable directly from a fork on GitHub that has a pending PR that the zen-observable maintainers are ignoring (the PR for this branch is neglected, but it works!)
buffer
libraryAdd package resolution overrides for buffer
in package.json (example covers pnpm and yarn)
"pnpm": {
"overrides": {
"buffer": "^6.0.3"
}
},
"resolutions": {
"buffer": "^6.0.3"
}
rm -rf node_modules
in your project or your monorepo package folderpnpm install
or yarn
or whatever package manager you're using@armenr Awesome! Thanks for the great work around!
@ErikCH and for anyone else who might find it useful --> here's a reproducible sample repo
@armenr I encounter the same issue while trying to use vite + svelte + amplify (for auth), can you/someone hint me towards solving the configuration puzzle there? What is the equivalent to "add vue --> template --> compiler options" in svelte?
Maybe they will fix the issue soon. It looks like they have been working on it. I found this thread in March and have postponed a project because of it.
The best way is to get rid of amplify and roll your own wrapper around amazon-cognito-identity-js
, tbh.
What goes in this runtimeConfig.js file??? I'm using svelte kit.
For @sveltejs/kit@1.0.0-next.190
with typescript@4.4.4
and @amplify/core@4.3.3
(using Node 14), the following steps worked for me.
For dev scripts, add the following to the top of the <head>
tag in app.html:
<script>
var global = global || window
var Buffer = Buffer || []
var process = process || { env: { DEBUG: undefined }, version: [] }
</script>
For builds to succeed, add the following in the config.kit.vite
object of svelte.config.js:
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser',
},
},
And for preview runs, if you face an "Amplify.configure is not a function" error, change Amplify
to a named import:
import { Amplify } from '@aws-amplify/core'
still getting this for me:
> 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
@chovyprognos , if you'd like to check I put an ssr repo for sveltekit + amplify (https://github.com/adnansmajlovic/svk-amplify-ssr), but there's also one for spa there too. I use svk + amplify in production, and all works perfect.
YES!!! I've been stuck on this for days!!! Thanks to @armenr a couple comments up I was able to get things running with just 'aws-amplify' (haven't tried with the components library yet) All i actually needed was to add
export default defineConfig({
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser',
},
},
...
Then i can use aws-amplify and actually have the project build as normal
import Amplify, { Auth } from 'aws-amplify';
...
Amplify.configure(configs)
...
For the record i'm using Vite, React, TS. Bootstrapped the project with the vite react template.
"vite": "2.6.12",
"aws-amplify": "4.3.3"
(now I'm just waiting for something else to go wrong as I progress through adding more functionality with amplify. Hope this helps you all that are struggling)
Nice to hear @RussMax783 . As I started the issue this repository was amplify-js
and not amplify-ui
. Glad to see things improve!
https://github.com/aws/aws-sdk-js/issues/3673 seems to be along similar issues. I too am seeking solutuin for sveltekit + aws-amplify and using I believe the correct "adapter" (new to this part) but as mentioned in the linked issue https://ui.docs.amplify.aws/ui/getting-started/installation?platform=vue seams to have a soltution for vite in vue but of course svelte has its own way of doing this. Does anyone know the "translation" of this to sveltekit?
I have in my app.html
<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>
which seems equivalent to their recommended vue index.html of
<script>
window.global = window;
var exports = {};
</script>
Next the config. I have in my svelte.config.js which i added adapter-node (which again im new to) https://github.com/sveltejs/kit/tree/master/packages/adapter-node
/** @type {import('@sveltejs/kit').Config} */
// const config = {
// kit: {
// // hydrate the <div id="svelte"> element in src/app.html
// target: '#svelte'
// }
// };
// export default 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'
}
})
}
};
The amplify fixes for vue vite say make vite.config.ts
export default defineConfig({
plugins: [vue()],
resolve: {
alias: [
{
find: './runtimeConfig',
replacement: './runtimeConfig.browser',
},
]
}
})
I'm not sure what the translation to svelte.config.js would be
Then lastly they add to tsconfig.json
...
"compilerOptions": {
"skipLibCheck": true,
...
Appreciate all help and people that have figured this stuff out thus far
YES!!! I've been stuck on this for days!!! Thanks to @armenr a couple comments up I was able to get things running with just 'aws-amplify' (haven't tried with the components library yet) All i actually needed was to add
export default defineConfig({ resolve: { alias: { './runtimeConfig': './runtimeConfig.browser', }, }, ...
Then i can use aws-amplify and actually have the project build as normal
import Amplify, { Auth } from 'aws-amplify'; ... Amplify.configure(configs) ...
For the record i'm using Vite, React, TS. Bootstrapped the project with the vite react template.
"vite": "2.6.12",
"aws-amplify": "4.3.3"
(now I'm just waiting for something else to go wrong as I progress through adding more functionality with amplify. Hope this helps you all that are struggling)
Thank you, work for me
Unfortunately this didn't work for me, but this slight hack did...
try {
Amplify.configure(cfg);
} catch (e) {
// did it error because node defaults were used?
if (e.name == "TypeError") {
// @ts-ignore
Amplify.default.configure(cfg);
} else {
throw e;
}
}
I've been fighting this one for a few days and finally got it to work. This is what worked for me for vite and react.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import resolve from '@rollup/plugin-node-resolve'
export default defineConfig({
plugins: [
react(),
{
...resolve({
preferBuiltins: false,
browser: true,
}),
enforce: 'pre',
apply: 'build',
},
],
})
@armenr solution worked for me with Vite + React + Amplify, updating index.html & vite.config.js with below
<script> if (global === undefined) { var global = window; } </script>
resolve: { alias: { './runtimeConfig': './runtimeConfig.browser' } }
@armenr solution worked for me with Vite + React + Amplify, updating index.html & vite.config.js with below
<script> if (global === undefined) { var global = window; } </script>
resolve: { alias: { './runtimeConfig': './runtimeConfig.browser' } }
This solution also works in SvelteKit as well. Adding the resolve
bit to the svelte.config.js
file and adding the <script>
tag to the app.html
file (above all your other files) fixed everything!
svelte.config.js
import adapter from '@sveltejs/adapter-auto';
const config = {
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser',
},
},
kit: {
adapter: adapter()
}
};
export default config;
and the app.html
file
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" href="%svelte.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
// This is required for AWS Amplify
if (global === undefined) {
var global = window;
}
</script>
<!-- ... All your other standard svelte stuff here -->
</head>
And depending on your specific setup, don't forget to add your aws-exports.js
file. Mine looks like this:
const urlBase = "https://www.your-domain.com";
const hostname = "your-domain.com";
const awsconfig = {
aws_project_region: "region",
aws_cognito_region: "region",
aws_user_pools_id: "user-pool-id",
aws_user_pools_web_client_id: "cliend-id",
oauth: {
domain: "domain",
scope: ["email", "openid", "aws.cognito.signin.user.admin"],
redirectSignIn: `${urlBase}/`,
redirectSignOut: `${urlBase}/login`,
responseType: "code",
client_id: "client-id",
},
cookieStorage: {
domain: hostname,
secure: false,
path: "/",
expires: 0.0416, // one hour (in fractions of a day)
},
};
export default awsconfig;
and then in my __layout.svelte
file, I added:
import Amplify, { Auth } from 'aws-amplify';
import awsconfig from '$lib/aws-exports';
Amplify.configure(awsconfig);
This works fine locally. I'm able to log in, log out, do all that fun stuff.
When I go to build the Sveltekit project with npm run build
, I get this error:
✓ 1974 modules transformed.
'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
file: C:/project.../node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js:4:9
2: import { ProviderError } from "@aws-sdk/property-provider";
3: import { Buffer } from "buffer";
4: import { request } from "http";
^
5: /**
6: * @internal
> 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
at error (C:\project...\node_modules\rollup\dist\shared\rollup.js:198:30)
at Module.error (C:\project...\node_modules\rollup\dist\shared\rollup.js:12477:16)
at Module.traceVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:12835:29)
at ModuleScope.findVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:11465:39)
at FunctionScope.findVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:6433:38)
at ChildScope.findVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:6433:38)
at FunctionScope.findVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:6433:38)
at ChildScope.findVariable (C:\project...\node_modules\rollup\dist\shared\rollup.js:6433:38)
at Identifier.bind (C:\project...\node_modules\rollup\dist\shared\rollup.js:7724:40)
at CallExpression.bind (C:\project...\node_modules\rollup\dist\shared\rollup.js:5298:23)
Got it works in
@sveltejs/kit
1.0.0-next.355
aws-amplify
4.3.26
@aws-sdk/client-cognito-identity
3.118.1
By putting this in app.html
<script>
const isBrowser = () => typeof window !== 'undefined';
const isGlobal = () => typeof global !== 'undefined';
if (!isGlobal() && isBrowser()) {
var global = window;
}
</script>
And svelte.config.js
import adapter from '@sveltejs/adapter-cloudflare';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: preprocess({
postcss: true
}),
kit: {
adapter: adapter(),
floc: true,
alias: {
$assets: 'src/assets',
$components: 'src/components',
$pages: 'src/pages',
$routes: 'src/routes',
$stores: 'src/stores'
},
vite: {
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser'
}
}
}
}
};
export default config;
In __layout.svelte
<script lang="ts">
import '../app.css';
import NavigationBar from '$components/NavigationBar.svelte';
import { onMount } from 'svelte';
import { Auth } from 'aws-amplify';
import { IdentityPoolId, Region, UserPoolId, UserPoolWebClientId } from '$stores/constants';
onMount(async () => {
Auth.configure({
identityPoolId: IdentityPoolId,
userPoolId: UserPoolId,
userPoolWebClientId: UserPoolWebClientId,
region: Region,
identityPoolRegion: Region
});
const creds = await Auth.currentCredentials();
console.log('creds', creds);
});
</script>
Confirmed it can npm run dev
, npm run build
and deploy on CloudFlare Pages without an issue.
You need to have @aws-sdk/client-cognito-identity
installed along with aws-amplify
else it will have issues like Could not resolve "@aws-sdk/protocol-http"....
etc.
I was also getting error:
'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
I am using Vite + React + Amplify
I was abe to do a build and publish the site, however, When loading the site I get the following error in the browser:
Uncaught TypeError: Cannot read properties of undefined (reading 'memoizedProperty') at index.6c2d94c0.js:2603:8441
I don't get this error in development.
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import nodeResolve from '@rollup/plugin-node-resolve'
import json from '@rollup/plugin-json'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser'
}
},
build: {
rollupOptions: {
plugins: [
nodeResolve({
browser: true,
preferBuiltins: false
}),
json()
]
}
}
})
I do use aws-sdk-v3 packages within the project. Not sure what is causing the memoizedProperty
error
Do we have a proper solution two years after? Its probably causing lot of projects to reject AWS Cognito (potentially also other AWS services) from tech stack.
@paragvk - doesn't look like it, yet. But I did post a way to work around it, discussed above ^^^
It seems to have worked/keep working for a number of people.
Running into this issue with Nuxt 3, creating my own plugin (client-only) to use AppSync:
import { Amplify, API } from 'aws-amplify';
export default defineNuxtPlugin(() => {
const {
public: {
awsRegion,
graphqlEndpoint,
identityPoolId,
userPoolId,
userPoolClientId,
},
} = useRuntimeConfig();
Amplify.configure({
aws_appsync_graphqlEndpoint: graphqlEndpoint,
aws_appsync_region: awsRegion,
aws_appsync_authenticationType: 'AWS_IAM',
Auth: {
identityPoolId,
region: awsRegion,
userPoolId,
userPoolWebClientId: userPoolClientId,
mandatorySignIn: false,
},
});
return {
provide: { API },
};
});
Build output:
Nuxt CLI v3.0.0-rc.4 18:43:56
ℹ Vite client warmed up in 5594ms 18:44:04
ERROR 'request' is not exported by __vite-browser-external, imported by nuxt/node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js
file: /Volumes/SuperData/Sites/reelcrafter/v2-presentation-nuxt3/nuxt/node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js:4:9
2: import { ProviderError } from "@aws-sdk/property-provider";
3: import { Buffer } from "buffer";
4: import { request } from "http";
^
5: /**
6: * @internal
For my Svelte/Vite build none of the above work-arounds actually worked, but replacing import with require/assign does (and yes, a node resolve is already built-in to vite, so no need for the additional plugin):
// import Amplify from 'aws-amplify';
// import { API, graphqlOperation } from "aws-amplify";
const awsAmplify = require('aws-amplify');
const Amplify = awsAmplify.default;
const API = awsAmplify.API;
const graphqlOperation = awsAmplify.graphqlOperation;
For my Svelte/Vite build ...
Yeah, npm run dev
AND npm run build
works, but if I try to serve the static build assets I get an error in the browser, so it's a no-go:
Uncaught ReferenceError: require is not defined <anonymous> http://localhost:5000/assets/index.67fd2eab.js:24
[index.67fd2eab.js:24:6](http://localhost:5000/assets/index.67fd2eab.js)
<anonymous> http://localhost:5000/assets/index.67fd2eab.js:24
InnerModuleEvaluation self-hosted:2361
evaluation self-hosted:2322
This is definitely the problem...
I have determined that the following modules cause build errors related to expecting various node js modules in the browser such as
http
andfs
.'@aws-sdk/credential-provider-imds', '@aws-sdk/credential-provider-process', '@aws-sdk/shared-ini-file-loader', '@aws-sdk/eventstream-serde-node', '@aws-sdk/hash-node', '@aws-sdk/node-http-handler', '@aws-sdk/util-body-length-node', '@aws-sdk/util-user-agent-node',
Hopefully the aws-sdk team jumps on this in the nearish future!
Thank you @armenr.
For my Svelte/Vite build ... ...
Uncaught ReferenceError: require is not defined <anonymous> http://localhost:5000/assets/index.67fd2eab.js:24 ...
I'm hitting this same issue of unresolved references to "require", even when there are no such references in my source code, whenever I use import
to include aws-amplify
or directly include a specific @aws-sdk
library (i.e., import { API } from '@aws-amplify/api/lib-esm'
) in main.jsx
/main.js
(React/Svelte respectively), even when I include this in my vite.config.js
file:
resolve: {
alias: [
// {
// find: '@', replacement: resolve(__dirname, './src'),
// },
{
find: './runtimeConfig', replacement: './runtimeConfig.browser',
}
]
}
^ That helps npm run build
to complete, but does not resolve the mechanisms to require
non-ESM dependencies that are buried in the various @aws-sdk/...
libraries.
So, I personally have not successfully implemented any of the work-arounds above (including my own) for compiling/transpiling the npm version of aws-amplify
into the js bundle output by Vite, but I have discovered that there is way to integrate the CDN version of the library that is included in the npm package (node_modules/aws-amplify/dist/aws-amplify[.min].js
).
Here are the relevant fragments from my configuration and source code files....
package.json:
"dependencies": {
"@aws-amplify/cli": "^9.1.0",
"aws-amplify": "^4.3.29",
"react": "^18.2.0",
"react-dom": "^18.2.0",
...
},
"devDependencies": {
"@guanghechen/rollup-plugin-copy": "^1.9.8",
"@rollup/plugin-node-resolve": "^13.3.0",
"@vitejs/plugin-react": "^2.0.0",
"@vitejs/plugin-react-refresh": "^1.3.6",
...
"vite": "^3.0.4"
},
vite.config.js:
import { defineConfig } from 'vite';
import copy from '@guanghechen/rollup-plugin-copy';
import nodeResolve from '@rollup/plugin-node-resolve';
import react from '@vitejs/plugin-react';
...
// https://vitejs.dev/config/
export default defineConfig({
external: [ 'aws_amplify', 'Buffer', 'CustomEvent' ],
...
plugins: [
...
copy({
hook: 'buildStart',
targets: [
{ src: [ './node_modules/aws-amplify/dist/aws-*' ], dest: 'public/' }
]
}),
nodeResolve({
browser: true,
preferBuiltins: false,
// dedupe: importee =>
// importee === 'svelte' || importee.startsWith('svelte/')
}),
react(), // svelte()
]
})
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
...
<script src="/aws-amplify.min.js" ></script>
<script>
const isBrowser = () => typeof window !== 'undefined';
const isGlobal = () => typeof global !== 'undefined';
if (!isGlobal() && isBrowser()) {
var global = window;
}
</script>
</head>
<body>
...
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
main.jsx:
import aws_exports from "./aws-exports";
...
// import Amplify from '@aws-amplify/core/lib-esm'; // <- DOES NOT RESOLVE require()
// import { API, graphqlOperation } from '@aws-amplify/api/lib-esm'; // <- DOES NOT RESOLVE require()
// const aws_amplify = require('@aws-amplify/core/src'); // <- DOES NOT RESOLVE require()
const Amplify = aws_amplify.default; // aws_amplify is now a global var
const API = aws_amplify.API;
const graphqlOperation = aws_amplify.graphqlOperation;
Amplify.configure(aws_exports);
...
Hey all, I don't know if this helps, but I paid someone to come up with a solution so that AWS Amplify would work within Nuxt 3 (which uses Vite under the hood).
This is the code he wrote. This is way over my head, but it looks like it's a custom Vite plugin. BTW, this is just a workaround until AWS fixes stuff on their end. I've talked with the Amplify team, and they fully intend to update their SDK to use some of the more modern features of Node.js like import/export maps, and using proper ESM, which will fix these issues.
import { pathToFileURL } from 'url';
import { defineNuxtModule } from '@nuxt/kit';
import { parseURL } from 'ufo';
import { dirname, join } from 'pathe';
export default defineNuxtModule({
meta: {
name: 'nuxt-amplify',
},
setup(_options, nuxt) {
nuxt.options.build.transpile.push(
'aws-amplify',
/@aws-sdk/,
/@aws-amplify/,
);
nuxt.hook('vite:extendConfig', (config, { isClient }) => {
if (!isClient) return;
config.plugins = config.plugins || [];
config.plugins.push({
name: 'nuxt:aws-browser',
enforce: 'pre',
resolveId(id, importer) {
if (
!importer ||
!importer.includes('node_modules') ||
!importer.includes('aws')
) {
return;
}
const path = isRelative(id) ? join(dirname(importer), id) : id;
const { pathname, search } = parseURL(
decodeURIComponent(pathToFileURL(path).href),
);
if (pathname.endsWith('runtimeConfig') && !id.includes('browser')) {
return pathname + '.browser.js' + search;
}
},
});
});
},
});
const IS_RELATIVE_RE = /^\.{1,2}\//;
function isRelative(id: string) {
return IS_RELATIVE_RE.test(id);
}
@dancingfrog Thanks for that solution, it is working for me for vite build
, however for local dev there is a console error thrown Uncaught ReferenceError: aws_amplify is not defined
. Did you get it to work for your dev server?
Edit: disregard my question, it was due to outDir being set to "../dist" and not having access to the upper folder in dev mode
@emmmarosewalker
I think that means that the dev server is not sourcing aws-amplify.min.js
from your public
folder, so can you confirm that the file that you reference in index.html
is present in public
?
On another note, the resolve: { alias: [ ... ] }
work-around is now working for me because I changed the structure and versions of dependencies that I am pulling in via package.json
, after reading these issues about the recurring conflicts between the monolithic aws-amplify
package and the various @aws-amplify/...
modular packages (essentially we need to choose to depend on one or the other, not both): #2885 #7619. So, I dropped the CDN version of aws-amplify from index.html
/public
and I'm currently using this (modular + working) setup...
package.json:
...
"dependencies": {
"aws-amplify-react": "~5.1.9",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@aws-amplify/analytics": "~3.3.11",
"@aws-amplify/api": "~3.3.3",
"@aws-amplify/api-graphql": "~1.3.3",
"@aws-amplify/api-rest": "~1.2.34",
"@aws-amplify/auth": "~3.4.34",
"@aws-amplify/cache": "~4.0.50",
"@aws-amplify/core": "~3.8.24",
"@aws-amplify/interactions": "~3.3.34",
"@aws-amplify/storage": "~3.4.4",
"@aws-amplify/ui": "~2.0.5",
"@aws-amplify/ui-components": "~1.7.2",
"@aws-amplify/ui-react": "~2.20.0",
"@aws-amplify/xr": "~2.2.34",
"@aws-sdk/credential-provider-cognito-identity": "^3.145.0",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.0.0",
"esbuild": "^0.14.54",
"vite": "^3.0.0"
},
...
(... most of the @aws-amplify/...
modules included are dependencies of aws-amplify-react
and/or @aws-amplify/ui-react
; as you will see I am using React components from aws-amplify-react
and only importing styles from @aws-amplify/ui-react
)
vite.config.js:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
// set external namespaces to help `npm run build` succeed
external: [
'aws_amplify', 'aws_amplify_core', 'aws_amplify_react', 'Buffer', 'CustomEvent'
],
plugins: [
react()
],
resolve: {
alias: [
// {
// find: '@', replacement: resolve(__dirname, './src'), // <- just to illustrate how to set multiple alias entries
// },
{
find: './runtimeConfig', replacement: './runtimeConfig.browser',
}
]
}
});
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<script>
const isBrowser = () => typeof window !== 'undefined';
const isGlobal = () => typeof global !== 'undefined';
if (!isGlobal() && isBrowser()) {
var global = window;
var root = window;
}
</script>
</head>
<body>
<div id="app"></div>
<script src="/src/main.jsx" type="module"></script>
</body>
</html>
main.jsx:
...
//import aws_exports from "./aws-exports";
import aws_config from "./aws-config"; // <- using a custom config (committed to git)
// instead of auto-generated aws-exports.js; not
// necessary for this work-around, just noting this
import * as aws_amplify_core from "@aws-amplify/core";
const Amplify = aws_amplify_core.Amplify;
Amplify.configure(aws_config);
...
App.jsx:
...
import '@aws-amplify/ui-react/styles.css';
import * as aws_amplify_react from "aws-amplify-react";
import { Auth } from "@aws-amplify/auth";
import { AuthState } from '@aws-amplify/ui-components';
const Authenticator = aws_amplify_react.Authenticator;
const SignIn = aws_amplify_react.SignIn;
const SignOut = aws_amplify_react.SignOut; //... .etc
...
... I'm importing and initializing the Amplify
singleton object in the top-level main.jsx
and subsequently using the modular dependencies/resources in App.jsx
and child components. Now I can use <Authenticator />
from aws-amplify-react
in my custom React component.
NOTE: <Authenticator />
has significant differences from the equivalent component in @aws-amplify/ui-react
and while I would rather use the latter, more recent component, npm run build
will not succeed if I use it. For help with the aws-amplify-react
implementation alongside Auth
/AuthState
from @aws-amplify/auth
/@aws-amplify/ui-components
, see https://vaibhavsethia1998.medium.com/creating-a-custom-authenticator-using-aws-amplify-cognito-and-react-js-60f24d1c84aa
Polyfilling node APIs worked for me.
Rollup plugin mentioned here might be worth looking at.
Since this is still not resolved here are a few tips:
As others already mentioned, you can fix these errors by adding the following config to vite.config.js
define: {
global: {}, //fix dev build
},
resolve: {
alias: {
"./runtimeConfig": "./runtimeConfig.browser", //fix production build
},
},
The above configuration will FAIL if you're using React Router 6.4 data API.
import {createBrowserRouter, RouterProvider} from "react-router-dom";
const router = createBrowserRouter([
{
index: true,
element: <Landing />,
}
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
You will have to stick to using React Router components.
<BrowserRouter>
<Routes>
<Route index element={<Landing />} />
</Routes>
</BrowserRouter>
Hope this helps some poor soul. God knows how much time I wasted figuring this out.
We are working on removing the need for these manual configurations on Amplify, for now - for Vite customers can you try the workaround mentioned in this comment to see if that resolves build issues for you? https://github.com/kevinold/repro-vite-amplify/commit/4d6b42291dbbcc9cee08f0ec52b416efd5ed7145
We are working on removing the need for these manual configurations on Amplify, for now - for Vite customers can you try the workaround mentioned in this comment to see if that resolves build issues for you? kevinold/repro-vite-amplify@4d6b422
I confirm this works in Sveltekit with '@aws-amplify/api', '@aws-amplify/auth', '@aws-amplify/core' 🙏🏼
@abdallahshaban557 Yes this worked for me with aws-amplify 3.3.7, i.e., quite an old version.
We are working on removing the need for these manual configurations on Amplify, for now - for Vite customers can you try the workaround mentioned in this comment to see if that resolves build issues for you? kevinold/repro-vite-amplify@4d6b422
To say that this is annoying would be an understatement.
This is a horrible developer experience. The least you could do is make this lack of integration support known up front so we don't waste our time on another amplify product.
@pedersenderekserif - we understand this is not ideal, and are actively working on removing the need for additional configurations when using our library. We have also enriched our documentation with the steps you would need to get started with a Vue/Vite project.
I am facing a similar issue right now, this time actually caused by the use of CryptoJS.
'default' is not exported by node_modules/crypto-js/core.js, imported by node_modules/amazon-cognito-identity-js/es/AuthenticationHelper.js
file: C:/Users/...../node_modules/amazon-cognito-identity-js/es/AuthenticationHelper.js:7:7
5:
6: import { Buffer } from 'buffer';
7: import CryptoJS from 'crypto-js/core';
^
8: import 'crypto-js/lib-typedarrays'; // necessary for crypto js
9: import SHA256 from 'crypto-js/sha256';
My vite config is pretty wild righ tnow as I'm trying to convert from CRA to vite and had to get around a bunch of issues. Running the dev server works, the prod build fails. It seems like it has something to do with amplify.
// eslint-disable-next-line import/no-extraneous-dependencies
import { defineConfig } from 'vite';
// eslint-disable-next-line import/no-extraneous-dependencies
import react from '@vitejs/plugin-react';
import envCompatible from 'vite-plugin-env-compatible';
import copy from 'rollup-plugin-copy';
import rollupNodePolyFill from 'rollup-plugin-node-polyfills';
// npm i --save-dev @esbuild-plugins/node-globals-polyfill
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
// yarn add --dev @esbuild-plugins/node-modules-polyfill
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';
import * as _path from 'path';
import nodePolyfills from 'vite-plugin-node-stdlib-browser';
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default defineConfig((env) => {
const { mode } = env;
/**
* Fix build messages/errors like: `'useState' is not exported by 'node_modules/react/index.js'`
*/
let pathReact = 'umd/react.production.min.js';
let pathReactDom = 'umd/react-dom.production.min.js';
let pathReactJsx = 'cjs/react-jsx-runtime.production.min.js';
if (mode === 'development') {
pathReact = 'umd/react.development.js';
pathReactDom = 'umd/react-dom.development.js';
pathReactJsx = 'cjs/react-jsx-dev-runtime.development.js';
}
return {
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis',
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
process: true,
buffer: true,
}),
],
},
},
resolve: {
alias: [
{
util: 'rollup-plugin-node-polyfills/polyfills/util',
sys: 'util',
events: 'rollup-plugin-node-polyfills/polyfills/events',
stream: 'rollup-plugin-node-polyfills/polyfills/stream',
path: 'rollup-plugin-node-polyfills/polyfills/path',
querystring: 'rollup-plugin-node-polyfills/polyfills/qs',
punycode: 'rollup-plugin-node-polyfills/polyfills/punycode',
url: 'rollup-plugin-node-polyfills/polyfills/url',
string_decoder:
'rollup-plugin-node-polyfills/polyfills/string-decoder',
http: 'rollup-plugin-node-polyfills/polyfills/http',
https: 'rollup-plugin-node-polyfills/polyfills/http',
os: 'rollup-plugin-node-polyfills/polyfills/os',
assert: 'rollup-plugin-node-polyfills/polyfills/assert',
constants: 'rollup-plugin-node-polyfills/polyfills/constants',
_stream_duplex:
'rollup-plugin-node-polyfills/polyfills/readable-stream/duplex',
_stream_passthrough:
'rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough',
_stream_readable:
'rollup-plugin-node-polyfills/polyfills/readable-stream/readable',
_stream_writable:
'rollup-plugin-node-polyfills/polyfills/readable-stream/writable',
_stream_transform:
'rollup-plugin-node-polyfills/polyfills/readable-stream/transform',
timers: 'rollup-plugin-node-polyfills/polyfills/timers',
console: 'rollup-plugin-node-polyfills/polyfills/console',
vm: 'rollup-plugin-node-polyfills/polyfills/vm',
zlib: 'rollup-plugin-node-polyfills/polyfills/zlib',
tty: 'rollup-plugin-node-polyfills/polyfills/tty',
domain: 'rollup-plugin-node-polyfills/polyfills/domain',
find: 'common',
replacement: _path.resolve(__dirname, './src/common'),
},
// react alias fix
{
find: /^react$/,
replacement: require.resolve(_path.join('react', pathReact)),
},
{
find: /^react-dom$/,
replacement: require.resolve(_path.join('react-dom', pathReactDom)),
},
{
/*
2022-03-11
https://github.com/vitejs/vite/issues/6215#issuecomment-1064247764
*/
find: /react\/jsx-runtime/,
replacement: require.resolve(_path.join('react', pathReactJsx)),
},
// End react alias fix
{
find: './runtimeConfig', //amplify fix
replacement: './runtimeConfig.browser',
},
],
},
envPrefix: 'REACT_APP_',
plugins: [react(), rollupNodePolyFill(), nodePolyfills(), nodeResolve({
browser: true,
preferBuiltins: false,
})],
});
Maybe someone here has an idea about that?
@mkilp, I just went through the same path of converting from CRA to Vite. Same issues, dev worked, production build crashed with error about Crypto. I also tried some of the various npm poly fill packages I see that you have as well.
I ended up doing a clean Vite install with a new amplify project and moved my project over piece by piece. Then copied the vite.config.js back to my original project. Below is my vite.config.js file. It turned out to be much simpler setup than all the various things I tried. I think that a lot of the poly fill packages were used for earlier versions of vite/amplify and are no longer needed. (I think, not sure about that)
Note: the setupTests.js file in the test section @imports testing-library/jest-dom for vitest.
And I also, deleted npm_modules and the package-lock.json file to make sure the setup was clean as possible. I had other issues from the package-lock.json file so I don't know if it effected the vite config.
It has been working fine for about a mouth with several deploys to production. Although it was so much more work than I expected, I am happy I did it.
Hope this will help.
Regards,
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import rollupNodePolyFill from "rollup-plugin-node-polyfills";
// https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], define: { 'process.env': {} }, optimizeDeps: { esbuildOptions: { // Node.js global to browser globalThis define: { global: "globalThis", //<-- AWS SDK }, }, }, build: { rollupOptions: { plugins: [ // Enable rollup polyfills plugin // used during production bundling rollupNodePolyFill(), ], }, }, test: { globals: true, setupFiles: 'setupTests.js', }, resolve: { alias: { './runtimeConfig': './runtimeConfig.browser', // <-- Fix from above }, } })
@mkilp, I just went through the same path of converting from CRA to Vite. Same issues, dev worked, production build crashed with error about Crypto. I also tried some of the various npm poly fill packages I see that you have as well.
Regards,
vite.config.js
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import rollupNodePolyFill from "rollup-plugin-node-polyfills";
// https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], define: { 'process.env': {} }, optimizeDeps: { esbuildOptions: { // Node.js global to browser globalThis define: { global: "globalThis", //<-- AWS SDK }, }, }, build: { rollupOptions: { plugins: [ // Enable rollup polyfills plugin // used during production bundling rollupNodePolyFill(), ], }, }, test: { globals: true, setupFiles: 'setupTests.js', }, resolve: { alias: { './runtimeConfig': './runtimeConfig.browser', // <-- Fix from above }, } })
@bregan Thanks alot for your help! Like you said i started from scratch and am now stuck with react-cookies being weird. But that has nothing to do with amplify. I hope AWS can solve this soon natively without an alias.
configuring like this worked for me.
vite.config.js
export default defineConfig({ plugins: [vue()], resolve: { alias: { "./runtimeConfig": "./runtimeConfig.browser", //fix production build } } })
Similar thing worked for me. I am using Nuxt3:
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
resolve: {
alias: {
"./runtimeConfig": "./runtimeConfig.browser", //fix production build
}
}
}
})
We are working on removing the need for these manual configurations on Amplify, for now - for Vite customers can you try the workaround mentioned in this comment to see if that resolves build issues for you? kevinold/repro-vite-amplify@4d6b422
Thanks! this helped, here's my vite.config.vue
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
define: {
global: {},
},
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
"./runtimeConfig": "./runtimeConfig.browser",
},
},
});
For anyone using Vue 3 + Vitest, you'll need a conditional for that global definition, otherwise Vitest will break. This is my full Vite config:
/// <reference types="vitest" />
import { fileURLToPath, URL } from 'node:url';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vuetify from 'vite-plugin-vuetify';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vuetify()],
...(process.env.NODE_ENV !== 'test'
? {
define: {
global: {},
},
}
: {}),
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
test: {
deps: {
inline: ['vuetify'],
},
environment: 'jsdom',
include: ['**/*.spec.ts'],
},
});
I had to update my Vite config to the following to get both build time & dev working (only the relevant parts of the config are included):
export default defineConfig({
...(process.env.NODE_ENV === 'development'
? {
define: {
global: {},
},
}
: {}),
resolve: {
alias: {
...(process.env.NODE_ENV !== 'development'
? {
'./runtimeConfig': './runtimeConfig.browser', //fix production build
}
: {}),
},
},
});
Describe the bug
The package aws-amplify is meant to be used in the browser, isnt it? Therefore it should not rely on node builtins, which sadly is the case and prevents the usage of this package in many js build tools like rollup, snowpack or vitejs.
The @aws-sdk package which is used by aws-amplify relies on various node build in modules like fs, process or http2, ....
I described the issue also here (https://github.com/vitejs/vite/issues/1374) and Evan You the creator of vuejs and vite mentioned that webpack will drop support for node build ins in version five. Because webpack is used by tools such as create-react-app and vue-cli this will block many developers from using the amplify package soon I think!
To Reproduce Steps to reproduce the behavior:
Expected behavior The package works in the browser and does not import any node build ins which are not available in browser environment.
Code Snippet https://github.com/sem4phor/aws-cli-bug
Screenshots
What is Configured? Not relevant for this error.