aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.11k forks source link

Cannot use amplify-js in browser environment (breaking vite / snowpack / esbuild) #9639

Closed sem4phor closed 6 months ago

sem4phor commented 3 years ago

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:

  1. Download https://github.com/sem4phor/aws-cli-bug
  2. Run npm run dev (node required)
  3. See error in console

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

[plugin:vite:imports] Failed to resolve import "process". Does the file exist?
/Users/XXXXX/node_modules/@aws-sdk/util-user-agent-node/dist/es/index.js:1:22
1  |  import process from "process";
   |                       ^
2  |  export function defaultUserAgent(packageName, packageVersion) {
3  |      var engine = process.platform + "/" + process.version;
Error: Failed to resolve import "process". Does the file exist?
    at TransformContext.error (C:\Users\XXXXX\node_modules\vite\dist\node\chunks\dep-262f13eb.js:59552:50)
    at TransformContext.transform (C:\XXXXX\node_modules\vite\dist\node\chunks\dep-262f13eb.js:52957:30)
    at async Object.transform (C:\Users\XXXXX\node_modules\vite\dist\node\chunks\dep-262f13eb.js:59742:30)
    at async transformRequest (C:\Users\XXXXX\node_modules\vite\dist\node\chunks\dep-262f13eb.js:65977:29)
    at async C:\Users\XXXXX\node_modules\vite\dist\node\chunks\dep-262f13eb.js:66068:32

What is Configured? Not relevant for this error.

jonasgroendahl commented 1 year ago

I got it working using this:

export default defineConfig(({ command }) => ({
  plugins: [react()],
  server: {
    port: 3000,
  },
  define:
    // in development, amplifyjs relies on webpack or similiar somewhere so we need to add this for now
    command === 'serve'
      ? {
          global: {},
        }
      : undefined,
  // there's an issue with vite and amplifyjs that requires the following below (https://github.com/aws-amplify/amplify-js/issues/9639)
  resolve: {
    alias: {
      './runtimeConfig': './runtimeConfig.browser', //fix production build
    },
  },
}));

Not sure what is best approach here

bilal-korir commented 1 year ago

This solution worked for me. In case you're using Astro, which uses Vite, edit astro.config.mjs as follows:

import {defineConfig} from 'astro/config'
import rollupNodePolyFill from 'rollup-plugin-node-polyfills'
import react from '@astrojs/react'
import tailwind from '@astrojs/tailwind'
import {Amplify} from 'aws-amplify'
import awsExports from './src/aws-exports.cjs'

Amplify.configure(awsExports)

export default defineConfig({
  integrations: [react(), tailwind()],
  vite: {
    optimizeDeps: {
      esbuildOptions: {
        define: {
          global: 'globalThis',
        },
      },
    },
    build: {
      rollupOptions: {
        plugins: [rollupNodePolyFill()],
      },
    },
    resolve: {
      alias: {
        './runtimeConfig': './runtimeConfig.browser',
      },
    },
  },
}) 

Orginal answer can be found here

zhangyuezhong commented 1 year ago

npm install --save-dev rollup-plugin-polyfill-node vite.config.js


import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import nodePolyfills from "rollup-plugin-polyfill-node";
export default defineConfig({
  plugins: [react()],

  define: {
    global: {},
  },
  resolve: {
    alias: {
      "./runtimeConfig": "./runtimeConfig.browser",
    },
  },
  build: {
    rollupOptions: {
      plugins: [nodePolyfills()],
    },
  },
});
samputer commented 1 year ago

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
        }
        : {}),
    },
  },
});

I got both dev and prod builds working with @ffxsam 's solution - thanks!

My whole vite.config.ts (with Vuetify):

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath } from 'url'
import vuetify from 'vite-plugin-vuetify'

// https://vitejs.dev/config/
export default defineConfig({
  ...(process.env.NODE_ENV === 'development'
    ? {
      define: {
        global: {},
      },
    }
    : {}),
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
      ...(process.env.NODE_ENV !== 'development'
        ? {
          './runtimeConfig': './runtimeConfig.browser', //fix production build
        }
        : {}),
    },
  },
  plugins: [vue(), vuetify({ autoImport: true })],
})
tumus2004 commented 1 year ago

I also have this issue but with Vite + Preact + Amplify

my config:

import commonjs from '@rollup/plugin-commonjs';
import rollupNodePolyFill from 'rollup-plugin-node-polyfills';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';
import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';

export default defineConfig({
    plugins: [preact()],
    root: './',
    publicDir: 'src',
    build: {
        outDir: 'dist',
        emptyOutDir: false,
        assetsDir: '',
        copyPublicDir: false,
        manifest: false,
        // Need to use the CommonJS plugin to correctly bundle all imports in a single import.
        rollupOptions: {
            plugins: [commonjs(), vanillaExtractPlugin(), rollupNodePolyFill()],
            input: 'src/v1/instant-woocommerce.js', // <--- don't worry about this, using for specific merchant configs due to an issue documented here: 
            output: [
                {
                    format: 'iife',
                    dir: 'dist',
                    entryFileNames: 'v1/[name].min.js', // make this "[name][hash].js" to include the hash
                },
            ],
        },
    },
    resolve: {
        alias: {
            './runtimeConfig': './runtimeConfig.browser', // <--- Attempted fix as above
            react: 'preact/compat', // <--- Preact specific
            'react-dom/test-utils': 'preact/test-utils', // <--- Preact specific
            'react-dom': 'preact/compat', // Must be below test-utils // <--- Preact specific
            'react/jsx-runtime': 'preact/jsx-runtime', // <--- Preact specific
        },
    },
});

