Lesson 01-Getting Started with Nuxt.js Basics

Introduction

Nuxt.js is a framework based on Vue.js that supports Server-Side Rendering (SSR) and Static Site Generation (SSG). It provides a straightforward way to build high-performance Vue.js applications. Nuxt.js automates many best practices, such as routing, state management, and optimization, allowing developers to focus on business logic rather than framework details.

Installation

To start using Nuxt.js, ensure you have Node.js and npm installed. Once your environment is set up, create a new Nuxt.js project with the following command:

npx create-nuxt-app my-nuxt-project

This will guide you through the project initialization process, where you can customize options such as using TypeScript, selecting a CSS preprocessor, and more.

Basic Configuration

After creating the project, you can customize its configuration by editing the nuxt.config.js file located in the project’s root directory. This file is used to override Nuxt.js’s default behavior.

Configuration Example

Here’s a simple nuxt.config.js example:

// nuxt.config.js
export default {
  // Target (https://go.nuxtjs.dev/config-target)
  target: 'static',

  // Global page headers (https://go.nuxtjs.dev/config-head)
  head: {
    title: 'my-nuxt-project',
    htmlAttrs: {
      lang: 'en',
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' },
      { name: 'format-detection', content: 'telephone=no' },
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
    ],
  },

  // Global CSS (https://go.nuxtjs.dev/config-css)
  css: [
    '~assets/scss/main.scss',
  ],

  // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
  plugins: [
    '~/plugins/my-plugin.js',
  ],

  // Auto import components (https://go.nuxtjs.dev/config-components)
  components: true,

  // Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
  buildModules: [
    // https://go.nuxtjs.dev/eslint
    '@nuxtjs/eslint-module',
    // https://go.nuxtjs.dev/tailwindcss
    '@nuxtjs/tailwindcss',
  ],

  // Modules (https://go.nuxtjs.dev/config-modules)
  modules: [
    // https://go.nuxtjs.dev/axios
    '@nuxtjs/axios',
    // https://go.nuxtjs.dev/pwa
    '@nuxtjs/pwa',
  ],

  // Axios module configuration (https://go.nuxtjs.dev/config-axios)
  axios: {},

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {},
};

Directory Structure

The typical directory structure of a Nuxt.js project is as follows:

my-nuxt-project/
├── .nuxt/              # Nuxt-generated folder containing compiled files
├── assets/             # Static assets like CSS, JavaScript, images, etc.
├── components/         # Vue components
├── layouts/            # Page layouts
├── middleware/         # Middleware
├── pages/              # Vue pages
├── plugins/            # Plugins
├── static/             # Static files, copied to the output directory
├── store/              # Vuex store
├── nuxt.config.js      # Nuxt.js configuration file
├── package.json        # Project dependencies
└── ...
  • .nuxt/: Auto-generated by Nuxt, contains compiled files.
  • assets/: Stores static assets like CSS, JavaScript, and images.
  • components/: Vue components.
  • layouts/: Page layouts.
  • middleware/: Middleware for operations before or after page loading.
  • pages/: Vue pages, each file corresponding to a URL.
  • plugins/: Plugins to extend Vue instance functionality.
  • static/: Static files, copied directly to the output directory.
  • store/: Vuex store for managing application state.

Running the Project

After installing dependencies and configuring the project, start the development server with:

npm run dev

Or, if using Yarn:

yarn dev

This launches a development server that watches for file changes, automatically recompiling and refreshing the browser.

Views

Views are a core part of Nuxt.js applications, responsible for displaying data to users. Nuxt.js uses Vue.js Single File Components (SFCs) as the building blocks for views.

Creating Views

View files are typically placed in the pages/ directory, with each file representing a view and its filename determining the corresponding URL.

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from Nuxt.js!',
    };
  },
};
</script>

Styles

Nuxt.js supports multiple CSS preprocessors, including SCSS, SASS, LESS, and Stylus. Style files can be placed in the assets/ directory and specified in nuxt.config.js.

Using Global Styles

Create a style file in the assets/ directory and declare it in nuxt.config.js.

Example:

// nuxt.config.js
export default {
  css: ['~/assets/scss/main.scss'],
};

main.scss file content:

// assets/scss/main.scss
body {
  font-family: 'Arial', sans-serif;
  background-color: #f4f4f4;
}

Using Local Styles

Use scoped styles within individual components or pages.

// pages/index.vue
<template>
  <div class="welcome">
    <h1>Welcome to Nuxt.js!</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from Nuxt.js!',
    };
  },
};
</script>

