详解基于 Vue 的服务端渲染框架 NUXT
什么是 NUXT?
NUXT 是一个基于 Vue.js 的轻量级框架,利用它可以帮我们快速搭建一个服务端渲染(SSR)的应用程序。服务端渲染的优势在于可以提高应用程序的首屏渲染速度,提供更好的搜索引擎优化(SEO)。除此之外,NUXT 还封装了 Vue.js,提供了一些默认配置和功能,例如自动生成路由和静态资源的优化。
安装
NUXT 可以通过命令行工具快速安装:
$ npm install -g create-nuxt-app
$ create-nuxt-app my-project
该命令会在当前目录下创建一个名为 "my-project" 的新项目。
NUXT 应用程序的结构
NUXT 应用程序的结构如下:
nuxt-app/
├── assets/
├── components/
├── layouts/
├── middleware/
├── pages/
├── plugins/
├── static/
├── store/
├── nuxt.config.js
└── package.json
assets/
:用于存放应用程序的资源文件,例如样式文件和图片文件等等components/
:存放应用程序的 Vue 组件layouts/
:应用程序的布局模板,用于组合各个页面middleware/
:应用程序的中间件,用于处理网页请求(例如带有 cookie 的请求)pages/
:应用程序页面的组件(每个路由映射到一个文件)plugins/
:应用程序的插件,用于扩展 Vue.js 的功能static/
:存储静态文件,例如图片、视频等(会被自动引入到应用程序中)store/
:Vuex 状态管理器模块nuxt.config.js
:NUXT 配置文件package.json
:应用程序的 npm 依赖文件
NUXT 的路由机制
NUXT 的路由机制可以帮我们自动生成应用程序的路由。在 NUXT 中,每个 .vue
文件会被处理成一个独立的路由,文件名即为路由名。例如,pages/index.vue
会映射到路由 /
。
如果我们需要映射到名为 blog/:id
的路由,只需要在 pages/
目录下创建一个名为 blog/_id.vue
的文件,NUXT 会自动将 id
参数传入该组件。例如:
pages/
└── blog/
├── _id.vue
└── index.vue
NUXT 的模板功能
NUXT 的模板功能可以帮我们更方便的进行页面布局。
我们可以在 layouts/
目录下创建一个全局的布局模板,然后在每个页面中使用该模板,并在其中嵌入每个页面的内容。例如:
layouts/
├── default.vue
└── error.vue
然后,在页面中使用布局模板:
<!-- pages/index.vue -->
<template>
<default-layout>
<h1>Hello world!</h1>
</default-layout>
</template>
<script>
import DefaultLayout from '~/layouts/default.vue'
export default {
layout: DefaultLayout
}
</script>
NUXT 的插件系统
NUXT 的插件系统可以帮我们扩展 Vue.js 的功能。
我们可以在 plugins/
目录下创建一个指定的插件,并在 NUXT 中引入。例如:
plugins/
└── moment.js
然后,在 NUXT 配置文件中引入该插件:
// nuxt.config.js
module.exports = {
plugins: [
'~/plugins/moment.js'
]
}
NUXT 的数据预取
在 NUXT 中,我们可以在渲染组件之前通过 fetch
钩子函数获取数据,并将该数据注入到应用程序的状态管理器中(Vuex)。例如:
<!-- pages/index.vue -->
<template>
<div>
<h1>{{ title }}</h1>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
fetch ({ store }) {
return store.dispatch('getPosts')
},
computed: {
title () {
return this.$store.state.title
},
posts () {
return this.$store.state.posts
}
}
}
</script>
上述代码中,fetch
钩子函数会在页面渲染之前被调用,从而在渲染组件之前获取数据并注入到应用程序的状态管理器中。获取数据的逻辑可以在 store/
目录下的 Vuex 模块中实现。
示例 1:使用 NUXT 快速搭建一个博客应用
下面,让我们使用 NUXT 快速搭建一个博客应用。
- 创建一个新的 NUXT 应用程序:
bash
$ npx create-nuxt-app my-blog
- 在
pages/
目录下创建一个名为index.vue
的组件,用于展示博客列表:
``` html
My Blog
- {{ post.title }}
```
上述代码中,我们通过 asyncData
钩子函数获取博客列表数据,并注入到组件的 posts
属性中。
- 在
store/
目录下创建一个名为blog.js
的 Vuex 模块,用于管理博客数据:
``` js
import axios from 'axios'
export const state = () => ({
posts: []
})
export const mutations = {
setPosts (state, posts) {
state.posts = posts
}
}
export const actions = {
async getPosts ({ commit }) {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
commit('setPosts', data)
}
}
```
上述代码中,我们通过 getPosts
方法获取博客列表数据,并使用 setPosts
方法将数据注入到应用程序的状态管理器中。
- 在
nuxt.config.js
配置文件中启用应用程序的 Vuex 模块:
``` js
//nuxt.config.js
export default {
modules: [
'@nuxtjs/axios',
'@nuxtjs/style-resources'
],
axios: {
baseURL: 'http://localhost:8080', // Used as fallback if no runtime config is provided
},
buildModules: [
'@nuxtjs/vuetify',
],
plugins: [
],
components: true,
styleResources: {
scss: [
'./assets/scss/main.scss'
]
},
router: {
middleware: ['auth']
},
build: {
},
serverMiddleware: [
// Will register file from project api directory to handle /api/* requires
{ path: '/api', handler: '~/api/index.js' }
],
server: {
port: 80, // default: 3000
host: '0.0.0.0', // default: localhost
},
//增加
modulesDir: ['node_modules', '~/modules'],
// 增加 Vuex 模块引用
modules: [
'~/store/blog.js'
]
}
```
- 运行 NUXT 应用程序:
bash
$ npm run dev
现在,我们就可以通过 http://localhost:3000/
访问我们的博客应用了。
示例 2:使用 NUXT 和 Koa 将博客应用程序部署到服务器
假设我们已经搭建好了一个 Koa 服务器,下面我们将学习如何将 NUXT 应用程序部署到该服务器上。
- 编写 Koa 服务器:
``` js
const Koa = require('koa')
const consola = require('consola')
const app = new Koa()
app.use((ctx, next) => {
const start = Date.now()
return next().then(() => {
const ms = Date.now() - start
consola.info(`${ctx.method} ${ctx.url} - ${ms}ms`)
})
})
app.use((ctx) => {
ctx.body = 'Hello, world!'
})
app.listen(3000, () => {
consola.success('Server is running on http://localhost:3000')
})
```
上述代码会创建一个 Koa 应用程序,监听 http://localhost:3000
端口,并在访问该地址时返回一个 "Hello, world!" 的字符串。
- 在 NUXT 中配置应用程序的端口和模式:
js
// nuxt.config.js
module.exports = {
mode: 'universal',
server: {
port: 3001
}
}
上述代码中,我们将 NUXT 应用程序的端口设置为 3001
,并将其模式设置为 Universal。
- 在 NUXT 中配置应用程序的 API 请求:
js
//nuxt.config.js
export default {
modules: [
'@nuxtjs/axios',
'@nuxtjs/style-resources'
],
axios: {
baseURL: 'http://localhost:8080', // Used as fallback if no runtime config is provided
},
serverMiddleware: [
{ path: '/api', handler: '~/api/index.js' }
],
plugins: [
],
components: true,
buildModules: [
'@nuxtjs/vuetify',
],
styleResources: {
scss: [
'./assets/scss/main.scss'
]
},
router: {
middleware: ['auth']
},
build: {
},
modulesDir: ['node_modules', '~/modules']
}
上述代码中,在 serverMiddleware
中引用了目录 ~/api
下的 JS 文件。在该目录下,我们可以编写服务器端脚本,例如连接数据库、执行查询操作等等。
- 在 Koa 服务器中引用 NUXT 应用程序:
``` js
const Koa = require('koa')
const { Nuxt, Builder } = require('nuxt')
const app = new Koa()
// 启用 NUXT 引擎
const nuxt = new Nuxt(require('../nuxt.config.js'))
if (nuxt.options.dev) {
const builder = new Builder(nuxt)
builder.build()
}
// NUXT 中间件
app.use(nuxt.render)
// 启动 Koa 服务器
app.listen(3000, () => {
consola.success('Server is running on http://localhost:3000')
})
```
上述代码中,我们使用 NUXT 的 Nuxt
类初始化一个 NUXT 引擎对象,并使用 koa.use
方法将其挂载到 Koa 中。
完成上述步骤,进入你的NUXT项目的根目录。手动打开控制台,在当前目录下按住 Shift 键并点击鼠标右键,选择 "在此处打开命令窗口" 。接下来输入 npx create-nuxt-app appName 进行项目的初始化新建。
在建立完成后进入appName文件夹内,输入 npm install 以安装依赖包。
将你的koa主文件命名为app.js放入根目录下,接下来需要用到的依赖包有:koa, consola, nuxt, nuxt-builder。通过控制台命令输入:
npm install koa consola nuxt nuxt-builder --save
在完成以上依赖包的安装后,需要对文件进行编辑配置。
因为在koa中我们需要引用NUXT的打包后的文件,就需要通过 nuxt-builder 对NUXT进行打包处理。在package.json文件中增加以下命令:
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"generate": "nuxt generate",
"start": "cross-env NODE_ENV=production node app.js",
"start-dev": "nodemon app.js"
},
最后一个命令是运行app.js的命令,其中cross-env命令是用来设置系统全局变量的的命令。
找到app.js文件,在开始处输入以下代码:
const nuxtConfig = require('./nuxt.config.js')
const nuxt = new Nuxt(nuxtConfig)
if(nuxtConfig.dev) {
const builder = new Builder(nuxt)
builder.build()
}
app.use(async (ctx) => {
await nuxt.ready()
ctx.status = 200
ctx.respond = false
nuxt.render(ctx.req, ctx.res)
})
const server = app.listen(3000, () => {
console.log(`Listening on http://localhost:${server.address().port}`)
})
在/etc/nginx/nginx.conf文件中增加以下内容:
http {
# add new upstream for Node.js application
upstream node-app {
# http server bind to 3000
server 127.0.0.1:3000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name your-domain.com;
# reverse proxy to Node.js application
location / {
proxy_pass http://node-app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
Node.js 监听的端口为 3000. location / {}, 是连接 Node.js 服务的 upstream 的配置, 然后代理请求到应用程序所监听的端口。
在这种方式下,所有的请求会被代理分配到本地的3000端口上面,而应用程序则是被 NUXT 的引擎进行渲染,然后返回一个 HTML 页面给服务器。
现在,我们的博客应用程序已经部署到了云服务器上,并可以通过你的域名访问了!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解基于vue的服务端渲染框架NUXT - Python技术站