I'll also include my tsconfig.json file:

{
    "compilerOptions": {
        "target": "ES6",
        "useDefineForClassFields": true,
        "module": "ESNext",
        "lib": ["ESNext", "DOM"],
        "moduleResolution": "Node",
        "strict": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "esModuleInterop": true,
        "noEmit": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "types": ["vite/client", "@types/gtag.js", "node"],
        "jsx": "react-jsx",
        "jsxImportSource": "preact",
        "baseUrl": "./",
        "paths": {
            "react": ["./node_modules/preact/compat/"],
            "react-dom": ["./node_modules/preact/compat/"]
        }
    },
    "include": ["src", "main.ts"]
}

I recognise the post is mostly around vue + vite but I am getting the same build issues with preact + vite.

No troubleshooting as above has helped yet - would be very keen on some assistance

brillout commented 1 year ago

This also affects many vite-plugin-ssr users.

ErhardScampi commented 1 year ago

Still open in 2023 with newest Quasar (vite). and newest amplify:

Tried to use rollup-plugin-polyfill-node but quasar.config.js runs in a node env. so I can't import it. require does not work either. Any ideas to manage it with quasar and vite somehow ?

This is the origin error when I run npx quasar build : 'request' is not exported by __vite-browser-external, imported by node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js file: /Users/sc/dev/artbarrack/code/node_modules/@aws-sdk/client-cloudwatch-logs/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 /Users/sc/dev/artbarrack/code/node_modules/rollup/dist/shared/rollup.js:198 base = Object.assign(new Error(base.message), base);

brnsnt commented 1 year ago

For Quasar I had to add it to the build section in quasar.config.js (extending the vite config didn't work).

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

The missing global definitions is added directly inside index.html

    <script>
      /* https://ui.docs.amplify.aws/vue/getting-started/troubleshooting */
      window.global = window;
      var exports = {};
    </script>
movingelectrons commented 1 year ago

ugh whatever I'm going back to CRA then.

avorsterman commented 11 months ago

For Quasar I had to add it to the build section in quasar.config.js (extending the vite config didn't work).

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

The missing global definitions is added directly inside index.html

    <script>
      /* https://ui.docs.amplify.aws/vue/getting-started/troubleshooting */
      window.global = window;
      var exports = {};
    </script>

Thanks! I'm using Quasar too and this solved the error.

charlieforward9 commented 10 months ago

I was told during Amplify Office Hours that v6 introduced a fix for Vite environments that removes the need to add this resolve config:

resolve: {
      alias: {
        "./runtimeConfig": "./runtimeConfig.browser", //fix production build
      }
    }

The release of v6 may or may not address everything discussed in this issue, but it felt appropriate to share this update here.

asmajlovicmars commented 10 months ago

I was told during Amplify Office Hours that v6 introduced a fix for Vite environments that removes the need to add this resolve config:

resolve: {
      alias: {
        "./runtimeConfig": "./runtimeConfig.browser", //fix production build
      }
    }

The release of v6 may or may not address everything discussed in this issue, but it felt appropriate to share this update here.

@charlieforward9 v6 works perfectly out of the box with SvelteKit, just tested it today, but there's another problem with SSR, which I don't know how to solve yet, described it here: https://github.com/aws-amplify/amplify-js/issues/12578 .

There's no more withSSRContext, so I need to figure out how to get cognitoUser on the server side... Otherwise, v6 looks good to me.

charlieforward9 commented 10 months ago

Good to hear! It seems like this issue might be solved/closable if it resolved this issue.

QuantumStatic commented 9 months ago

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",
    },
  },
});

I was facing global not defined. This really helped. Thanks!

nadetastic commented 9 months ago

With the release of the latest major version of Amplify (aws-amplify@>6), this issue should now be resolved! Please refer to our release announcement, migration guide, and documentation for more information.

If you are still facing this issue after upgrading to v6, please let us know with a reply back.

TeoTN commented 8 months ago

I still saw it with:

    "aws-amplify": "6.0.9",
    "@aws-amplify/ui-react": "6.0.7",

adding the following to vite.config.ts solves it:

  optimizeDeps: {
    esbuildOptions: {
      define: {
        global: 'globalThis',
      },
    },
  },

Without this change, it still fails and the error clearly points to @aws-amplify/ui-react:

Screenshot 2024-01-01 at 13 42 36 Screenshot 2024-01-01 at 13 43 08
nadetastic commented 8 months ago

@TeoTN thanks for your feedback, it seems that it may be specific to the UI library. Will do additional testing and confirm.

reesscot commented 7 months ago

@TeoTN Can you share your full package.json file? I don't see how buffer could be coming from the @aws-amplify/ui-react package. My understanding is that buffer was a dependency of aws-amplify version 5 and was removed in aws-amplify version 6.

nadetastic commented 7 months ago

Hi @TeoTN unfortunately, Im unable to reproduce this issue. Are you still experiencing the error? If so could you try to delete your node_modules and reinstall you packages and see if the error persists? If you still continue to see the error, It would be great to get your package.json so I can reproduce with the same dependencies you have.

nadetastic commented 6 months ago

Hi @TeoTN - Im going to close out this issue as we have not heard back from you. If you are still experiencing this, please feel free to reply back and provide any information previously requested and we'd be happy to re-open the issue.

Thank you!