How to Implement SSR in Nuxt.js for Vue Applications

Implement Server-Side Rendering (SSR) in Nuxt.js for your Vue applications. Our step-by-step guide ensures improved performance and SEO for Vue apps.

Server-side rendering (SSR) is a technique used to improve the performance and SEO of web applications by rendering HTML on the server rather than the client. Nuxt.js, a framework built on top of Vue.js, simplifies the process of setting up SSR for Vue applications. By using Nuxt.js, developers can create fast, dynamic, and SEO-friendly applications with ease.

In this article, we will explore how to implement SSR in Nuxt.js for Vue applications. We will cover the setup process, key features, and best practices to ensure your SSR implementation is effective and efficient.

Setting Up Nuxt.js for SSR

To get started with Nuxt.js, you need to install it in your project. You can create a new Nuxt.js project using the Nuxt CLI. Open your terminal and run the following command:

Installing Nuxt.js

To get started with Nuxt.js, you need to install it in your project. You can create a new Nuxt.js project using the Nuxt CLI. Open your terminal and run the following command:

npx create-nuxt-app my-nuxt-app

This command will prompt you to choose various options for your project, such as the package manager, UI framework, and modules. Select the options that best fit your project requirements. Once the setup is complete, navigate to your project directory:

cd my-nuxt-app

Configuring SSR

Nuxt.js supports SSR out of the box. By default, a newly created Nuxt.js application is configured for SSR. However, you can verify and customize the SSR configuration in the nuxt.config.js file. Ensure that the mode property is set to 'universal', which enables SSR:

export default {
  mode: 'universal',
  // Other configurations...
}

Running the Development Server

To run your Nuxt.js application in development mode with SSR enabled, use the following command:

npm run dev

Your application will be accessible at http://localhost:3000. At this point, you have a basic Nuxt.js application with SSR enabled.

Fetching Data Server-Side

Using asyncData

Nuxt.js provides the asyncData method to fetch data server-side before rendering the page. This method is called every time before loading the page component. It can be used to fetch data and make it available to the component during server-side rendering.

Here is an example of how to use asyncData in a page component:

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

<script>
export default {
  asyncData({ params }) {
    return fetch(`https://api.example.com/item/${params.id}`)
      .then(res => res.json())
      .then(data => {
        return { title: data.title, description: data.description }
      })
  }
}
</script>

In this example, the asyncData method fetches data from an API and returns it. The data is then available in the component as title and description.

Using fetch

Another method to fetch data server-side is the fetch method. Unlike asyncData, the fetch method does not replace the component’s data but instead populates the component’s store.

Here is an example of how to use the fetch method:

<template>
  <div>
    <h1>{{ item.title }}</h1>
    <p>{{ item.description }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      item: {}
    }
  },
  fetch() {
    return fetch(`https://api.example.com/item/1`)
      .then(res => res.json())
      .then(data => {
        this.item = data
      })
  }
}
</script>

In this example, the fetch method populates the item data property of the component with the fetched data.

Optimizing Performance with SSR

Caching is essential for improving the performance of SSR applications. By caching rendered pages or API responses, you can reduce server load and improve response times.

Caching

Caching is essential for improving the performance of SSR applications. By caching rendered pages or API responses, you can reduce server load and improve response times.

Server-Side Caching

Implementing server-side caching involves storing the rendered HTML of your pages in memory or a caching layer like Redis. This allows the server to serve cached pages for subsequent requests, reducing the need to re-render the page each time.

Here’s an example of setting up server-side caching with Nuxt.js and Redis:

// Install Redis client
npm install redis

// nuxt.config.js
import redis from 'redis'

const client = redis.createClient()

export default {
  // Other configurations...

  render: {
    cache: {
      client,
      // Default TTL for the cache in seconds
      ttl: 60
    }
  }
}

This configuration sets up a Redis client for caching rendered pages. The ttl property defines the time-to-live for cached pages, reducing the load on the server by serving cached content.

Client-Side Caching

Client-side caching involves using the browser’s caching mechanisms to store static assets and API responses. Configure your server to set appropriate cache-control headers for static files and API responses.

For static files, you can add the following to your nuxt.config.js:

