Nuxt.js实际应用:Vue.js服务器端渲染框架
创建 Nuxt.js 项目Create a Nuxt.js project
首先确保你已经安装了 Node.js 和 yarn 或 npm。然后通过命令行创建一个新的 Nuxt.js 项目:
yarn create nuxt-app my-nuxt-project cd my-nuxt-project
在创建过程中您可以选择是否需要UI框架,预处理器等选项,并根据需要进行配置。
目录结构
**Nuxt.js 遵循特定的目录结构,一些关键目录如下:**
├── .nuxt/ # Automatically generated files, including compiled code and configuration ├── assets/ # Used to store uncompiled static resources, such as CSS, images, fonts ├── components/ # Custom Vue components ├── layouts/ # Application layout files, defining the general structure of the page │ └── default.vue # Default layout ├── middleware/ # Middleware files ├── pages/ # Application routes and views, each file corresponds to a route │ ├── index.vue # Default homepage │ └── [slug].vue # Dynamic routing example ├── plugins/ # Custom Vue.js plugins ├── static/ # Static resources, will be copied to the output directory as is ├── store/ # Vuex state management file │ ├── actions.js # Vuex actions │ ├── mutations.js # Vuex mutations │ ├── getters.js # Vuex getters │ └── index.js # Vuex store entry file ├── nuxt.config.js # Nuxt.js configuration file ├── package.json # Project dependencies and scripts └── yarn.lock # Or npm.lock, record dependency versions
页面渲染
在 pages/ 目录中创建一个 index.vue 文件。这是应用程序的主页:
Hello from Nuxt.js SSR
{{ message }}
Nuxt.js 页面渲染的过程主要分为两个阶段:服务端渲染(SSR)和客户端渲染(CSR)。下面是 Nuxt.js 页面渲染的详细步骤:
初始化:
用户在浏览器中输入URL并向服务器发送请求。
服务器收到请求后,开始处理。
路线解析:
Nuxt.js 使用 `nuxt.config.js` 中的 `routes` 配置(如果存在)或从 pages/ 目录自动生成路由。
识别相应的页面文件,例如“pages/index.vue”或“pages/about.vue”。
数据预取:
Nuxt.js 在页面组件中查找“asyncData”或“fetch”方法(如果存在)。
这些方法将在服务器端运行,以从 API 或其他数据源获取数据。
获取到数据之后会序列化并注入到页面模板中。
模板渲染:
Nuxt.js 使用 Vue.js 的渲染引擎将组件和预取数据转换为 HTML 字符串。
HTML 字符串包含客户端所需的所有初始数据,内联在`
Return HTML:
The server sends the generated HTML response back to the client (browser).
Client initialization:
After the browser receives the HTML, it begins parsing and executing inline JavaScript.
The Nuxt.js client library (`nuxt.js`) is loaded and initialized.
Client rendering:
The client library takes over the rendering, the Vue.js instance is created, and the data is injected from the inline JSON into the Vue instance.
The page completes the initial rendering and the user can see the complete page content.
At this point, the page is interactive and the user can trigger events and navigate.
Subsequent navigation:
When the user navigates to other pages, Nuxt.js uses client-side routing (Vue Router) for non-refresh jumps.
If the new page requires data, the `asyncData` or `fetch` method will run on the client, fetch the new data and update the view.
SSG (Static Site Generation):
Outside of development, you can use the nuxt generate command to generate static HTML files.
Each page will be pre-rendered as a separate HTML file with all the necessary data and resources.
Using asyncData
The `asyncData` method is unique to Nuxt.js and allows you to pre-fetch data on the server and reuse it on the client. In the example above, we simply changed the value of message, but in a real application, you might call an API to fetch data here.
Middleware
Middleware (`Middleware`) is a feature that allows you to execute specific logic before and after route changes. Middleware can be used globally, at the page level, or at the layout level to handle tasks such as authentication, data preloading, route guards, etc.
1. Global middleware
Global middleware is configured in the nuxt.config.js file and affects all pages in the application:
// nuxt.config.js export default { // ... router: { middleware: ['globalMiddleware1', 'globalMiddleware2'] // can be a string array } };
Middleware files are usually located in the middleware/directory, such as middleware/globalMiddleware1.js:
// middleware/globalMiddleware1.js export default function (context) { // context contains information such as req, res, redirect, app, route, store, etc. console.log('Global Middleware 1 executed'); }
2. Page-level middleware
Page-level middleware only affects specific pages. Declare middleware in the page component:
// pages/about.vue export default { middleware: 'pageMiddleware' // can be a string or a function };
The corresponding middleware file is located in the middleware/directory, for example, middleware/pageMiddleware.js:
// middleware/pageMiddleware.js export default function (context) { console.log('Page Middleware executed'); }
3. Layout-level middleware
Layout-level middleware is similar to page-level, but it applies to all pages that use the layout. Declare middleware in the layout component:
// layouts/default.vue export default { middleware: ['layoutMiddleware1', 'layoutMiddleware2'] };
The corresponding middleware file is located in the middleware/directory:
// middleware/layoutMiddleware1.js export default function (context) { console.log('Layout Middleware 1 executed'); } // middleware/layoutMiddleware2.js export default function (context) { console.log('Layout Middleware 2 executed'); }
Context of middleware
The middleware function receives a context object as a parameter, which contains the following properties:
Middleware can be executed sequentially, and each middleware can decide whether to continue executing the next middleware in the chain or interrupt the route through the redirect function.
Dynamic Routing
`Nuxt.js` supports dynamic routing, which is very useful for handling content with dynamic IDs such as blog posts, user profiles, etc. Create a dynamic routing file in the pages/ directory, such as [id].vue:
{{ post.title }}
{{ post.content }}
Here [id] represents a dynamic parameter, asyncData will automatically process this parameter and get the blog post with the corresponding ID.
**Layout**
Layout allows you to define the common structure of global or specific pages. Create a default.vue file in the layouts/ directory:
By default, all pages will use this layout. If you want to set a different layout for a specific page, you can specify it in the page component:
// pages/about.vue export default { layout: 'custom' // Create custom.vue under layouts/ };
**Plugin and library integration**
Nuxt.js supports Vue.js plugins, which you can configure in nuxt.config.js:
// nuxt.config.js export default { plugins: [ { src: '~plugins/vuetify.js', ssr: true }, { src: '~plugins/vue-chartjs.js', mode: 'client' } // Run only on the client side ] };
Then create the corresponding files in the `plugins/` directory, such as `vuetify.js`:
// plugins/vuetify.js import Vue from 'vue'; import Vuetify from 'vuetify'; import 'vuetify/dist/vuetify.min.css'; Vue.use(Vuetify);
Configuration and Optimization
Nuxt.js Configuration File (nuxt.config.js)
`nuxt.config.js` is the main configuration file for Nuxt applications, which is used to customize the behavior of the application. Here are some commonly used configuration items:
// nuxt.config.js export default { // Project Name name: 'my-nuxt-app', // Project mode: spa, universal, static mode: 'universal', // Default value, supports server-side rendering // Application meta information head: { title: 'My Nuxt App', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: 'App description' } ], link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] }, // CSS Styles css: [ '@/assets/css/main.css' ], // Routing Configuration router: { base: '/my-nuxt-app/', // The base path of the application extendRoutes(routes, resolve) { // Manually extend or modify routes } }, // Build Configuration build: { transpile: [/^my-vue-component/], // Modules that need to be translated vendor: ['lodash'], // Public library, pre-packaged extractCSS: true, // Extract CSS to a separate file optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, filename: 'vendors.js' } } } } }, // Axios configuration axios: { baseURL: process.env.BASE_URL || 'http://localhost:3000/api', // API base URL browserBaseURL: 'https://api.example.com' // Client API base URL }, // Plugins plugins: [ { src: '@/plugins/vue-my-plugin', ssr: false } // Asynchronously loaded plugin, ssr: false means only client loading ], // Modules modules: [ '@nuxtjs/axios', // Install and configure axios module '@nuxtjs/pwa' // Install and configure PWA module ], // Environment variables env: { apiKey: 'your-api-key', apiUrl: 'https://api.example.com' }, // Vuex Store configuration store: true, // Automatically create Vuex store loading: { color: '#3B8070' }, // Loading indicator color // Server-side middleware serverMiddleware: [ { path: '/api', handler: '~/api/index.js' } // Use custom server-side middleware ], // Static generation configuration generate: { dir: 'dist', // Output directory fallback: true, // Generate 404 page for dynamic routes that are not pre-rendered routes: () => ['/about', '/contact'] // Pre-rendered specified routes } };
Optimization strategy
Static Site Generation (SSG)
Nuxt.js's static site generation (SSG) is implemented through the `nuxt generate` command. This command traverses the application's routes and generates a pre-rendered HTML file for each route, which can be directly deployed to any static file hosting service. Here are some key points about SSG:
**1. Configuration**: In the nuxt.config.js file, you can configure the generate option to control the behavior of static generation:
export default { generate: { dir: 'dist', // Output directory, default is dist fallback: true, // Generate 404 page for dynamic routes that are not pre-rendered routes: () => ['/about', '/contact'], // Predefined static routes exclude: ['/admin/*'], // Exclude certain routes interval: 5000, // Generation interval, in milliseconds concurrency: 10 // Number of concurrently generated routes } }
**2. Generate**: Run `npm run generate` or `yarn generate` to start the static generation process. Nuxt.js will generate the corresponding HTML file according to the configuration in `generate.routes`. If not explicitly defined, it will automatically scan all files under the `pages/` directory to generate routes.
**3. Data prefetching**: In the page component, you can use the asyncData or fetch method to prefetch data. This data will be injected into the HTML when the static page is generated, so that the page does not require additional requests when the client loads:
// pages/about.vue export default { async asyncData({ params, $axios }) { const aboutInfo = await $axios.$get('/api/about') return { aboutInfo } } }
**4. Middleware processing**: Server-side middleware will not be executed during the SSG process because SSG generates static files without a server environment. Therefore, if you need to execute some logic when generating, it is best to handle it in asyncData or fetch.
**5. Deployment**: The generated static files can be deployed to any static file hosting service, such as Netlify, Vercel, GitHub Pages, or AWS S3. These services usually do not require running any server-side code, just upload the generated dist folder.
**6. SEO Optimization**: SSG improves SEO because search engine crawlers can read pre-rendered HTML content without waiting for JavaScript to execute.
**7. Dynamic Routes**: For dynamic routes, Nuxt.js will try to generate all possible combinations. If all possible dynamic routes cannot be predicted, they can be manually specified in generate.routes, or controlled using generate.includePaths and generate.excludePaths.
**8. 404 Page**: Setting generate.fallback to true will generate a 404 page for dynamic routes that are not pre-rendered. When users visit these routes, Nuxt.js will try to render them on the client side.
Run the nuxt generate command and Nuxt.js will generate static HTML files.
Validation and Error Handling
Validation
Validation usually involves input validation of form data or API requests. Nuxt.js itself does not directly provide a validation library, but you can integrate third-party libraries such as Vuelidate, vee-validate, or use TypeScript for type checking.
**Using Vee-Validate**
**1. Installation**: First, you need to install the vee-validate library:
npm install vee-validate
**2. Configuration**: Add the Vue plugin configuration in nuxt.config.js:
export default { plugins: [{ src: '~/plugins/vee-validate', ssr: false }] };
**3. Create a plugin**: Configure Vee-Validate in plugins/vee-validate.js:
import Vue from 'vue'; import VeeValidate from 'vee-validate'; Vue.use(VeeValidate);
**4. Usage**: Use Vee-Validate for form validation in your component:
Error handling
Nuxt.js provides several ways to handle errors, including global error handling and page-specific error handling.
**Global error handling**
export default { error: { // Handling when the page does not exist pageNotFound({ error, store, app, env }) { // Handling logic }, // Handling any errors handler(error, { error: nuxtError, store, app, env }) { // Handling logic } } };
**Page-specific error handling**
In the page component, you can use the try-catch structure of the asyncData or fetch method to handle errors:
export default { async asyncData({ params, error }) { try { const data = await fetchSomeData(params.id); return { data }; } catch (err) { error({ statusCode: 500, message: 'Data acquisition failed' }); } } };
**API request error handling**
For API requests, if you use the @nuxtjs/axios module, you can handle errors uniformly in the request interceptor:
// plugins/axios.js import axios from 'axios'; import { toast } from '~/utils/toast'; axios.interceptors.response.use(null, (error) => { const { status } = error.response; if (status === 401) { // Handling unauthorized errors } else if (status >= 500) { // Handling Server Errors toast.error('Server Error'); } return Promise.reject(error); }); export default ({ $axios }, inject) => { inject('axios', $axios); };
Make sure to register this plugin in nuxt.config.js.
Vue Ecosystem Integration
Vue Router:
Nuxt.js automatically generates a routing system for your application based on the file structure. Routing configuration usually does not need to be written manually, but can be extended through the `router` property of `nuxt.config.js`.
Vuex:
Nuxt.js automatically creates a Vuex store. Under the `store` directory, you can create modular state, mutations, actions, and getters. For example, create a `store/modules/users.js` file to manage user data.
// store/modules/users.js export const state = () => ({ users: [] }); export const mutations = { SET_USERS(state, payload) { state.users = payload; } }; export const actions = { async fetchUsers({ commit }) { const response = await this.$axios.get('/api/users'); commit('SET_USERS', response.data); } };
Vue CLI:
Nuxt.js provides its own build tool, but it is also based on Vue CLI. This means you can use command-line tools similar to Vue CLI, such as npx nuxt generate (static generation) or npx nuxt build (build application).
Babel:
Nuxt.js is configured with Babel by default to support the latest JavaScript features. You usually don't need to configure Babel manually unless there is a special need.
TypeScript:
To use TypeScript, set typescript: true in nuxt.config.js and Nuxt.js will automatically configure TypeScript support.
ESLint:
For code quality checking, you can install ESLint in your project and configure .eslintrc.js. Nuxt.js provides @nuxt/eslint-module plugin to simplify integration.
// nuxt.config.js module.exports = { buildModules: [ '@nuxt/typescript-build', '@nuxtjs/eslint-module' // Add ESLint integration ], eslint: { fix: true, // Automatically fix errors ignoreDuringBuilds: true // Ignore errors during build } };
VueUse:
VueUse is a Vue use case library that contains various practical functions. To integrate, first install `@vueuse/core`, then import and use the functions in your components.
npm install @vueuse/core
// In the component import { useCounter } from '@vueuse/core'; export default { setup() { const count = useCounter(0); // Using the Counter Function // ... } };
Vue plugins:
You can register Vue plugins globally through the plugins configuration item in nuxt.config.js. For example, integrate Vue Toastify to display notifications:
// nuxt.config.js export default { plugins: [{ src: '~plugins/toastify.js', ssr: false }] };
// plugins/toastify.js import Vue from 'vue'; import Toastify from 'toastify-js'; Vue.use(Toastify);
Workflow using Nuxt.js
Nuxt.js provides a complete workflow for development, building, and deployment. Use the nuxt command to start the development server, nuxt build for production building, nuxt start to start the production server, and nuxt generate to generate static files.