Storyblok Raises $80M Series C - Read News

What’s the True Total Price of Enterprise CMS? Find out here.

Skip to main content

Nuxt 3 beta: best DX, composables, auto-importing and more!

Developers
Alex Jover Morales
Try Storyblok

Storyblok is the first headless CMS that works for developers & marketers alike.

The Nuxt team recently released the long-awaited Beta 3 version! I couldn't wait to try it out and I'm so impressed with the great DX (Developer Experience) you feel with Nuxt 3.

Many devs are wondering... what's new on Nuxt 3? Will my code and productivity improve? But Alex... is really worth the effort?

We've been experimenting by moving our libs to Nuxt 3 and Vue 3 (to be published soon) and learned a lot. Tell me if you're interested in Twitter and I can do it 😉

But for now, let me quickly tell you the real deal with Nuxt 3 and my top 6 features I like the most!

Powered by Vue 3 and Composition API

Vue 3 is lighter, faster, and opens a new world of possibilities thanks to the native Composition API. Nuxt 3 is built on top of it, meaning you have those benefits directly.

Most of the functionality, from data fetching to meta tags definition, comes as composable functions. Some examples are useFetch, useMeta and useState.

But as usual, the Nuxt team supercharged it with new features! To learn more, continue reading.

Auto-imports

In Nuxt 2 you could already auto-import components, but Nuxt 3 brings that to the next level.

If you're familiar with <script setup>, the syntactic sugar over the setup function, you can use any of the composable functions that Nuxt 3 brings to you.

You can also use the new composable directory to define all your functionality in composition functions, which are auto-imported as well.

Even better, if you're already using any function from the amazing VueUse library, they're also auto-imported.

Code speaks by itself. This Nuxt 2 code:

Nuxt 2 code
        
      <script>
export default {
  data() {
    return {
      userName: "",
      products: [],
    };
  },
  async fetch() {
    const { apiURL, apiToken } = this.$config;
    const url = `${apiURL}/cdn/stories?token=${apiToken}`;
    this.products = await fetch(url).then((res) => res.json());
  },
  head: {
    title: "My cool page",
    meta: [
      {
        hid: "description",
        name: "description",
        content: "Lorem...",
      },
    ],
  },
};
</script>
    

In Nuxt 3 becomes:

Nuxt 3 code
        
      <script setup>
const config = useRuntimeConfig();
const userName = ref("");

const { data: products } = await useFetch(`/cdn/stories`, {
  baseURL: config.apiURL,
  params: { token: config.apiToken },
});

useMeta({
  title: "My cool page",
  meta: [
    { hid: "description", name: "description", content: "Lorem..."}
  ]
})
</script>
    

Performance in mind

Anyone that used Nuxt before knows how crazy optimized it is for Web Performance, from the very beginning. In "My web performance journey with Nuxt, Storyblok and Netlify" our ambassador Alba goes through all of the details on what can be optimized in a web. You'll see that Nuxt covers the most by default, from preload, prefetch and lazy-loading to unused code removal.

Nuxt 3 again is in the next level. How?

  • Targeting modern browsers it produces up to 75x smaller bundles, both on client and server.
  • Dynamic server code-splitting, thanks to Nitro engine.
  • Vue 3 as its backbone. Look at this benchmark and see performance comparisons.
  • Bundling and hot reloading are almost instant! It took around 75ms when I tried. Vite is the culprit.

Flexible dynamic pages

Thanks to the new brackets syntax for the pages directory, now you can declare just a part of the file name dynamic. Oh, and for directories, this applies as well 😉.

In other words, see the following structure:

        
      -| pages/
---| index.vue
---| users-[group]/
-----| [id].vue
    

Produces two dynamic route params:

        
      {{ $route.params.group }}
{{ $route.params.id }}
    

And a URL like /users-berlin/2343, for example.

Nuxt Bridge: making migration easy

The Nuxt team is well aware of the cost and effort to upgrade and doesn't want to leave us behind.

That's why they created Nuxt Bridge, an intermediate layer that lets your Nuxt 2 applications benefit from most of the Nuxt 3 improvements on DX, performance, and features. That opens the door to migrate as smoothly as possible.

What if you have already migrated? No problem, read the instructions and you'll see how easy it is to remove Nuxt Bridge.

Nitro Engine: going serverless and API-friendly

Has it happened to you that you needed a simple API to run alongside your Nuxt App? Maybe just some simple endpoints?

Nuxt 3 makes it very easy thanks to Nitro, the new server engine that won't disappoint you.

I could tell you it has serverless support out of the box, API routing or dynamic server-side code-splitting, but you can check all of the features yourself.

To create API endpoints, you just need to place them under server/api. For instance:

        
      // server/api/hello.js
export default async (req, res) => {
  await someAsyncFunction()

  return {
    someData: true
  }
}
    

This file will generate the /api/hello endpoint.

Server middleware is on the menu as well. Nuxt will load them automatically and they run in every request, similar to how express.js work:

        
      // server/middleware/addSomeValue.js
export default async (req, res) => {
  req.someValue = true
}
    

Wrapping up

I hope you're as excited as I am with all the new features and the DX that comes with it!

A little warning: probably when you read this Nuxt 3 is still unstable, so be aware that it might not be production-ready yet. But who needs to wait to get started and learn the new stuff? 😉

Let me know your thoughts on Nuxt 3 on Twitter, I'll be happy to see what you're building with it or answer any questions!

ResourceLink
Nuxt v3 pagehttps://v3.nuxtjs.org/
Status of Nuxt 3 plugins & moduleshttps://isnuxt3ready.owln.ai/