nextconfigmjs
Mastering Next.js Configuration with next.config.mjs
Key Takeaways
- ESM Support –
next.config.mjsenables native ES modules, aligning Next.js with modern JavaScript. - Migration Path – A clear, step‑by‑step guide to move from
next.config.jswithout breaking builds. - Enhanced Type Safety – Using TypeScript with
next.config.mjsreduces runtime errors. - Performance & Compatibility – Proper configuration can unlock faster builds and smoother plugin integration.
- SEO‑Friendly Practices – Configuring rewrites, redirects, and headers directly in
next.config.mjsboosts crawlers’ understanding.
Why Use next.config.mjs?
Next.js 13 introduced native ES module support, allowing developers to write configuration files in .mjs format. This transition brings several benefits:
- Consistent module syntax across your codebase.
- Improved support for
importstatements, making tree‑shaking and bundling more efficient. - Future‑proofing against Node.js’ gradual deprecation of CommonJS in some contexts.
Common Pain Points
1. Migration Errors
Misconfigured module.exports vs. export default can lead to “Configuration file must export a function” errors.
2. Environment Variable Access
Accessing process.env inside an ES module requires careful handling to avoid type mismatches.
3. Plugin Compatibility
Some older Next.js plugins expect CommonJS exports and may fail with .mjs files.
4. TypeScript Integration
Without proper typings, IntelliSense and compile‑time checks become unreliable.
Solutions & Best Practices
Exporting Correctly
export default defineConfig({
// Your config here
});
Using defineConfig from next/dist/shared/lib/utils
Wrap your configuration in defineConfig to get type inference and linting support.
Handling Environment Variables
Define process.env types in next-env.d.ts or use next/config module to expose env values during build.
Plugin Migration Strategy
- Check the plugin’s documentation for ESM support.
- If unavailable, use dynamic imports:
import('plugin').then(p => p.default(config)); - Alternatively, keep
next.config.jsfor that plugin while exporting the rest asnext.config.mjs.
TypeScript Setup
Add the following to next-env.d.ts:
///
///
declare module 'next/config' {
export interface RuntimeConfig {
// Define your runtime config here
}
}
Comparison: next.config.js vs next.config.mjs
| Feature | next.config.js (CommonJS) |
next.config.mjs (ESM) |
|---|---|---|
| Export Syntax | module.exports = {...} |
export default {...} |
| Import Syntax | require() |
import |
| TypeScript Support | Requires any or manual type declaration. |
Native inference with defineConfig. |
| Plugin Compatibility | Works with all legacy plugins. | May need dynamic import or wrapper for older plugins. |
| Future Proofing | CommonJS is gradually being phased out. | Aligns with Node.js ESM trend. |
| Build Performance | Marginally slower due to CommonJS resolution. | Potentially faster with tree‑shaking. |
Migration Checklist
- Rename
next.config.jstonext.config.mjs. - Replace
module.exports =withexport default. - Wrap the export in
defineConfigif using TypeScript. - Verify all dynamic imports or require calls are converted.
- Update plugin configurations to use dynamic import if