Hiprup

What is top-level await?

Top-level await lets you use await directly in an ES module, outside any async function.

  • Module-level — await imports, fetches, or setup before the module finishes loading.

  • Blocks dependents — modules importing it wait until its top-level await resolves.

Use carefully: it can delay everything that depends on the module.

// config.js (ES Module)
const response = await fetch('/api/config');
export const config = await response.json();

// app.js (imports config — waits for it to load)
import { config } from './config.js';
console.log(config.apiUrl); // Config is ready

// Dynamic import at top level
const { default: lodash } = await import('lodash');

// Conditional module loading
const dbModule = await import(
  process.env.DB_TYPE === 'postgres' ? './pg.js' : './mysql.js'
);

// In HTML: <script type="module" src="app.js"></script>

await at the top level pauses the module until the Promise resolves. Dependent modules (importing from config.js) wait automatically.

Dynamic import() with await loads modules on demand. This only works in ES Modules (type='module'), not regular scripts or CommonJS.

Only works in ES Modules (not CommonJS, not regular scripts). Dependent modules wait for the awaited module to resolve.

The config loading pattern is the most practical example. ES2022 feature.

What is top-level await? | Hiprup