export default {
  // Other configurations...

  render: {
    static: {
      maxAge: '1d' // Cache static files for one day
    }
  }
}

For API responses, ensure your server sets cache-control headers appropriately. Here’s an example of setting cache-control headers for an Express.js server:

// server.js
const express = require('express')
const app = express()

app.get('/api/data', (req, res) => {
  res.set('Cache-Control', 'public, max-age=86400') // Cache API response for one day
  res.json({ data: 'Sample data' })
})

app.listen(3000)

Lazy Loading

Lazy loading is a technique that defers the loading of non-essential resources until they are needed. This can significantly improve the initial load time of your SSR application.

Lazy Loading Components

Nuxt.js supports lazy loading of components out of the box. You can use dynamic imports to lazy load components. Here’s an example:

<template>
  <div>
    <h1>Home Page</h1>
    <LazyComponent v-if="showComponent" />
    <button @click="showComponent = true">Load Component</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showComponent: false
    }
  },
  components: {
    LazyComponent: () => import('@/components/LazyComponent.vue')
  }
}
</script>

In this example, the LazyComponent is only loaded when the showComponent data property is set to true.

Minification and Compression

Minifying and compressing your assets can reduce their size, resulting in faster load times. Nuxt.js supports these optimizations out of the box.

Minifying JavaScript and CSS

Nuxt.js automatically minifies JavaScript and CSS in production mode. You can configure additional options in the nuxt.config.js file:

export default {
  build: {
    // Enable minification for JavaScript and CSS
    terser: {
      terserOptions: {
        compress: {
          drop_console: true
        }
      }
    },
    extractCSS: true
  }
}

Enabling Compression

You can enable Gzip or Brotli compression for your Nuxt.js application by using the compression middleware. Here’s how to set it up:

// Install compression middleware
npm install compression

// nuxt.config.js
import compression from 'compression'

export default {
  serverMiddleware: [
    compression()
  ]
}

This configuration enables Gzip compression for your Nuxt.js application, reducing the size of the assets sent to the client.

Managing State in SSR

Nuxt.js integrates seamlessly with Vuex, a state management library for Vue.js. Using Vuex, you can manage the state of your application in a centralized store, ensuring consistency between server and client.

Using Vuex for State Management

Nuxt.js integrates seamlessly with Vuex, a state management library for Vue.js. Using Vuex, you can manage the state of your application in a centralized store, ensuring consistency between server and client.

Setting Up Vuex in Nuxt.js

Create a store directory in your project root, and add an index.js file to define your Vuex store:

// store/index.js
export const state = () => ({
  counter: 0
})

export const mutations = {
  increment(state) {
    state.counter++
  }
}

export const actions = {
  async fetchCounter({ commit }) {
    const response = await fetch('/api/counter')
    const data = await response.json()
    commit('setCounter', data.counter)
  }
}

export const mutations = {
  setCounter(state, counter) {
    state.counter = counter
  }
}

Accessing Store in Components

You can access the Vuex store in your components using the mapState helper:

<template>
  <div>
    <h1>{{ counter }}</h1>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState(['counter'])
  },
  methods: {
    ...mapMutations(['increment'])
  }
}
</script>

In this example, the counter state and increment mutation are accessed in the component using the mapState and mapMutations helpers.

Hydrating the State

When using SSR, the state needs to be transferred from the server to the client to ensure consistency. Nuxt.js automatically handles state hydration by serializing the Vuex state on the server and deserializing it on the client.

Handling Authentication and Authorization

Setting Up Authentication

Authentication is a critical aspect of any web application. With Nuxt.js, you can implement authentication using various strategies such as JWT (JSON Web Tokens) or OAuth. Nuxt.js provides a powerful module called @nuxtjs/auth-next that simplifies the process of adding authentication to your application.

Installing the Auth Module

To get started with the Nuxt Auth module, install it along with the Axios module, which is required for making HTTP requests:

npm install @nuxtjs/auth-next @nuxtjs/axios

Configuring the Auth Module

Add the Auth and Axios modules to your nuxt.config.js file and configure them:

