Nuxt.js 介绍
特性
- 基于 Vue.js
- Vue、Vue Router、Vuex、Vue SSR
- 自动代码分层
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- ES2015+语法支持
- 打包和压缩JS和CSS
- HTML头部标签管理
- 本地开发支持热加载
- 集成ESLint
- 支持各种样式预处理器: SASS、LESS、Stylus等等
-
Nuxt.js框架是如何运作的
Nuxt.js 集成了以下组件/框架,用于开发完整而强大的 Web 应用: Vue.js
- Vue Router
- Vuex
- Vue Server Renderer
压缩并 gzip 后,总代码为:57kb(如果使用了 Vuex 特性的话为 60kb)。
另外,Nuxt.js使用Webpack 和 vue-loader、babel-loader 来处理代码的自动化构建工作(如打包、代码分层、压缩等等)。
创建项目
Nuxt提供了两种方式用来创建项目:
- 使用 create-nuxt-app 脚手架工具
- 手动创建
本文手动创建
(1)准备
# 创建示例项目
mkdir nuxt-app-demo
# 进入示例项目目录中
cd nuxt-app-demo
# 初始化 package.json 文件
npm init -y
# 安装 nuxt
npm install nuxt
在 package.json 文件的 scripts 中新增
"scripts": {
"dev": "nuxt"
}
通过运行 npm run dev 来运行 nuxt
(2)创建页面并启动项目
创建 pages 目录:
mkdir pages
创建我们的第一个页面 pages/index.vue
<template>
<h1>Hello world!</h1>
</template>
然后启动项目
npm run dev
(3)Nuxt中的基础路由
Nuxt.js会根据pages目录中的所有*.vue文件生成应用的路由配置
Nuxt路由
Nuxt.js依据 pages 目录结构自动生成 vue-router 模块的路由配置
- 动态路由
- 在Nuxt.js里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的Vue文件或目录。
嵌套路由
ttps://zh.nuxtjs.org/docs/2.x/configuration-glossary/configuration-router/
视图
异步数据——asyncData
- ttps://zh.nuxtjs.org/guide/async-data
- asyncData 方法
- Nuxt.js 扩展了 Vue.js,增加了一个叫”asyncData”的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据
- 基本用法
- 它会将asyncData 返回的数据融合组件data方法返回数据一并给组件
- 调用时机:服务端渲染期间和客户端路由更新之前
- 注意事项
- 只能在页面组件中使用
- 没有 this,因为它是在组件初始化之前被调用的。
上下文对象
async asyncData (context) {
console.log(context)
const { data } = await axios({
method: 'GET',
url" 'http://localhost:3000/data.json'
})
const id = Number.parseInt(context.params.id)
return {
article:data.posts.find(item => item.id === id)
}
}
生命周期
Vuex 状态管理
Nuxt 渲染流程
下图阐述了 Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 切换路由渲染页面)的流程:
Nuxt常见问题
Nuxt 官方示例
https://zh.nuxtjs.org/examples/
Nuxt.js 综合案例
介绍
- 在线示例:https://demo.realworld.io/#/
- 接口文档:https://github.com/gothinkster/realworld/tree/master/api
- 页面模板:https://github.com/gothinkster/realworld-starter-kit/blob/master/FRONTEND_INSTRUCTIONS.md
nuxtServerinit
- 是一个特殊的 action 方法
- 这个 action 会在服务端渲染期间自动调用
作用:初始化容器数据,传递数据给客户端使用
```javascript nuxtServerInit ({ commit }, { req }) { let user = null// 如果请求头中有 Cookie if (req.headers.cookie) {
// 使用 cookieparser 把 cookie 字符串转为 JavaScript 对象
const parsed = cookieparser.parse(req.headers.cookie)
try {
user = JSON.parse(parsed.user)
} catch (err) {
// No valid cookie found
}
}
// 提交 mutation 修改 state 状态 commit(‘setUser’, user) }
**路由中间件**
- 路由匹配之前先执行中间件
```javascript
export default {
// 在路由匹配组件渲染之前会先执行中间件处理
middleware: 'authenticated',
name: 'EditorIndex'
}
在项目目录下建立 middleware 文件夹 下建立 authenticated.js
/**
* 验证是否登录的中间件
*/
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.user) {
return redirect('/login')
}
}
监听 query 参数变化
默认情况下,query的改变不会调用asyncData方法。如果要监听这个行为,例如,在构建分页组件时,您可以设置应通过页面组件的watchQuery属性监听参数。
- 使用watchQuery属性可以监听参数字符串的更改。 如果定义的字符串发生变化,将调用所有组件方法(asyncData, fetch, validate, layout, …)。 为了提高性能,默认情况下禁用。
如果您要为所有参数字符串设置监听, 请设置: watchQuery: true.
export default {
watchQuery: ['page']
}
插件
- Nuxt.js 允许您在运行 Vue.js 应用程序之前执行 js 插件。这在您需要使用自己的库或第三方模块时特别有用。
通过插件机制获取到上下文对象(query、params、req、res、app、store…)
// 插件导出函数必须作为 default 成员
export default ({ store }) => {
// 请求拦截器
// Add a request interceptor
// 任何请求都要经过请求拦截器
// 我们可以在请求拦截器中做一些公共的业务处理,例如统一设置 token
request.interceptors.request.use(function (config) {
// Do something before request is sent
// 请求就会经过这里
const { user } = store.state
if (user && user.token) {
config.headers.Authorization = `Token ${user.token}`
}
// 返回 config 请求配置对象
return config
}, function (error) {
// 如果请求失败(此时请求还没有发出去)就会进入这里
// Do something with request error
return Promise.reject(error)
})
}
然后,在 nuxt.config,js 内配置 plugins 如下:
module.exports = {
plugins: ['~/plugins/request.js']
}
给某个页面加 title
head () {
return {
title: `${this.article.title} - RealWorld`,
meta: [
{ hid: 'description', name: 'description', content: this.article.description }
]
}
}
发布部署
基本方法
将应用打包
nuxt build
将打包文件 .nuxt static nuxt.config.js package.json package-lock.json 上传到服务器
scp /path/filename username@servername:/path
在服务器上安装依赖
npm install
在服务器上运行
pm2 start npm -- start
自动部署
将本地代码提交至 git 仓库
- 设置 token
- 目录所在地 Settings —> Developer settings —> Personal access tokens
- 起一个名称, 勾选第一个选项 repo
- 得到 token 保存后续使用,这个 token 只出现一次
- 配置 Secrets
- 在项目中点击 Settings —> Secrets —> New repository secret
- 名字 TOKEN 内容: 上一步获得的 token
- 名字 HOST 内容: 服务器外网 ip
- 名字 PASSWORD 内容: 服务器密码
- 名字 PORT 内容: 默认 22
- 名字 USERNAME 内容: root
项目根目录创建 pm2.config.json
{
"apps": [
{
"name": "RealWorld",
"script": "npm",
"args": "start"
}
]
}
项目根目录创建.github/workflows/main.yml ```javascript name: Publish And Deploy Demo on: push: tags:
- 'v*'
jobs: build-and-deploy: runs-on: ubuntu-latest steps:
# 下载源码
- name: Checkout
uses: actions/checkout@master
# 打包构建
- name: Build
uses: actions/setup-node@master
- run: npm install
- run: npm run build
- run: tar -zcvf release.tgz .nuxt static nuxt.config.js package.json package-lock.json pm2.config.json
# 发布 Release
- name: Create Release
id: create_release
uses: actions/create-release@master
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
# 上传构建结果到 Release
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@master
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./release.tgz
asset_name: release.tgz
asset_content_type: application/x-tgz
# 部署到服务器
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
port: ${{ secrets.PORT }}
script: |
cd /home/realworld-nuxtjs
wget https://github.com/lipengzhou/realworld-nuxtjs/releases/latest/download/release.tgz -O release.tgz
tar zxvf release.tgz
npm install --production
pm2 reload pm2.config.json
- 将所有代码提交 git 创建 tag 提交
```javascript
git tag v0.1.0
git push origin v0.1.0
- 提交成功后在github项目上查看构建状态 Actions
- 点击 Releases 查看历史版本