DEV Community

Cover image for a first look at nuxt 3
anthony-campolo
anthony-campolo

Posted on

a first look at nuxt 3

We are excited to open source Nuxt 3 after more than a year of intense development. On top of supporting Vue 3 or Vite, Nuxt 3 contains a new server engine, unlocking new full-stack capablities to Nuxt server and beyond.

Introducing Nuxt 3 Beta

The goal of Nuxt is to make web development intuitive and performant while keeping great developer experience in mind. The original version was created by Sébastien Chopin in October 2016 to emulate the features of Next.js but with Vue instead of React. Version 3 has been over a year in the making and is composed of the following core packages:

Together these packages provide a selection of libraries for managing many common concerns for developers building on the web today such as:

  • A JavaScript framework to bring reactivity and web components - Vue.js
  • A bundler to support hot module replacement in development and bundling for production - Webpack 5 and Vite both supported
  • A transpiler for writing the latest JavaScript syntax while supporting legacy browsers - esbuild
  • A server that can serve your application in development and support server-side rendering or API routes - h3
  • A routing library to handle client-side navigation - vue-router

In addition to curating and integrating these tools, Nuxt also provides directory structure conventions for managing pages and components.

How to Migrate a Nuxt 2 Project to Nuxt 3

If you don't have a Nuxt 2 project, skip ahead to the section, "Create a Nuxt 3 project from scratch."

At the moment, there is no Nuxt 2 to Nuxt 3 migration guide nor is it recommended due to potentially more changes coming. The team is working to provide a stable migration guide and tooling to make it as smooth as possible in the form of Nuxt Bridge. If you have an existing Nuxt 2 project, the team strongly recommends you begin by using Nuxt Bridge to experiment with new features while avoiding breaking changes. Bridge is a forward-compatibility layer that allows you to experience new Nuxt 3 features by installing and enabling a Nuxt module.

All Nuxt 2 modules should be forward compatible with Nuxt 3 as long as they migrate to bridge or if they are already following guidelines. All (upcoming) modules made with @nuxt/kit should be backward compatible with Nuxt 2 projects (even without bridge) as long as they are not depending on a Nuxt 3 / Bridge-only feature. Since Nuxt 3 natively supports TypeScript and ECMAScript Modules, it is useful to avoid CommonJS syntax such as __dirname, __filename, require(), and module.exports as much as possible.

Try online

We will be building a Nuxt application from scratch. However, you can start playing with Nuxt 3 online in your browser on either StackBlitz or CodeSandBox.

Create a Nuxt 3 project from scratch

The project will start with only three files:

  • .gitignore to avoid accidentally committing stuff that shouldn't be committed
  • package.json to define our scripts and dependencies
  • app.vue to display our Vue application

We will create a directory for pages and an api later on.

mkdir ajcwebdev-nuxt3
cd ajcwebdev-nuxt3
touch package.json app.vue
echo 'node_modules\n.DS_Store\n*.log\n.nuxt\nnuxt.d.ts\n.output' > .gitignore
Enter fullscreen mode Exit fullscreen mode

All the code for this article can be found on my GitHub.

App file - app.vue

The app.vue file is the main component in your Nuxt 3 applications. With Nuxt 3, the pages/ directory is optional, if not present, Nuxt won't include vue-router dependency. This is useful when working on a landing page or an application that does not need routing.

<!-- app.vue -->

<template>
  <div>
    <h2>ajcwebdev-nuxt3</h2>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

app.vue acts as the main component of your Nuxt application. This means anything you add to it, such as JavaScript or CSS, will be global and included in every page.

package.json

In your package.json, add the following scripts (dev, build, and start) along with the latest version of nuxt3 as a development dependency.

{
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build",
    "start": "node .output/server/index.mjs"
  },
  "devDependencies": {
    "nuxt3": "latest"
  }
}
Enter fullscreen mode Exit fullscreen mode

Nuxi is the new CLI for Nuxt 3 and has two main commands:

  1. nuxi dev - Start development server
  2. nuxi build - Make production assets

We also created a start script that uses Node to run the bundled output generated for the server by nuxi build.

Start development server

The yarn dev command starts your Nuxt app in development mode and includes hot module replacement. You can include the --open flag to automatically open the browser after starting up.

yarn dev
Enter fullscreen mode Exit fullscreen mode

The CLI will display links to the running application and performance metrics.

Nuxt CLI v3.0.0-27237303.6acfdcd

  > Local:    http://localhost:3000/
  > Network:  http://192.168.1.242:3000/