export default {
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/auth-next'
  ],
  axios: {
    baseURL: 'https://api.example.com' // Replace with your API base URL
  },
  auth: {
    strategies: {
      local: {
        token: {
          property: 'token',
          global: true,
          required: true,
          type: 'Bearer'
        },
        user: {
          property: 'user',
          autoFetch: true
        },
        endpoints: {
          login: { url: '/auth/login', method: 'post', propertyName: 'token' },
          logout: { url: '/auth/logout', method: 'post' },
          user: { url: '/auth/user', method: 'get', propertyName: 'user' }
        }
      }
    }
  }
}

In this configuration, we set up a local authentication strategy with endpoints for login, logout, and fetching user information.

Using the Auth Module in Components

You can use the $auth object provided by the Auth module to handle authentication in your components:

<template>
  <div>
    <form @submit.prevent="login">
      <input v-model="email" type="email" placeholder="Email" />
      <input v-model="password" type="password" placeholder="Password" />
      <button type="submit">Login</button>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    async login() {
      try {
        await this.$auth.loginWith('local', {
          data: {
            email: this.email,
            password: this.password
          }
        })
      } catch (error) {
        console.error('An error occurred:', error)
      }
    }
  }
}
</script>

In this example, the login method uses the $auth object to log in the user with their email and password.

Implementing Authorization

Authorization involves restricting access to certain parts of your application based on user roles or permissions. With Nuxt.js, you can use middleware to protect routes and components.

Adding Middleware

Create a middleware file in the middleware directory to check for authentication:

// middleware/auth.js
export default function ({ $auth, redirect }) {
  if (!$auth.loggedIn) {
    return redirect('/login')
  }
}

In this middleware, we check if the user is authenticated. If not, they are redirected to the login page.

Protecting Routes

To protect routes, add the auth middleware to the pages that require authentication:

// pages/protected.vue
<template>
  <div>
    <h1>Protected Page</h1>
    <p>You are logged in as {{ $auth.user.email }}</p>
  </div>
</template>

<script>
export default {
  middleware: 'auth'
}
</script>

In this example, the auth middleware ensures that only authenticated users can access the protected page.

Handling User Roles

For more advanced authorization, you may need to manage user roles and permissions. You can extend the authentication setup to include role-based access control.

Defining Roles

Update your user fetching endpoint to include roles:

export default {
  auth: {
    strategies: {
      local: {
        // Other configurations...
        user: {
          property: 'user',
          autoFetch: true
        },
        endpoints: {
          user: { url: '/auth/user', method: 'get', propertyName: 'user' }
        }
      }
    }
  }
}

Ensure your API returns user roles as part of the user object.

Checking Roles in Middleware

Modify your middleware to check for specific roles:

// middleware/role.js
export default function ({ $auth, redirect }) {
  if (!$auth.loggedIn || $auth.user.role !== 'admin') {
    return redirect('/not-authorized')
  }
}

Use this middleware to protect routes that require specific roles:

// pages/admin.vue
<template>
  <div>
    <h1>Admin Page</h1>
    <p>Welcome, {{ $auth.user.email }}</p>
  </div>
</template>

<script>
export default {
  middleware: 'role'
}
</script>

In this example, only users with the ‘admin’ role can access the admin page.

Debugging and Error Handling

Handling errors gracefully is crucial for providing a good user experience. Nuxt.js provides several ways to handle errors in SSR applications.

Handling Errors in SSR

Handling errors gracefully is crucial for providing a good user experience. Nuxt.js provides several ways to handle errors in SSR applications.

Error Pages

Nuxt.js allows you to customize error pages by creating an error.vue file in the layouts directory:

// layouts/error.vue
<template>
  <div>
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.message }}</p>
  </div>
</template>

<script>
export default {
  props: ['error']
}
</script>

This custom error page will be displayed when an error occurs during SSR.

Error Handling in asyncData and fetch

You can handle errors in the asyncData and fetch methods by using try-catch blocks:

export default {
  async asyncData({ params, error }) {
    try {
      const res = await fetch(`https://api.example.com/item/${params.id}`)
      const data = await res.json()
      return { item: data }
    } catch (err) {
      error({ statusCode: 404, message: 'Item not found' })
    }
  }
}

In this example, if an error occurs while fetching data, a custom error message is returned.