<style scoped>
.welcome {
  background-color: #fff;
  padding: 20px;
  border: 1px solid #ccc;
}
</style>

Assets

Asset files (e.g., images, fonts) are typically placed in the static/ directory. These files are copied directly to the output directory.

<!-- pages/index.vue -->
<img src="~/static/images/logo.png" alt="Logo" />

Basic Application

Layouts

Layouts define the common structure of pages, such as headers and footers, reducing repetitive code.

Creating a Layout

Layout files are typically placed in the layouts/ directory.

// layouts/default.vue
<template>
  <div>
    <header>
      <nav>
        <ul>
          <li><a href="/">Home</a></li>
          <li><a href="/about">About</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <nuxt />
    </main>
    <footer>
      <p{{ new Date().getFullYear() }} My App</p>
    </footer>
  </div>
</template>

Using the Default Layout:

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from Nuxt.js!',
    };
  },
};
</script>

Using Multiple Layouts

Create multiple layout files in the layouts/ directory and selectively use them in pages.

// layouts/admin.vue
<template>
  <div>
    <header>
      <nav>
        <ul>
          <li><a href="/admin">Admin Dashboard</a></li>
          <li><a href="/admin/settings">Settings</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <nuxt />
    </main>
    <footer>
      <p{{ new Date().getFullYear() }} Admin Panel</p>
    </footer>
  </div>
</template>

Using a Specific Layout in a Page:

// pages/admin/index.vue
<template>
  <div>
    <h1>Welcome to the Admin Panel!</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  layout: 'admin',
  data() {
    return {
      message: 'Hello from Admin Panel!',
    };
  },
};
</script>

Components

Components are the fundamental building blocks in Vue.js and a key part of Nuxt.js applications.

Creating Components

Component files are typically placed in the components/ directory.

// components/HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  props: {
    msg: String,
  },
};
</script>

<style scoped>
.hello {
  color: #42b983;
}
</style>

Using Components in Pages:

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <HelloWorld msg="Hello from Nuxt.js!" />
  </div>
</template>

<script>
import HelloWorld from '~/components/HelloWorld.vue';

export default {
  components: {
    HelloWorld,
  },
};
</script>

Dynamic Routing

Dynamic routing allows you to create different pages based on parameters.

Creating Dynamic Pages

Create folders starting with square brackets in the pages/ directory.

// pages/posts/_id.vue
<template>
  <div>
    <h1>Post ID: {{ id }}</h1>
    <p>{{ post.title }}</p>
  </div>
</template>

<script>
export default {
  asyncData({ params, $axios }) {
    return $axios.$get(`/api/posts/${params.id}`).then(res => {
      return { post: res };
    });
  },
};
</script>

URL Examples:

/posts/1
/posts/2

Asynchronous Data

Asynchronous data fetching allows you to retrieve data from the server when a page loads.

Using the asyncData Function

Use the asyncData function in components or pages to fetch asynchronous data.

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios }) {
    const response = await $axios.$get('/api/data');
    return { message: response.message };
  },
};
</script>

Vuex Store

Vuex is the official state management library for Vue.js, and Nuxt.js provides built-in support.

Creating a Vuex Store

Create a Vuex store in the store/ directory.

// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
  actions: {
    increment({ commit }) {
      commit('increment');
    },
  },
  getters: {
    count: state => state.count,
  },
});

Using Vuex in Pages:

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
export default {
  computed: {
    count() {
      return this.$store.getters.count;
    },
  },
  methods: {
    increment() {
      this.$store.dispatch('increment');
    },
  },
};
</script>

Middleware

Middleware allows you to execute logic before or after page loading.

Creating Middleware

Create middleware in the middleware/ directory.

// middleware/authenticated.js
export default function ({ store, redirect }) {
  if (!store.getters['auth/isAuthenticated']) {
    return redirect('/login');
  }
}

Using Middleware in Pages:

// pages/admin/index.vue
export default {
  middleware: 'authenticated',
};

Plugins

Plugins extend the functionality of Vue instances, such as adding global methods, mixins, or event listeners.

Creating Plugins

Create plugin files in the plugins/ directory.

// plugins/vuetify.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';

Vue.use(Vuetify);

export default new Vuetify({
  theme: {
    themes: {
      light: {
        primary: '#3f51b5',
        secondary: '#b0bec5',
        accent: '#8c9eff',
        error: '#b71c1c',
      },
    },
  },
});

Register the plugin in nuxt.config.js:

// nuxt.config.js
export default {
  plugins: ['~/plugins/vuetify.js'],
};

Internationalization

Nuxt.js supports various internationalization solutions, such as nuxt-i18n.

