Next.js 3.0 Ships with Static Exports and Dynamic Imports
Next.js 3.0 is now stable and available on npm. The release focuses on two long-requested capabilities—static HTML export and dynamic code loading—alongside a round of developer-experience fixes to hot module replacement and error reporting.
Next.js remains a zero-configuration toolchain for React apps, providing server rendering and code splitting out of the box.
Export Static HTML
One of the most upvoted feature requests in the Next.js repository has now landed. A configured project can be exported to a directory of plain .html and .css files:
next export
The output can be deployed as often as needed to now.sh without any additional setup or cost. Community members have already built static blog generators on top of the feature:
- next-blog
- next-static
- nextein
Dynamic Import for Code and Components
Next.js now fully supports the TC39 dynamic import proposal. Applications split into chunks that load on demand, giving developers control over when code is fetched—based on user interaction or application state.
Importing a module as a promise is all it takes:
const moment = import('moment')
setTimeout(function() {
moment.then(moment => {
// Do something with moment
})
}, 15000)
In that example, the moment module is fetched only when the setTimeout callback fires, roughly 15 seconds after page load. The main JavaScript bundle stays smaller by deferring code until it is actually needed.
For React components, the opt-in next/dynamic utility handles on-demand loading while preserving server rendering when the component is part of the initial render.
Dynamic components can load a single component:
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(import('@components/hello'))
export default () => (
<div>
<Header />
<DynamicComponent />
<p>HOME PAGE is here!</p>
</div>
)
Or select between different components based on runtime properties:
import dynamic from 'next/dynamic'
const HelloBundle = dynamic({
modules: (props) => {
const components = {
Hello1: import('@components/hello1'),
Hello2: import('@components/hello2')
}
// you can add / remove components based on props
return components
},
render: (props, { Hello1, Hello2 }) => (
<div>
<h1>{props.title}</h1>
<Hello1 />
<Hello2 />
</div>
)
})
export default () => (
<HelloBundle title="Dynamic Bundle" />
)
Previously, code splitting was tied to routes and the sections of an application a user had navigated to. With this release, code can be split according to the data being displayed.
Error and HMR Improvements
Error displays have been reworked with a new color theme contributed by Krisztian Puska, intended to be easier on the eyes and more accessible.
Hot module replacement behavior has also been tightened in several edge cases:
- Error recovery now works broadly: when any error occurs, edits can be saved and the error will update, resolve to another error, or disappear.
ERR_INCOMPLETE_CHUNK_ENCODINGerrors that appeared in dev tools under Node.js 8.x have been fixed.- Navigating to a page with an error renders the error message and supports live correction.
- A previously problematic flow—navigating to a missing page (404), then populating it with an error—now behaves correctly.
- Returning an unexpected type from a module is handled cleanly, with the page recovering once the correct type is returned.
- Runtime errors such as
undefined is not a functionare now caught during module evaluation, enabling real-time debugging.
Performance and Size Gains
Baseline server boot time is roughly five times faster, dropping to about 200ms from 1000ms. The core Next.js bundle has also been optimized and is now 10% smaller, with only production-essential code included in final bundles.
Looking Toward 4.0
A public roadmap for Next.js 4.0 will be shared soon. Planned focus areas include a leaner core, faster boot and rendering, integration with React 16, and better development caching to avoid recompilation.