Advanced Features and Techniques

Using Plugins for Extending Functionality

Nuxt.js supports plugins that allow you to extend its core functionality. Plugins are useful for adding global functionalities, initializing third-party libraries, or providing reusable functions across your application.

Creating a Plugin

Create a plugins directory in your project and add a JavaScript file for your plugin. For example, to initialize a third-party library like Axios globally:

// plugins/axios.js
import axios from 'axios'

export default ({ app }, inject) => {
  const instance = axios.create({
    baseURL: 'https://api.example.com'
  })

  // Inject to context as $axios
  inject('axios', instance)
}

Registering the Plugin

Register your plugin in the nuxt.config.js file:

export default {
  // Other configurations...

  plugins: [
    '~/plugins/axios.js'
  ]
}

Now, you can use the $axios instance in your components and pages:

<template>
  <div>
    <h1>Data from API</h1>
    <p>{{ data }}</p>
  </div>
</template>

<script>
export default {
  asyncData({ $axios }) {
    return $axios.get('/data')
      .then(response => {
        return { data: response.data }
      })
  }
}
</script>

Middleware for Custom Logic

Middleware in Nuxt.js allows you to run custom logic before rendering a page or during navigation. This is particularly useful for authentication checks, logging, or any other pre-render logic.

Creating Middleware

Create a middleware file in the middleware directory. For example, to log each page visit:

// middleware/log.js
export default function ({ route }) {
  console.log(`Navigating to ${route.fullPath}`)
}

Applying Middleware Globally

You can apply middleware globally by adding it to the nuxt.config.js file:

export default {
  // Other configurations...

  router: {
    middleware: 'log'
  }
}

Using Middleware on Specific Pages

Alternatively, you can apply middleware to specific pages:

// pages/specific-page.vue
<template>
  <div>
    <h1>Specific Page</h1>
    <p>Only this page uses the log middleware</p>
  </div>
</template>

<script>
export default {
  middleware: 'log'
}
</script>

Nuxt.js Modules for Enhanced Functionality

Nuxt.js provides a rich ecosystem of modules that can add powerful features to your application. These modules can help with everything from state management to performance optimization.

Using the PWA Module

Progressive Web Applications (PWAs) provide a native app-like experience on the web. Nuxt.js offers a PWA module to easily integrate PWA features into your application.

Installing the PWA Module

Install the PWA module:

npm install @nuxtjs/pwa
Configuring the PWA Module

Add the PWA module to your nuxt.config.js file and configure it:

export default {
  // Other configurations...

  modules: [
    '@nuxtjs/pwa'
  ],
  pwa: {
    manifest: {
      name: 'My Nuxt PWA',
      lang: 'en',
      useWebmanifestExtension: false
    },
    workbox: {
      // Workbox options for offline support
    }
  }
}

This configuration enables PWA features like a web manifest and offline support through Workbox.

Using the Content Module

The Nuxt Content module allows you to write content in Markdown, JSON, YAML, and XML and access it via a Vue component. It’s particularly useful for blogs or documentation sites.

Installing the Content Module

Install the Content module:

npm install @nuxt/content
Configuring the Content Module

Add the Content module to your nuxt.config.js file:

export default {
  // Other configurations...

  modules: [
    '@nuxt/content'
  ]
}
Creating and Accessing Content

Create a content directory in your project root and add Markdown files:

// content/hello.md
---
title: 'Hello, Nuxt Content'
description: 'A simple example of using Nuxt Content module.'
---

# Hello, Nuxt Content

This is an example of content written in Markdown.

Access and display the content in your components:

<template>
  <div>
    <h1>{{ article.title }}</h1>
    <nuxt-content :document="article" />
  </div>
</template>

<script>
export default {
  async asyncData({ $content }) {
    const article = await $content('hello').fetch()
    return { article }
  }
}
</script>

Deploying Your Nuxt.js SSR Application

Deploying your Nuxt.js SSR application requires setting up a server to handle requests and render pages server-side.

Building for Production

First, build your application for production:

npm run build

Setting Up a Node.js Server

Create a server file (e.g., server.js) to run your Nuxt.js application:

const { Nuxt, Builder } = require('nuxt')
const express = require('express')
const app = express()