Install nuxt-i18n

npm install --save nuxt-i18n

Configure nuxt-i18n in nuxt.config.js:

// nuxt.config.js
export default {
  i18n: {
    locales: [
      { code: 'en', iso: 'en-US', file: 'en-US.js' },
      { code: 'zh', iso: 'zh-CN', file: 'zh-CN.js' },
    ],
    defaultLocale: 'en',
    vueI18n: {
      fallbackLocale: 'en',
      messages: {},
    },
  },
};

Create Language Files:

// locales/en-US.js
export default {
  message: 'Hello from Nuxt.js!',
};

// locales/zh-CN.js
export default {
  message: '你好,来自 Nuxt.js!',
};

Using Internationalization in Pages:

// pages/index.vue
<template>
  <div>
    <h1>Welcome to Nuxt.js!</h1>
    <p>{{ $t('message') }}</p>
  </div>
</template>

SEO and Meta Tags

Nuxt.js provides strong support for SEO, allowing customization of meta tags via the head property.

Customizing Meta Tags

Use the head property in pages to customize meta tags.

// pages/index.vue
export default {
  head() {
    return {
      title: 'Welcome to Nuxt.js!',
      meta: [
        { hid: 'description', name: 'description', content: 'My amazing Nuxt.js application' },
      ],
    };
  },
};

Code Splitting

Nuxt.js supports dynamic imports for on-demand loading and code splitting.

Using Dynamic Imports

Use import() in asyncData or fetch methods for code splitting.

// pages/posts/_id.vue
export default {
  async asyncData({ params, $axios }) {
    const Post = await import('~/models/Post');
    const post = await $axios.$get(`/api/posts/${params.id}`);
    return { post: new Post(post) };
  },
};

Error Handling

Nuxt.js provides mechanisms for handling errors at a global level.

Global Error Handling

Handle errors in the pages/_error.vue file.

// pages/_error.vue
<template>
  <div>
    <h1>Error {{ statusCode }}</h1>
    <p>{{ errorMessage }}</p>
  </div>
</template>

<script>
export default {
  props: {
    statusCode: Number,
    errorMessage: String,
  },
};
</script>

Configure error handling in nuxt.config.js:

// nuxt.config.js
export default {
  error: {
    statusCode: 500,
    message: 'Internal Server Error',
  },
};

Server-Side Rendering (SSR)

Nuxt.js supports server-side rendering by default, significantly improving first-page load speed and SEO.

Configuring SSR

Control the rendering mode via the target configuration option.

// nuxt.config.js
export default {
  target: 'server',
};

Static Site Generation (SSG)

Nuxt.js supports static site generation, creating pre-rendered HTML files.

Configuring SSG

Enable SSG by setting the target configuration option to static.

// nuxt.config.js
export default {
  target: 'static',
};

Production Deployment

Nuxt.js supports various deployment methods, including traditional server deployment and modern serverless deployment.

Traditional Server Deployment

Use nuxt build and nuxt start commands to build and start the production application.

npm run build
npm run start

Serverless Deployment

Deploy to platforms like Netlify or Vercel for serverless deployment.

# Deploy with Vercel
vercel

Performance Optimization

Nuxt.js offers various performance optimization techniques, including lazy loading and caching strategies.

Lazy Loading

Use import() in asyncData or fetch methods for code splitting.

// pages/posts/_id.vue
export default {
  async asyncData({ params, $axios }) {
    const Post = await import('~/models/Post');
    const post = await $axios.$get(`/api/posts/${params.id}`);
    return { post: new Post(post) };
  },
};

Caching Strategies

Leverage browser caching, CDN caching, and other strategies to reduce network requests.

// nuxt.config.js
export default {
  router: {
    base: process.env.BASE_URL,
  },
};

Appendix: Frequently Asked Questions

Q: How do I use Vuex in Nuxt.js?
A: Create Vuex store files in the store/ directory, then access them in pages or components using $store.

Q: How do I use Vue Router in Nuxt.js?
A: Nuxt.js has built-in routing, so Vue Router is not required. Page file names determine route paths.

Q: How do I handle API requests in Nuxt.js?
A: Use $axios in asyncData or fetch methods to handle API requests.

Q: How do I use third-party libraries in Nuxt.js?
A: Install libraries via npm or Yarn, then create plugin files in the plugins/ directory to register and configure them.

Q: How do I implement multi-language support in Nuxt.js?
A: Use the nuxt-i18n plugin for multi-language support, configuring it in nuxt.config.js and using the $t function in pages to switch languages.

Share your love