一、前言
在实际业务开发中,会遇到这样一种需求,使用VUE的页面需要支持SEO,同时对首屏有指标性要求,目前市面上普遍使用的是Nuxt.js解决方案,在引入的同时还需要考虑与现有的全栈工程结合,本系列文章探讨的是此类全栈工程的解决方案,同时使用的是TypeScript应用于前后端编程,文章中介绍的工程与技术要点源码已上传至Github,有需要的朋友可自行下载:
Nuxt.js和Nest.js同构工程
文章意在抛砖引玉,前后端使用同一种语言TypeScript编写,示例已包含基本接口请求,数据库连接应用,公用模块封装等实际开发中使用到的内容。
效果预览:
以下为该系列文章入口列表:TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 一、《简介》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 二、《框架融合》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 三、《配置服务》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 四、《UI系统》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 五、《API服务设计》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 六、《SEO功能实现》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 七、《Vuex使用》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 八、《接入Mongo DB服务》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 九、《TypeScript》
TypeScript全栈工程实战-(Nuxt. js & Nest. js) - 十、《工程化部署》
使用说明:
- 前置条件MongoDB
工程中使用到了MongoDB,需先在本地安装该服务 MongoDB安装教程 安装完成后使用以下命令启动:
mongod --config mongod 配置目录/mongod.conf --dbpath 数据库存放目录
例如:
mongod --config /usr/local/etc/mongod.conf --dbpath /usr/local/mongodir
- 前置条件Charles
对接接口时借助Charles Web Debugging Proxy抓包分析工具能提升开发效率和快速定位问题,请注意Charles端口是否已设置为8888(默认值)
- 开发环境运行
npm run client:prod // local start on production mode
npm run client:dev // local start on development mode
visit: http://localhost:8088
启动效果:
- 生产环境运行
npm run build
and
cross-env NODE_ENV=production npm run start // server start on production mode
cross-env NODE_ENV=development npm run start // server start on development mode
二、所使用的技术栈
Nuxt.js
Nuxt.js 基于 Vue.js 的通用应用框架,通过对客户端/服务端基础架构的抽象组织,主要关注的是应用的 UI渲染。支持异步数据加载、中间件支持、布局支持等。工程中主要使用其服务端渲染、SEO、自动代码分层、打包和压缩 JS 和 CSS等功能。
Nest.js
Nest.js 一个用于构建高效,可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,内置并完全支持 TypeScript并结合了 OOP(面向对象编程),FP(函数式编程)和 FRP(函数式响应编程)的元素。
在底层,Nest.js使用强大的 HTTP Server 框架,如 Express(默认)和 Fastify。Nest.js在这些框架之上提供了一定程度的抽象,同时也将其 API 直接暴露给开发人员。 在工程中与Nuxt.js结合,主要是使用Nuxt.js作为中间件middleware的形式注入Nest.js服务中。
Vant UI Framework
Vant 友赞Vant主打轻量、可靠的移动端 Vue 组件库,主要是把业务开发中常用的组件进行抽象和易用性改造。得益于它支持SSR和TypeScript及在国内有一定的使用率,故UI框架选用它作为表现层内容。
TypeScript
TypeScript JavaScript超集,主打可选的静态类型和基于类的面向对象编程。工程中采用它解决全栈工程中统一语言问题,避免开发者在开发时针对不同的框架需要做麻烦的语法转换。得益于强类型,使代码重构,类型推断,代码质量在工程业务越来越大时能达到比较不错的质量收益。
三、所解决的问题
搜索引擎优化(SEO)
将SEO的关键数据直接在后台就渲染成html,从而保证搜索引擎的爬虫能爬取到关键数据,如图所示:TDK实时渲染,保证搜索引擎识别。
SSR提升首屏时间
SSR优势之一是更快的响应时间,不用等待所有的js都下载完成,浏览器变成现实比较完整的页面。可以在页面初始化之前在服务器端优先将页面使用的数据提前加载。例如
首屏渲染是node发送过来的html字符串,不依赖于Vue前端渲染生成DOM节点,使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,解决白屏等待时间过长问题。全栈化功能扩充
引入全栈功能,可以继续发挥node作为中间层作用,在此基础上,可以封装前端自有API,例如RESTful中转接口,解决跨域问题,连接数据库、操作缓存、文件、错误捕捉上报等功能。
四、架构分析说明
结构说明
底层采用Nest.js将Nuxt.js包装成middleware形式嵌入服务器中,UI层Vant则运行在Nuxt.js中,属Vue.js表示层框架。 在此基础上封装公共组件层,用于提供开发中常用且公共服务,避免代码分散,和非重用。主要包括core、日志、权限管理、服务端渲染实现,基础网络请求封装。 最上层为业务功能层,包括各业务功能页面实现逻辑,Vue.js文件采用HTML/CSS/JS逻辑包含在同一文件中,未作进一步分离,但基本原则是细粒度化组件划分。整个开发过程服务端与前端采用TypeScript作为同一种语言开发,增加开发质量和减少重构成本。流程举例
客户端发起HTTP请求,这里分为2种情况,在框架层分别处理了2种请求,页面和API层级,框架自动依据请求地址是否带API前缀,将处理请求发往不同的处理底层,分别是非API,使用SSR服务处理,主要返回页面HTML代码结构,而API则发往特定的API服务控制器,在非中转接口类请求中,如果使用到DB还会与MONGO DB交互,例如:作必要的CRUD操作等。五、相关规范
目录规范
目录统一采用小写格式,依据功能分治原则,取名使用全英文,避免拼音,同时单个单词不能表达相应意思时,使用烧考串模式:some-words-descript
来描述。
文件规范
文件统一使用大写驼峰模式命名,避免使用拼音,首字母或单词一般采用当前目录文件夹名字,使文件看上去统一整齐,快速定位和查找。接口命名统一使用I开头
例如:
特例
有个特殊的例外,store目录中内容不受大小写影响,因为在服务端渲染情况下,读取store中内容,则需要用原文件名访问才能访问到,例如:
访问store中的auth对象值,正常访问方式为:
store.state.modules.auth // right
如果auth使用大写命名Auth,那么正确访问方式为: 不符合变量对象访问常规方式,故加入特列中。
store.state.modules.Auth // wrong
六、目录结构
功能分层:
- build目录
生成配置环境脚本
- config目录
前后端共用配置,按环境区分
- dist目录
生产编译发布后生成的转译源码目录
- docs目录
文档说明目录
- src
源码目录
- client目录
前端源码目录,包括Vue等源文件
- server目录
服务端源码目录,包括服务、控制器、数据库逻辑等源文件
- client目录
Client层:
- assets
样式资源文件
- common
客户端业务层公用逻辑
- components
业务封装的Vue组件
- core
业务底层
- layouts
模板目录
- middleware
中间件
- models
前端与服务端交互的数据模型
- pages
业务逻辑页面,按模块区分
- plugins
插件目录
- routers
按业务划分的显式路由常量存放之处
- service
与服务端交互的业务接口请求封装
- static
站点静态资源目录
- store
vuex目录
Server层:
- common
服务端业务层公用逻辑
- modules
模块目录
- routers
显式物理路由划分目录
- AppController.ts
全局Controller
- AppModule.ts
APP模块
- Main.ts
服务器入口文件