Closed yaquawa closed 2 years ago
Hi @yaquawa, can you please share more details about how this error came about? What does amplify status
show?
@jhockett I think this is a webpack 5 compatibility problem. I'm using laravel-mix to bundle the js files, which it's utilizing webpack 5. I didn't see errors like this before I upgraded to webpack 5.
I'm going to close this then @yaquawa. If it turns out that webpack 5 isn't causing the issue, comment below and the issue can be reopened.
Hi @jhockett I don't think this is an "issue" of WebPack, some library like graphql-js already supports webpack 5 as of its latest version.
I believe this can be fixed by simply changing aws-exports.js
to aws-exports.mjs
if the upstream(amplify-cli
) is using commonjs.
By the way amplify-cli
still depends on the old version of graphql-js so I have to replace the old one with the latest one manually.
Hi @jhockett just to reinforce that this topic still not solved, and I agree with @yaquawa that this is not related to WebPack. I'm having the same issue trying to use the newly release SvelteKit with static distribution and console deploy.
It seems that as part of the "amplify push" process the aws-exports.js is required by "amplify-frontend-javascript/lib/frontend-config-creator.js", and as the whole project is of type module it should have been imported.
I took a look at the code and found this piece where apparently there is a tentative to circumvent it, but it seems not working. Couldn't deep dive on it to come with a PR.
if (isPackaged) {
// if packaged, we can't load an ES6 module because pkg doesn't support it yet
const es5export = 'module.exports = {default: awsmobile};\n';
const es6export = 'export default awsmobile;\n';
const fileContents = fs.readFileSync(targetFilePath, 'utf-8');
fs.writeFileSync(targetFilePath, fileContents.replace(es6export, es5export));
awsExports = require(targetFilePath).default;
fs.writeFileSync(targetFilePath, fileContents);
} else {
awsExports = require(targetFilePath).default;
}
Hi @rodgco, thanks for the detailed information. I'll add this to our triaging project so this can get better visibility.
Sorry @yaquawa, I missed your comment somehow and never followed up.
I don't think this is a Webpack issue. The error message comes from Node. I think the long term solution is to move to import()
, but I don't think we could get away with that yet due to varying ESM support in Node versions.
We might be able to do something similar to the code in https://github.com/aws-amplify/amplify-cli/issues/5691#issuecomment-808574722... read the file, write it back out as CJS to a file with the .cjs
extension, require it, and then delete the .cjs
file.
Same error for me trying to push sveltekit static build with amplify.
Must use import to load ES Module: /Users/a/code/sveltekit/svk5/src/aws-exports.js
An error occurred during the push operation: Must use import to load ES Module: /Users/a/code/sveltekit/svk5/src/aws-exports.js
We started some academic exercises to deploy applications with Svelte-Kit in aws amplify, playing with Appi, storage ... etc.
Installation method: mkdir my-app cd my-app npm init svelte @ next npm install npm run dev - --open
As far as I understand Sapper is not ESM based, so this test deviates from the original problem that is Amplify Support for ESM based projects like SvelteKit.
Hey there. Im using svelte kit with amplify. This error happens to me when I have already created aws-exports.js
. When I delete it everything goes fine. I can do it manually when doing a change to the backend locally, but when using the hosting CI/CD I can not. Is there a workaround for this?, I just need to update my frontend, should be a simple node app (that build to static) and dont even need to update a single service on my backend. I can handle that by my own, but even if i dont put anything about the backend in the pipeline definition it tries to update the it or at least pull it.
Is there any update on this. Seams like been a while and people have same issue which leads me to suspect its not repairable easily. Supabase works easy and fine. Would like to use aws amplify ui console and sveltekit though. Actually I dont get error when I dont want to edit backend locally (which i dont). So thats good now just need to figure out how to make calls to database and what not
For me, adding Amplify to my SvelteKit Project where type: is "module" was fairly easy... I did exactly what the error suggested.... I watched it initialise and fail, then I renamed the aws-exports extension from .js
to .cjs
Then I ran amplify init again... said 'Yes' to existing environment, selected 'dev' ... and everything is now fine.
After any amplify commands I have to remove the .cjs and rename the .js to .cjs again.
It's slightly annoying, but easily fixed.
@michaelcuneo That works locally, but when you are going to use CI/CD, it throws an error in the server and you can't change the extension there.
Not sure if this is helpful to anyone, but after having all the same issues, I was able to get CI/CD working with SvelteKit and Amplify with the following:
preBuild
command in build settings to upgrade node nvm install 14
src
of my repo and pushed repo to GitHub.main
branch in the amplify console.It all seems to be working so far. I'm guessing with this process aws-exports.cjs isn't being overwritten. Not ideal, but works and I have access to all the amplify features like access-control etc..!
version: 1
frontend:
phases:
preBuild:
commands:
- nvm install 14
- yarn install
build:
commands:
- yarn run build
artifacts:
baseDirectory: build
files:
- '**/*'
cache:
paths:
- node_modules/**/*
The problem here is that Amplify CLI writes out an ES6 module: aws_exports.js.ejs but then attempts to require it as a CommonJS module: frontend-config-creator.js. It's like trying to execute a C++ program with nodejs, these are different file formats. There's documentation here: https://nodejs.org/api/packages.html
My suggestion to the Amplify team is to convert that template file into a CommonJS file and output with a .cjs
extension. For the users of Amplify CLI I suggest replacing export default awsmobile;
with module.exports = awsmobile;
perhaps with an Amplify hook.
The problem here is that Amplify CLI writes out an ES6 module: aws_exports.js.ejs but then attempts to require it as a CommonJS module: frontend-config-creator.js. It's like trying to execute a C++ program with nodejs, these are different file formats. There's documentation here: https://nodejs.org/api/packages.html
My suggestion to the Amplify team is to convert that template file into a CommonJS file and output with a
.cjs
extension. For the users of Amplify CLI I suggest replacingexport default awsmobile;
withmodule.exports = awsmobile;
perhaps with an Amplify hook.
This hook solutions sounds reasonable. Changing manually all the time would be a headache.
Which hooks are we talking about here? post-push.js
and post-pull.js
maybe?
I am trying to set this up with Amplify hooks.
@laverdet , changing export default awsmobile;
to with module.exports = awsmobile;
gives me an undefined error in my react app on all the exported values. Eg.
import awsmobile from './aws-exports.cjs';
...
const env = awsmobile['aws_user_files_s3_bucket'].slice(envStart + 1);
package.json
: type: "module"
TypeError: awsmobile.aws_user_files_s3_bucket is undefined
Any idea what's going on there?
Any updates on this? I've tried a bunch of different suggestions in this thread but my SvelteKit app will not build properly on Amplify.
What worked for me was changing package.json type: "module" to type: "commonjs" of course that changes babel and nodes interpretation of the code so it won't work for everyone. Leaving this as a suggestion that may help others.
I'm trying to follow steps mentioned here - https://docs.amplify.aws/cli/function/#graphql-from-lambda to call GraphQL API from lambda. As soon as I add "type": "module" to package.json , it starts throwing an error on amplify mock command. As per above link I need to import node-fetch but I'm not able to do it. Lambda code is just a hello-world code as of now, just changing package.json starts creating this problem.
stack: 'Error: Could not load lambda handler function due to Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
@kriti-eco try installing node-fetch@2 instead. Version 3 made a strict cutover to modules. I recommend kicking the can down the road until Amplify can better support modules.
None of the workarounds mentioned here work for our use case. We now have pre/post push/pull hooks to replace the type from module to commonjs before the operation and back to module afterwards to get the CI build working. There were several other places where buggy/non-existing ESM support in Amplify caused trouble after we upgraded to Angular 13/14 that only ships ES modules. I really hope proper ESM support is something the Amplify team will address, soon.
I really hope proper ESM support is something the Amplify team will address, soon.
I have bad news for you
Any updates on this?
@vadimmelnicuk I've managed to get this working from the following flow...
1: amplify init or amplify init project then let it fail. 2: rename aws-exports to .cjs extension. 3: copy aws-exports to .js so there is both a .cjs and .js in the project. 4: Remove type: "module" from package.json. 5: All subsequent pushes will be successful.
@michaelcuneo Brilliant, thanks. It worked :)
Hello everyone, if you want to have ES Modules working with Amplify CI pipeline, you need to change amplifyPush
script behaviour. I tweaked it in my own project. It is available in https://github.com/Karol-Perec/wykopX/blob/master/scripts/amplifyPush.sh. So you just need to add this custom script to your repository, for example to scripts/amplifyPush.sh
, just like I did. Then you need to update your CI backend build pipeline to execute custom script instead of the built-in one:
backend:
phases:
build:
commands:
- sh scripts/amplifyPush.sh --simple
TLDR: i just added renaming aws-exports.js
to aws-exports.cjs
before running amplify init
, so every of your CI pipelines will work with ES Modules out of the box.
This bug is killing us on a project we're attempting to deliver.
It's really bad. +1 for needing a non-hacky fix, please!
@Karol-Perec and ALL:
A way to do this without introducing a custom amplifyPull
script:
echo "Stashing package.json"
cp package.json package.json.bak
echo "Removing type: module and writing modified package.json"
jq -c 'del(.type)' package.json.bak > package.json
echo "Running Amplify command"
eval $cmd
echo "Restoring package.json"
mv package.json.bak package.json
or
echo "Removing type: module and writing modified package.json"
jq -c 'del(.type)' package.json.bak > package.json
echo "Running Amplify command"
eval $cmd
echo "Restoring package.json"
git checkout package.json
Not sure why this issue got closed. I'm using "type": "module"
in my package.json (not possible to change it because the entire app depends on that setting). When I push changes to my Github repo Amplify CI/CD deployment starts and fails with the following error: Must use import to load ES Module
It makes no sense to rename aws-exports.js to .cjs locally because during push or pull commands it's generating .js files locally instead. My build config is a default Vue 3 one:
version: 1
backend:
phases:
build:
commands:
- '# Execute Amplify CLI with the helper script'
- amplifyPush --simple
frontend:
phases:
preBuild:
commands:
- npm install
build:
commands:
- npm run build
artifacts:
baseDirectory: dist
files:
- '**/*'
cache:
paths:
- node_modules/**/*
Any idea how to solve this @danielleadams @armenr ? Any help is highly appreciated, thanks!
For @bart and ANYONE ELSE who hits this same problem:
Amplify (luckily) exposes some "entrypoints" for us to use to trigger hooks and scripts. See here: Amplify Docs - Command Hooks
In the root of your project (or in the folder within a monorepo) where your amplify
folder is, you will see this folder structure:
❯ tree -L 1 amplify
amplify
├── #current-cloud-backend
├── README.md
├── backend
├── cli.json
├── hooks
└── team-provider-info.json
So, inside of that folder called hooks
- you can drop off scripts (written either in JS or SH). I recommend straight shell to avoid even more pains in the ass and headaches with TypeScript, in case your project is TypeScript.
Like this:
❯ tree -L 1 amplify/hooks
amplify/hooks
├── README.md
├── post-pull.sh
├── post-push.sh
├── pre-pull.sh
└── pre-push.sh
I needed to deal with this particular problem - the whole Must use import to load ES Module
- in a way that is:
jq
in this case)Therefore, I wrote two hook scripts.
If it helps instill confidence, I've been using these "in production" with my team + production customers/apps without any problems, for a few weeks now...
The pre-pull
script will:
package.json.amplify-pre-pull
jq
to modify your project's existing package.json (in place) by deleting the type
key/value pairThe post-pull
script will:
package.json.amplify-pre-pull
file existsjq
made before pulling the Amplify projectIf you use git
to check your repo before/after a pull (using my scripts), git won't/shouldn't report any changes to package.json
😎
NOTE: The script presumes/requires that you have jq
installed on your development machine & in your CI/CD pipeline.
The first time you ADD these scripts to your amplify project, you have to IMMEDIATELY PUSH THEM TO GIT AND AMPLIFY
So, to "install" these scripts:
amplify/hooks/
directorygit add, git commit, git push
amplify push
THEN
amplify pull
OTHERWISE, if you add the scripts and then pull BEFORE pushing, amplify will ignore them/overwrite them/delete them.
#!/bin/bash
# !!Note: SCRIPT RUNS IN REPO ROOT! All relative path references should be handled as such!
# pre-pull.sh: Armen Rostamian
# last modified: 2022-08-22
set -euo pipefail
# These are here in case you are using a monorepo or have some kind of custom/funky directory structure set up
# and need a way to automatically obtain the necessary absolute paths to any specific app-related files
ROOT_PATH=$(jq <amplify/.config/local-env-info.json -r .projectPath)
APP_REL_PATH=$(jq <amplify/.config/project-config.json -r .javascript.config.SourceDir)
FULL_PATH=$ROOT_PATH/$APP_REL_PATH
echo "Pre-pull script running at $(date +%s)!"
PRE_PULL_PACKAGE_JSON="package.json.amplify-pre-pull"
echo " Stashing package.json"
cp package.json ${PRE_PULL_PACKAGE_JSON}
echo " Removing type: module and writing modified package.json"
jq -c 'del(.type)' ${PRE_PULL_PACKAGE_JSON} > package.json
#!/bin/bash
# post-pull.sh: Armen Rostamian
# last modified: 2022-08-22
set -euo pipefail
echo "Post-pull script running at $(date +%s)!"
# These are here in case you are using a monorepo or have some kind of custom/funky directory structure set up
# and need a way to automatically obtain the necessary absolute paths to any specific app-related files
ROOT_PATH=$(jq <amplify/.config/local-env-info.json -r .projectPath)
APP_REL_PATH=$(jq <amplify/.config/project-config.json -r .javascript.config.SourceDir)
FULL_PATH=$ROOT_PATH/$APP_REL_PATH
# this file *would* be created as the original copy of the package.json by the pre-pull.sh script
PRE_PULL_PACKAGE_JSON="package.json.amplify-pre-pull"
if [ -f ${PRE_PULL_PACKAGE_JSON} ]; then
echo " Restoring package.json"
mv ${PRE_PULL_PACKAGE_JSON} package.json
fi
Thank you so much @armenr for sharing your hook scripts and diving deep into the topic. I already understood the hooks concept but after running into another Amplify issue (where I would have to find another workaround for) I decided to go the good old fashioned way using Serverless framework. In my opinion Amplify unfortunately is still not stable and flexible enough to get used in enterprise applications. But for sure this is just a personal opinion and I'm sure other devs would love to go this hook way. So again, thanks a lot for sharing!!
@bart - no problem. I went down the Serverless Inc. framework route, as well as a few others.
In the end, the amount of value that Amplify provides (e.g. - PR preview environments, branch auto-detection + automatically provisioned backends per-branch, etc...) outweighed the cons/bugs/workarounds...so I've chosen to stick with Amplify.
IF you're getting into the Serverless Inc. framework world of things, I'd highly encourage you to also check out SST and CDK too. Depending on your technology needs/objectives/business goals, those may be good to check out also. :)
Thanks a lot @armenr for pointing me into the SST / CDK direction. Accidentally I already tinkered around with it yesterday. Like the simplicity but decided to go with Serverless framework in the end because I'm most familiar with it. But maybe for a side project or smaller project in future SST might be a good choice.
Hey @bart and @armenr this fix has been released with the latest version of Amplify CLI, 10.2.3 🙂
Really happy this got fixed!
Describe the bug package.json with
"type": "module"
be set cause the following error when I runamplify push
Amplify CLI Version 4.30.0
node.js Version v14.11.0