本文详细解析Nuxt与Node.js在生产环境中的集成方案。通过Express构建后端服务,结合Session机制解决多用户Token验证问题,并利用中间件代理处理静态资源与API请求。重点阐述如何整合Nuxt渲染逻辑,确保服务端渲染(SSR)与业务接口的有序执行,提供完整的架构思路与代码示例。
上周,甲方要求在应用中开展一项促活活动,具体形式为用户领取OFO骑行券。鉴于此前已在另一款应用中实现了客户端Token验证,我决定直接在现有的Node.js服务基础上进行开发。
技术栈选型:Nuxt与Express
Nuxt
Nuxt类似于React生态中的Next.js,是Vue服务端渲染(SSR)的便捷框架。其目录结构与Vue-Cli相似,但结构更为清晰,且提供了丰富的配置选项,如顶部Loading条、Layer主题模板、利于SEO的服务端渲染以及自动生成Router等功能。选择Nuxt主要基于使用习惯及良好的性能表现,此处不再展开细节。
Express
Express是一款封装了众多便捷方法的Node.js服务端工具,类似于Koa或Egg框架。此处不再赘述其基础用法。
前端页面与业务流程实现
第一步 完成静态页面
此处省略HTML构建及Vue基础使用等无关细节。页面最终效果如图所示:
用户点击确认领取后,前端向后端发送请求以获取券码:
整体业务流程大致如上所述。
基于Webview的Token验证机制
第二步 基于Webview完成Token验证
甲方如何将Token提供给用户?
- 用户登录客户端。
- 用户在Webview中访问指定地址。
- 客户端将Token等信息绑定在URL上发送给服务端,并向服务端发起GET请求。
- 服务端接收到Token后,验证用户身份并返回页面给用户。
因此,当前的Node服务需要完成Token验证功能,具体实现如下:
此处需特别说明Session机制。初期完成Token验证时,发现多用户同时访问会导致后访问者重新执行请求中的方法,造成数据初始化甚至重复赋值,无法区分用户。咨询Java同事后得知,其框架默认处理了Session隔离,这让我感到困惑。实际上,他们虽熟悉Session,但长期使用框架后往往忽略了其存在。
起初我考虑使用Cookie验证浏览器,但认为该方法较为古老且存储容量有限。经过一天探索,发现Session机制可用于验证对应浏览器(本质是将Cookie作为数据索引)。明确这一点后,思路豁然开朗。
// 引入一些工具
const http = require('http')
const express = require("express");
const session = require('express-session');
const nuxtapp = express(); // 创建一个express应用
// 设置SESSION配置
nuxtapp.use(session({
secret: 'key' // 建议使用 128 个字符的随机字符串
}));
// 处理OPTIONS请求(axios发送POST请求时会先发送一个OPTION请求验证服务器的连通情况)
nuxtapp.use(function (req, res, next) {
if ('OPTIONS' === req.method) {
res.sendStatus(200);
} else {
next();
}
});
// 写一个验证Token的接口
nuxtapp.get('/getphone', (req, res) => {
if (!req.query.token) {
// if else ...
res.sendStatus(200)
return;
}
// 这里创建请求只是举一个例子,有的Token可以本地解析,有的需要服务端向另一个服务端请求解析。(参考微信)
const request = http.request({
host: "api.example.com",
headers: {
'Content-Type': ' application/json',
'Accept-Encoding': 'utf-8', //这里设置返回的编码方式 设置其他的会是乱码
'Accept-Language': 'zh-CN,zh;q=0.8',
'Connection': 'keep-alive',
},
path: '/getTokenorSth',
port: 'port',
method: 'POST'
}, response => {
let data = ""; // 创建变量记录数据
response.on("data", function (chunk) {
data += chunk
})
response.on("end", function () { // 设置seesion
try {
if (!req.session.id) {
// set session like : req.session.id= JSON.parse(data)
}
res.sendStatus(200)
} catch (err) {
console.log(err);
res.sendStatus(500)
}
})
}).on('error', (e) => {
console.log(`错误信息: ${e.message}`);
res.sendStatus(500)
});
// POST Data
request.write(JSON.stringify({
example:example,
token: req.query.token
})); // 用户传过来的数据 post
request.end();
})
nuxtapp.listen(port || 80, '0.0.0.0')
console.log("已开启服务器,请访问 —— localhost:" + port || 80)
服务端代理与接口处理
第三步 服务端代理(此处存疑:淘宝Node+Java架构是否采用此模式?)
作为前端开发者,功能实现部分交由资深Java工程师处理(若有时间,我也愿编写SQL以复习相关知识)。
用户访问时仍向Node发起请求。需注意的是,若后端提供多个接口,无需为每个接口单独编写app.get('/api')。Express文档中提及了类似以下写法:
nuxtapp.all(["/api1/*","/api2/*"], requestFunction)
其余逻辑与上述Token验证部分相似。
Express集成Nuxt渲染逻辑
第四步 用Express执行Nuxt
Nuxt官网虽有部分代码指导如何使用Node运行Nuxt,但内容尚不完善。在此补充我的理解,如有不当之处,欢迎指正。
// nuxt
const {
Nuxt,
Builder
} = require('nuxt') // 引入核心构建属性
// 判断开发环境
const isProd = (process.env.NODE_ENV === 'production')
const port = process.env.PORT || 80
// 引入nuxt配置
const config = require('./nuxt.config.js')
config.dev = !isProd;
const nuxt = new Nuxt(config);
// 判断生产模式 dev(开发者模式)表示重新构建 ;pro(生产模式)表示直接从yanr build的文件直接执行
if (config.dev) {
new Builder(nuxt).build()
.then(listen)
.catch((error) => {
console.error(error)
process.exit(1)
})
} else {
listen()
}
上述listen函数对应第二、三步中编写的Express服务器接口。
此时Nuxt尚未在代码中直接执行。创建Nuxt实例后返回的nuxt方法,实际上是依据request和response执行相应渲染。需特别注意Express中各种接口的执行顺序:若提前匹配到第二步的GET请求,则后续all方法中的接口将无法被接收。
我的考量是:接口并非无故执行,但用户请求必然发生。因此,除故意发送的请求外,其余请求均由Nuxt接管。故将Nuxt置于最后,负责渲染页面并交付用户。为方便Token验证,我将验证Token的请求置于首页,使浏览器捕获Token及相关信息后交由Node执行手动登录(也可在Nuxt渲染前判断是否存在Token来决定是否进行验证,此处不再展示大量代码)。
结合上述思路,即在最后捕获所有GET请求并交由Nuxt处理:
// 最后捕获nuxt渲染
nuxtapp.get('/*', (req, res) => {
nuxt.render(req, res)
})
Demo:jasontan.cn
以上为本文全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。