Lighter, faster, auto-imports, awesome developer experience
Recently we have had exciting releases for the React ecosystem. First, it was Next.js
then came Remix
and later on React 18
. Those were stealing the thunder of any JavaScript
framework. They were driving all the frontend discussions and increasing React’s momentum.
Luckily, the Nuxt
team is making a big comeback with its latest Nuxt 3
version. It is currently in RC
and the stable release is due in June. As great as a Vue.js
is, it will fail to gain traction if it lags behind in framework features. This version might play a big role in increasing its popularity 🚀.
What is Nuxt
anyway? You can think of it as the Remix/Next.js
equivalent written in Vue.js
. It is an isomorphic JavaScript
framework that empowers us to write code that executes both on the client and on the server. It abstracts all the complexity and configuration away.
The new Nuxt 3
release is packed with many features. Not only to create performant web applications but also to raise the developer experience to a whole new level. It has built-in TypeScript support which is awesome. The only obvious caveat is that it is highly opinionated. It’s a tall we need to pay for. However, seeing how amazing this evolution is, I will happily pay for it.
In this article, I will summarise some of the greatest features that might hopefully lead many developers to switch from React
.
This new version of Nuxt
is powered by a new server engine which is nicknamed Nitro
. It is built from the ground up, meaning no legacy code.
What are its features?
- Cross-platform support for Node.js, Browsers, service-workers, and more: it makes the engine platform-agnostic
- Serverless support
- API routes: it is powered internally by the unjs/h3 project.
- Automatic code-splitting
- Hot module downloading
- Hybrid mode: granularly controlling how your pages are rendered. More on that in the next section.
In summary, we get a great engine that is not only able to power SSR
. We can create static
, spa
or event api
applications. The fact that it is platform agnostic and lightweight makes it super powerful. It does not only mean faster response times but the liberty to host the application where we like to. We can now deploy our code directly on the edge. That means the SSR
code is executed as close as possible to the end-user.
Currently the Nuxt
framework supports two rendering modes:
- Client-side: the browser downloads all the
JavaScript
files and then it generates the HTML elements - Server-side: The server generates the HTML page and returns it back to the client. The client is then hydrated to add the interaction.
Each of those approaches has its pros and cons. For example, server-side
rendering is more expensive since we are computing the view in our hosting. However, client-side
does not play well with SEO
.
In prior versions, we had to choose either one or the other approach for the whole application. In this new release, we have a Hybrid Rendering
. We can customize the behavior on a per route basis.
In summary, we have more granular control over which routes we want to be using SSR
and which not. It lets us enjoy the pros of each approach and design our web application accordingly.
⚠️ This might not be part of the first stable release but will be coming shortly after.
Imports are a trivial task. It is such boring work that we normally rely on tooling to handle those (VSCode extensions) and some to order those (ESLint). What if they were not needed?
That is exactly what is happening on Nuxt 3
. We won’t need to add any import statements anymore. It will be worked out automatically by the engine. How will Nuxt
know how to resolve those? They are based on a directory and naming structure.
components/
— this is whereVue
components should be placed.composables/
— this is whereVue
compostables should be placed.
Components
Let’s say we created a components/Foo.vue
:
<template>
Foo
</template>
To use this component all we have to do is use it in our .vue
template file matching the component file name.
<template>
<div>
<Foo />
</div>
</template>
How does that happen? Internally the engine creates everything in the .nuxt
folder. We can inspect the .nuxt/components.d.ts
and find our components definition there.
Dynamic Imports
What if we wanted to import that component in a Lazy way? It can be easily done by prefixing Lazy
to the component Name.
<template>
<div>
<LazyFoo /> // component will be lazy loaded
</div>
</template>
Nested Components
What if the component is in a nested directory? We just have to amend the path directory to the component’s name. For example components/bar/foo.vue
.
<template>
<div>
<BarFoo />
</div>
</template>
💁♂️ It is recommended to name the component components/bar/BarFoo.vue
for consistency though.
Client Specific Components
What if we want to make that component Client only? We can use the ClientOnly
wrapper.
<template>
<div>
<ClientOnly>
<LazyFoo />
</ClientOnly>
</div>
</template>
Explicit Imports
We can use explicit imports if needed by using the #components
in this scenario.
import { Foo } from '#components';
The documentation is great. There is the traditional API
that can be found here.
However, there is an interesting and intuitive guide to get started here. It is still a work in process but helps us understand the Nuxt
project in an easy way. As Nuxt
has a lot of features scoped by folder it can be hard to understand at first. Some directors participate in some file-based routing.
Here are some examples on the folders we might find:
- pages: file-based routing to create routes within your web application through
Vue Router
. - server: folder scanned to register API and server handlers with HMR support.
- public: where we need to put our assets
- components: all the components that are exportable from any page.
- plugins: directory where we need to place our imported plugins.
In order to quickly grasp this, you can find in this guide the complete tree of any Nuxt
project.

There are also some interactive examples that can be found here. Those have links to CodeSandBox
or StackBlitz
.
Currently, the JavaScript frameworks really take into consideration the developer experience. There is great support for TypeScript is Nuxt 3
. We can combine the API
typings with our components
which wraps the whole thing together nicely.
Also, we can now use the latest fancy building tools for building our projects. It makes the whole experience more snappy.
Out of the box Nuxt 3
supports:
Vite
webpack 5
+esbuild
- PostCSS
The default builder is Vite
but switching to Webpack5
is easy but simplifying tweaking the nuxt.config.ts
file:
export default defineNuxtConfig({
vite: false
})
You might extend any config by using
extendWebpackConfig(callback, options?)
extendViteConfig(callback, options?)
addWebpackPlugin(webpackPlugin, options?)
addVitePlugin(vitePlugin, options?)
Thanks to the modern JavaScript compilers we can expect lighting faster build time and a better developer experience.
We have seen how great and important this release is. Hopefully, it will help increase the interest of Vue.js
. It is awesome to have diversity since competition brings many good ideas. That is how innovation is driven forward.
We can see how React is dominating JavaScript’s View ecosystem.

React’s community is bigger and it is easier to land a job. However, tools like Nuxt 3
might be able to balance the scales.
Interesting, it is a great time for being a web developer. We have plenty of great choices. Do we go for Remix
, Next.js
or Nuxt.js
? We can’t possibly go wrong with any of those. It will all boil down to our personal preferences.