ℹ Vite warmed up in 592ms
✔ Generated nuxt.d.ts
✔ Vite server built in 903ms
✔ Nitro built in 112 ms
Enter fullscreen mode Exit fullscreen mode

Open localhost:3000 to see your application.

01-ajcwebdev-nuxt3-localhost-3000

Build for production

The yarn build command builds your Nuxt application for production. It creates a .output directory with your application, server, and dependencies ready to be deployed.

yarn build
Enter fullscreen mode Exit fullscreen mode

Nitro produces a standalone server dist that is independent of node_modules. The output is combined with both runtime code to run your Nuxt server in any environment and serve you static files. A native storage layer is also implemented for supporting multi source, drivers and local assets.

Pages directory

The pages/ directory is optional, meaning that if you only use app.vue, vue-router won't be included, reducing your application bundle size. However, if you do include it, Nuxt will automatically integrate Vue Router and map pages/ directory into the routes of your application.

rm -rf app.vue
mkdir pages
touch pages/about.vue pages/index.vue
Enter fullscreen mode Exit fullscreen mode

We deleted app.vue and will include the previous home page's content in index.vue.

<!-- pages/index.vue -->

<template>
  <div>
    <h2>ajcwebdev-nuxt3</h2>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

We also created about.vue for an about page. Include the following code to make sure that people know stuff about your things.

<!-- pages/about.vue -->

<template>
  <div>
    <h2>This page tells you stuff about things!</h2>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Open localhost:3000/about.

02-about-page-localhost-3000

Server Engine

Nuxt 3 is powered by a new server engine called Nitro. Nitro is used in development and production. It includes cross-platform support for Node.js, Browsers, and service-workers and serverless support out-of-the-box. Other features include API routes, automatic code-splitting, async-loaded chunks, and hybrid static/serverless modes. Server API endpoints and Middleware that internally uses h3 are added by Nitro.

  • Handlers can directly return objects/arrays for an automatically-handled JSON response
  • Handlers can return promises, which will be awaited (res.end() and next() are also supported)
  • Helper functions for body parsing, cookie handling, redirects, and headers

Nitro allows 'direct' calling of routes via the globally-available $fetch helper. This will make an API call to the server if run on the browser, but will simply call the relevant function if run on the server, saving an additional API call. The $fetch API uses ohmyfetch to:

  • Automatically parse JSON responses (with access to raw response if needed)
  • Automatically handle request body and params with correct Content-Type headers added

Server directory for API routes

The server/ directory contains API endpoints and server middleware for your project. It is used to create any backend logic for your Nuxt application. Nuxt will automatically read in any files in the ~/server/api directory to create API endpoints. Each file should export a default function that handles API requests.

mkdir -p server/api
touch server/api/hello.js
Enter fullscreen mode Exit fullscreen mode

Add the following code to hello.js.

// server/api/hello.js

export default (req, res) => '<h2>Hello from Nuxt 3</h2>'
Enter fullscreen mode Exit fullscreen mode

Open localhost:3000/api/hello.

03-hello-api-route-localhost-3000

Deploy to Netlify

What's the point of a framework if you can't deploy it on a Jamstack platform?

touch netlify.toml
Enter fullscreen mode Exit fullscreen mode
[build]
  command = "yarn build"
  publish = "dist"
  functions = ".output/server"

[[redirects]]
  from = "/*"
  to = "/.netlify/functions/index"
  status = 200
Enter fullscreen mode Exit fullscreen mode

Create GitHub Repository

git init
git add .
git commit -m "the nuxt best thing"
gh repo create ajcwebdev-nuxt3
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Connect your repo to your Netlify account.

04-connect-repo-to-netlify

The build command and publish directory will be included automatically from the netlify.toml file.

05-netlify-site-settings

Lastly, give yourself a custom domain.

06-add-custom-domain

Open ajcwebdev-nuxt3.netlify.app/.

07-ajcwebdev-nuxt3-netlify-deploy

Discussion (2)

Collapse
procrates profile image
Procrates

Hi Anthony! Great article:) How would you go about using netlify dev with nuxt 3 functions? Want to use ntl dev to have access to process.env.

I got the functions to work on ntl dev when i ran ntl build before ntl dev. If i make changes they dont work anymore unless i build again.

Thanks!

Collapse
ajcwebdev profile image
anthony-campolo Author

Hey @procrates 👋, thanks for the kind words!

I have not tried Netlify Dev with Nuxt 3 yet so unfortunately I do not have any great insights into your issue, but you might have some luck asking in the Nuxt Discord or the Netlify Forums.