// Import and set Nuxt options
const config = require('./nuxt.config.js')
config.dev = false

const nuxt = new Nuxt(config)

// Build only in dev mode
if (config.dev) {
  const builder = new Builder(nuxt)
  builder.build()
}

// Give Nuxt middleware to express
app.use(nuxt.render)

// Listen the server
app.listen(3000, '0.0.0.0')
console.log('Server is listening on http://localhost:3000')

Running the Server

Start your server:

node server.js

Your Nuxt.js SSR application is now running in production mode, ready to handle requests and serve content dynamically.

Optimizing for Production

Using a CDN

Integrate a Content Delivery Network (CDN) to serve static assets faster and reduce server load. Configure your nuxt.config.js to use a CDN:

export default {
  // Other configurations...

  build: {
    publicPath: 'https://cdn.example.com/_nuxt/'
  }
}

Environment Variables

Use environment variables to manage configuration settings for different environments (development, staging, production). Nuxt.js supports .env files to define environment variables:

# .env
API_URL=https://api.example.com

Access these variables in your nuxt.config.js:

require('dotenv').config()

export default {
  env: {
    apiUrl: process.env.API_URL
  }
}

Performance Monitoring

Implement performance monitoring to track your application’s performance and identify bottlenecks. Tools like New Relic or Datadog can provide real-time insights into your server’s performance.

Advanced SEO Strategies for SSR in Nuxt.js

Structured data helps search engines understand the content of your pages. Implementing structured data using JSON-LD can enhance your SEO by providing additional context.

Structured Data for Better SEO

Structured data helps search engines understand the content of your pages. Implementing structured data using JSON-LD can enhance your SEO by providing additional context.

Adding Structured Data

You can add structured data in Nuxt.js by injecting JSON-LD scripts into your pages. Here’s an example of how to add structured data to a page:

<template>
  <div>
    <h1>{{ article.title }}</h1>
    <p>{{ article.description }}</p>
  </div>
</template>

<script>
export default {
  async asyncData({ params }) {
    const res = await fetch(`https://api.example.com/articles/${params.id}`)
    const article = await res.json()
    return { article }
  },
  head() {
    return {
      script: [
        {
          type: 'application/ld+json',
          json: {
            '@context': 'https://schema.org',
            '@type': 'Article',
            headline: this.article.title,
            description: this.article.description,
            author: {
              '@type': 'Person',
              name: 'Author Name'
            },
            datePublished: this.article.datePublished
          }
        }
      ]
    }
  }
}
</script>

In this example, the head method is used to inject structured data into the page’s <head> section. The JSON-LD script provides detailed information about the article, which helps search engines understand and rank the content better.

Optimizing Meta Tags

Meta tags are crucial for SEO and social sharing. Ensure your pages include appropriate meta tags such as titles, descriptions, and Open Graph tags.

Setting Meta Tags

Nuxt.js makes it easy to set meta tags using the head method. Here’s an example of how to set meta tags for a page:

<template>
  <div>
    <h1>{{ article.title }}</h1>
    <p>{{ article.description }}</p>
  </div>
</template>

<script>
export default {
  async asyncData({ params }) {
    const res = await fetch(`https://api.example.com/articles/${params.id}`)
    const article = await res.json()
    return { article }
  },
  head() {
    return {
      title: this.article.title,
      meta: [
        { hid: 'description', name: 'description', content: this.article.description },
        { property: 'og:title', content: this.article.title },
        { property: 'og:description', content: this.article.description },
        { property: 'og:type', content: 'article' }
      ]
    }
  }
}
</script>

In this example, the head method is used to set the page title and meta tags dynamically based on the article’s data.

Generating Sitemaps

A sitemap helps search engines crawl and index your site more effectively. Nuxt.js provides a module to generate sitemaps automatically.

Installing the Sitemap Module

Install the sitemap module:

npm install @nuxtjs/sitemap

Configuring the Sitemap Module

Add the sitemap module to your nuxt.config.js file and configure it:

export default {
  // Other configurations...

  modules: [
    '@nuxtjs/sitemap'
  ],
  sitemap: {
    hostname: 'https://example.com',
    routes: async () => {
      const res = await fetch('https://api.example.com/articles')
      const articles = await res.json()
      return articles.map(article => `/articles/${article.id}`)
    }
  }
}

