Top level await not supported. what's the workaround?

I get this error on deployment…

[ERROR] Top-level await is currently not supported with the "cjs" output format
9:21:06 PM:     .netlify/functions-internal/entry.mjs:3869:0:
9:21:06 PM:       3869 │ await fetchProducts();

My code requires this structure when it loads…

const state = {
  products: [],
  cart: [],
  wishlist: [],
};

const fetchProducts = async function () {
  if (localStorage.getItem("products")) {
    const data = JSON.parse(localStorage.getItem("products"));
    state.products = [...data];
    return;
  }
  const response = await fetch(url);
  const data = await response.json();
  // Update state with all products data

  state.products = [...data];
};

await fetchProducts();

Can you please advise what I need to do to get it to work on netlify? On the localhost I’ve tried to change a few things to avoid the ‘await’ at the top level but the code then doesn’t work. I’d just like some advise on how I need to structure this to avoid the top level await if the top level await is really not possible on netlify…

Regards,
Alim

@alimbolar The key part of that message is…

with the “cjs” output format

CJS is CommonJS.

Have you tried using ESM (ES Modules)?

Set "type": "module" in your package.json.

image

Here’s a random article that explains some of the differences:

Edit: I’ve now spotted you’ve got an .mjs extension, so I’m actually not sure what’s going on, but the error indicates it’s being interpreted as cjs.

Hi

Thanks for the response @nathanmartin

I checked my package.json and it already has module as the value of type

{
  "name": "@example/minimal",
  "type": "module",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "@astrojs/netlify": "^1.3.0",
    "@astrojs/tailwind": "^2.1.3",
    "@astrojs/vue": "^1.2.2",
    "@headlessui/vue": "^1.7.7",
    "@heroicons/vue": "^2.0.13",
    "@tailwindcss/aspect-ratio": "^0.4.2",
    "@tailwindcss/forms": "^0.5.3",
    "@tailwindcss/typography": "^0.5.9",
    "astro": "^1.9.0",
    "netlify-cli": "^12.9.2",
    "tailwindcss": "^3.2.4",
    "vue": "^3.2.45"
  }
}


And here’s my folder structure… the only .cjs file is that of tailwind…

astro.config.mjs  
package.json
README.md
tsconfig.json
folder.txt
package-lock.json
src
node_modules
public
tailwind.config.cjs

Any ideas what I could do?

OPTION 1
One option is to figure out the issue with the top level await… I’ll wait for some update from you on that…

OPTION 2
The second option is, assuming that top level await is not an option, would you know how I would import data to load asynchronously and ensure the data is loaded by the time the page renders?

Currently the moment I remove the await keyword the products don’t display on my page … so I assume that in my code I could do something to ensure that the state.products is populated and stays populated…

I know this could be a question beyond the scope of the netlify forum and maybe stackoverflow would be the right place but I am just taking a chance here…;-)…

Thanks in advance…

Have a nice day…:-)…

Regards,
Alim

@alimbolar I’m just a community member and it’s a day off for me today, so I’m actually just about to play some games with friends :slight_smile:

Hopefully another community member or someone from Netlify can get you sorted out!

1 Like

I seem to have resolved the issue but I am still not confident about what it was that fixed it.

I will document my findings here if it helps someone else and also as a reference for “myself from the future”.

So basically this is my initial few experiences with SSR and I think I am still stuck on the SPA mindset and although I seem to have got my head around the SSG part of astro I am yet to full understand the SSR process.

So from my understaning, I think I was trying to run the await keyword in a JS module which I was importing into my pages but I didn’t realise that those pages won’t have the state alive when each of them loads as an SSR render… that I think was my first mistake and so my await in the module was basically not really working.

Anyways I am not sure why the await (top level) was not accepted by netllify during build.

So I decided to use the await inside the VUE component that I was importing in astro. I had this as a choice or to use the await in the frontmatter of astro and then pass the data as a prop into the vue component.

For now, I am experimenting with using await in the component and when I experiment with the await in the frontmatter of astro I’ll add another response in this thread.

So my findings while using top level await in the vue component were interesting (to me at least!)…:-)…

Firstly, it worked on netlify so I still don’t know why it didn’t work in the JS module.

Secondly as astro seems to have some special needs, although the await did seem to get the data there was an error in the console saying that the component didn’t render as it needs to be wrapped by <Suspense> which is an experimental feature in vue at the time of writing this post. Suspense | Vue.js

So although the HTML of the vue component did render, the javascript was not working… so I had to wrap the vue component with the <Suspense> tag and it worked fine.

From my experience, my method might not be the best way to accomplish this as the page load seems to be long and I will surely try some method where I can pull the data in and use some state management option like the one recommended by astro - NanoStores (<GitHub - nanostores/nanostores: A tiny (258 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores)

And also maybe the top level await should be done in the frontmatter of Astro and then the data stored in either the state management module or localStore or passed down as props. I will share my findings on this when I am done with my experimentation.

Hope this helps someone.

Regards,
Alim

1 Like

Hi @alimbolar

thank you for sharing your solution! This is definitely helpful for other users :+1:

1 Like