In this configuration, the routes function fetches article data from an API and generates URLs for the sitemap.

Improving Page Speed

Page speed is a significant factor in SEO. Nuxt.js offers several features and best practices to improve the performance of your SSR application.

Lazy Loading Images

Lazy loading images can significantly improve page speed by deferring the loading of images until they are needed. You can use a Vue.js plugin like vue-lazyload to implement lazy loading in Nuxt.js.

Installing Vue-Lazyload

Install the vue-lazyload plugin:

npm install vue-lazyload
Configuring Vue-Lazyload

Create a plugin file to configure vue-lazyload:

// plugins/vue-lazyload.js
import Vue from 'vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'error.png',
  loading: 'loading.gif',
  attempt: 1
})

Register the plugin in your nuxt.config.js file:

export default {
  // Other configurations...

  plugins: [
    '~/plugins/vue-lazyload.js'
  ]
}

Use the lazy load directive in your components:

<template>
  <div>
    <img v-lazy="'/path/to/image.jpg'" alt="Lazy loaded image">
  </div>
</template>

Minifying HTML

Minifying HTML reduces the size of the HTML files sent to the client, improving load times. Nuxt.js supports HTML minification out of the box for production builds.

Ensure HTML minification is enabled in your nuxt.config.js file:

export default {
  build: {
    html: {
      minify: {
        collapseWhitespace: true,
        removeComments: true,
        removeRedundantAttributes: true,
        removeScriptTypeAttributes: true,
        removeStyleLinkTypeAttributes: true,
        useShortDoctype: true
      }
    }
  }
}

Pre-rendering Pages

Pre-rendering pages can enhance performance and SEO by generating static HTML for specific routes. Nuxt.js supports static site generation (SSG) out of the box.

Enabling Static Site Generation

To enable static site generation, set the target property to static in your nuxt.config.js file:

export default {
  target: 'static'
}

Generating Static Pages

Use the generate command to pre-render your site:

npm run generate

This command generates static HTML files for your application, which can be served by a static hosting provider like Netlify or Vercel.

Monitoring and Analyzing SEO Performance

Monitoring and analyzing your site’s SEO performance helps you identify areas for improvement and track the effectiveness of your SEO strategies.

Using Google Search Console

Google Search Console provides valuable insights into your site’s SEO performance. Set up Google Search Console for your site to monitor search traffic, index coverage, and identify issues.

Implementing Analytics

Integrate analytics tools like Google Analytics or Matomo to track user behavior and measure the impact of your SEO efforts. Use the Nuxt.js @nuxtjs/google-analytics module to add Google Analytics to your site:

Installing Google Analytics Module

Install the Google Analytics module:

npm install @nuxtjs/google-analytics
Configuring Google Analytics

Add the Google Analytics module to your nuxt.config.js file and configure it with your tracking ID:

export default {
  // Other configurations...

  modules: [
    '@nuxtjs/google-analytics'
  ],
  googleAnalytics: {
    id: 'UA-XXXXXXX-X' // Replace with your Google Analytics tracking ID
  }
}

Continuous SEO Improvement

SEO is an ongoing process that requires continuous monitoring and adjustment. Regularly update your content, monitor your site’s performance, and adapt your strategies to align with the latest SEO best practices.

Conclusion

Implementing server-side rendering (SSR) in Nuxt.js for Vue applications provides significant benefits in terms of performance, SEO, and user experience. By leveraging Nuxt.js’s robust features and modules, you can create dynamic, fast, and highly optimized web applications. Key strategies include setting up efficient data fetching methods like asyncData and fetch, optimizing performance with caching and lazy loading, and managing state with Vuex. Ensuring strong authentication and authorization mechanisms protects your application and users. Advanced SEO techniques, such as structured data and optimized meta tags, further enhance your site’s visibility and ranking. Regular monitoring, performance optimizations, and continuous improvement of SEO practices ensure your application remains competitive and performant. With these strategies, you can fully harness the power of SSR in Nuxt.js to deliver exceptional web applications.

Read Next: