首页IT科技vue ssr服务端渲染框架(基于NUXT.JS搭建一款VUE版SSR前端框架(解决SPA应用的SEO优化优化问题))

vue ssr服务端渲染框架(基于NUXT.JS搭建一款VUE版SSR前端框架(解决SPA应用的SEO优化优化问题))

时间2025-06-17 02:18:15分类IT科技浏览3579
导读:小仙男·言在前 关于框架:为了解决VUE的SPA单页应用对SEO搜索引擎优化不友好的问题,这几天一直在调研各种SSR框架。比如doc.ssr-fc.com/ 和 fmfe.github.io/genesis-do 都是比较不错,且有自己理念和想法的框架。但是对于公司来说技术规范差异太大,团队学习成本比较高,思来想...

小仙男·言在前

关于框架:为了解决VUE的SPA单页应用对SEO搜索引擎优化不友好的问题             ,这几天一直在调研各种SSR框架             。比如doc.ssr-fc.com/ 和 fmfe.github.io/genesis-do 都是比较不错                  ,且有自己理念和想法的框架                  。但是对于公司来说技术规范差异太大      ,团队学习成本比较高          ,思来想去                  ,还是基于NUXT.JS自己搭建一套SSR框架慢慢完善吧      。

关于本文档:本文档是从官网文档中摘录的一些重点内容         ,以及加入了自己的一些调整和对官网内容的理解和解释          。

关于官网:NUXT中文网 特别适合新手学习       ,文档及案例十分清楚详尽                  ,可以说有手就行                  。但是            ,中文网的更新不及时    ,有些章节(比如fetch钩子中不能使用this)甚至存在明显错误                   ,所以有一定技术水平的宝子               ,建议直接查看 NUXT英文官网          。

【一            、框架概述】

1                   、框架介绍

SSR 技术(即服务端渲染技术),区别于原先纯Vue框架的SPA应用(即单页应用)       。SPA应用只有一个index.html的入口文件                ,页面显示的所有内容均靠客户端JS进行渲染                  ,对于搜索引擎(SEO)优化来说   ,整个网站只有一个空页面             ,十分不友好                  。而服务端渲染技术                  ,是借助node.js作为框架服务端      ,在初次访问一个页面的时候          ,先在服务端预请求接口                  ,并在服务端组装完成的html页面后         ,返回给客户端呈现            。 Nuxt.js是基于Vue框架的一款服务端渲染框架       ,提供了特有的框架结构和服务端渲染声明周期    。

2      、开发环境

本框架基于Node.js+Webpack+vue+Nuxt.js进行开发                  ,提供ElementUI作为UI框架                   。开发前需全局安装Node.js与webpack开发环境               。 框架推荐Node.js版本为v16.15.0            ,最低版本不得低于12    ,推荐安装nvm或n等node版本管理工具。

3         、分支要求

遵循[前端团队git仓库及版本管理规范]                   ,即master分支只用于拉取框架代码               ,xxx_dev为开发分支,xxx_test为开发分支                ,xxx为生产分支                。

3                   、关于本文档

本文档所述内容                  ,已经是从官网中摘录的【重中之重】   ,开发前请【详尽】【仔细】【通读】本文档!!!尤其是【五         、数据请求】 与 【六-8      、重要Q&A】!!! 文档描述存在错误的地方             ,请以【NUXT英文官网】为准                  。

【二                   、启动与部署】

# 安装框架以来 $ npm install # 启动本地开发环境                  ,默认端口号:3000 $ npm run dev # 编译并在生产环境启动 $ npm run build $ npm run start # 将网站打包成静态化页面 $ npm run generate

【三            、框架结构】

详细目录结构介绍及使用      ,参照【六   、其他规范与Q&A】 -- 框架根目录 -- .nuxt Nuxt运营和编译自动生成 -- dist 执行Nuxt静态化时生成 -- api 全局通用的Api请求函数(非Nuxt提供) -- assets 静态资源目录          ,存放全局css                   、image等 -- components 自定义组件目录                  ,此目录下组件无需引入         ,按需使用即可 -- layout 布局文件       ,参考https://www.nuxtjs.cn/guide/views -- middleware 中间件                  ,类似于路由守卫 -- modules 模块            ,用于设置全局监听等    ,参考https://www.nuxtjs.cn/guide/modules -- pages 页面目录                   ,Nuxt会根据此目录自动生成路由               ,参考https://www.nuxtjs.cn/guide/routing -- plugins 插件目录,自定义各种插件                ,参考https://www.nuxtjs.cn/guide/plugins > global.js (全局变量与全局方法) > plugin.js (全局引入第三方组件) > request.js (全局请求封装) > filter.js (全局过滤器封装) > util.js (全局工具函数封装) > all.client.js(仅在客户端执行插件                  ,暂时替代原app.vue) -- static 不需要webpack编译的静态文件   ,一般存放ico等文件 -- store Vue状态树             ,与原写法有所不同                  ,参考https://www.nuxtjs.cn/guide/vuex-store -- utils 工具类包 (非Nuxt提供) .editorconfig .gitignore env.js 环境变量配置      ,分dev                、test、pro三种环境 nux.config.js Nuxt的所有配置项          ,参考https://www.nuxtjs.cn/api/configuration-build package-lock.json package.json README.md 框架使用文档 ReleaseNote.md 版本更新说明

【四               、生命周期】

-- Nuxt完整声明周期 【服务端渲染】 -- 全局 nuxtServerInit 第一个:nuxt中第一个运行的生命周期 RouteMiddleware 第二个:中间件                  ,类似于原框架的路由导航守卫 -- 组件 validate 是用来校验url参数符不符合 asyncData Nuxt专属声明周期         ,可用于数据请求       ,只有page可用                  ,子组件内部不可用 beforeCreate Vue声明周期            ,但是服务端会执行(不可用于数据请求    ,数据请求相关操作会在客户端执行) created Vue声明周期                   ,但是服务端会执行(同上) fetch Nuxt专属声明周期               ,可用于数据请求, page和子组件都可用 【客户端渲染】 -- 全局 * `@/plugins/all.client.js` (并非Nuxt声明周期                ,是只在客户端运行的插件   。此框架中用于暂时替代原框架中在App.vue中进行的全局初始化操作             。) -- 组件 beforeCreate created beforeMount mounted ... (其他Vue后续声明周期) 几点说明: beforeCreate/created 是Vue的生命周期                  ,但是会在服务端和客户端各执行一次   ,但这两个钩子             ,仅供了解                  ,不能用于数据请求                  。 asyncData和fetch都是Nuxt提供的声明周期      ,都可用于数据请求      。只是写法略有不同(参考后续章节【五                   、数据请求】)          。 @/plugins/all.client.js 并非Nuxt声明周期          ,是只在客户端运行的插件                  。但是Nuxt框架去掉了app.vue                  ,此插件的声明周期         ,近似于原来的app.vue       ,故暂时用于替代原框架中在App.vue中进行的全局初始化操作(是否恰当暂时不知)         。

【五   、数据请求】

1. 数据请求钩子

1.1 钩子相关说明 asyncData和fetch都是Nuxt提供的声明周期                  ,都可用于数据请求            ,都会在服务端预请求数据进行组装; asyncData只能在pages级别的页面中调用    ,在子组件内部不能调用;fetch则可以同时在页面和子组件中调用; 官方建议数据请求均采用asyncData                   ,但为了保持与老框架写法的一致               ,本框架暂时建议采用fetch(后果未知) fetch请求相比于asyncData的已知缺陷有: ① 数据请求较慢,本框架Demo                ,从index页进入Detail页                  ,当使用fetch请求时   ,可明显看到浏览器选项卡的title出现一瞬间undefined 尽管beforeCreate/created也可以在服务端渲染             ,但是这两个钩子的数据请求操作只会在客户端执行                  ,非特殊情况      ,切勿用于页面初始化       。 1.2 asyncData asyncData 中不能访问this          ,但是可以在第一参数中                  ,拿到context上下文         ,使用context.app访问Vue根示例; context上下文还包含store            、route                   、params      、query等数据       ,详见context上下文 asyncData中无法拿到组件实例                  ,不能访问组件实例中的data method等方法                  。 详细介绍:asyncData 【请求示例】 // ① 使用return返回的对象            ,将直接初始化到组件`data`中 async asyncData({app, params}) { const { code, data } = await app.$get(/policy/findById/+params.id) return {detail: data} }, // ② return一个Promise    ,将在Promise执行完成后                   ,将数据初始化到组件`data`中 asyncData({app, params}) { return app.$get(/policy/findById/+params.id).then(res => { return {detail: data} }) }, // ③ 第二个参数为callback回调函数               ,可直接传入数据,初始化到组件`data`中 asyncData({app, params}, callback) { app.$get(/policy/findById/+params.id).then(res => { callback(null, {detail: data}) }) }, 1.3 fetch fetch 分两种情况(新版本后支持第二种情况): ① 第一个参数接受context上下文                ,则与asyncData一样                  ,不能访问this和组件实例; (这种情况   ,也不支持像asyncData一样通过return或者回调函数修改data内容) ② 不接受任何参数时             ,则可以正常访问this            。(可以近似的看成created的用法                  ,区别是 必须要使用await 或者return一个primary) 详细介绍:fetch英文文档 (中文文档严重延迟      ,存在错误) 【请求示例】 // ① 使用return返回一个Promise fetch() { return this.getDetail() }, // ② 使用await/async async fetch() { await this.getDetail() }, methods: { // ① 使用await编写methods方法 async getDetail(id){ const { code, data } = await this.$get(/policy/findById/+this.$route.params.id) this.detail = data } // ② 使用return Promise编写methods方法 getDetail(id){ return this.$get(/policy/findById/+this.$route.params.id).then(resw => { this.detail = res.data }) } }

2. 数据请求方式

2.1 【框架推荐】 使用vue实例直接调用 本框架会将$request/$get/$post挂在到vue根示例          ,建议直接只用this或上下文context.app调用 【请求示例】 // 以this调用为例                  ,如果是在`asyncData`中         ,需要使用上下文`context.app`调用 // ① get this.$get(/policy/findById/+this.$route.params.id) // ② post this.$post(/policy/findAll/,{page:1,size:10,params:{}}) // ③ request this.$request({ url: /policy/findAll/, method: post, data: {page:1,size:10,params:{}} }) 2.2 兼容老框架的api分离式调用 本框架推荐使用五 2.1的方式调用       ,但是也兼容了老框架的api分离式调用                  ,用于提取可复用的公共请求    。 公共请求的api文件            ,统一放在@/api/*.js管理                   。 【请求示例】 /** * @/api/index.js */ import request from @/utils/request export function getPageList(data) { return request.post(/policy/findAll, data) } /** * @/pages/index.vue */ import { getPageList } from "@/api/index.js" export default { fetch() { return this.getPageList(this.pageDto) }, methods: { getPageList(pageDto) { return getPageList(pageDto).then(res => { this.pageList = res.data.result }) } }, }

3. 其他注意事项

原则上    ,所有初始化渲染数据的请求                   ,都要在服务端渲染函数(asyncData或fetch)中进行               ,极个别无法在服务端渲染的请求,可以在Vue的生命周期(created或mounted)中初始化; 服务端渲染的生命周期(即asyncData/fetch)                ,不能使用任何浏览器专属的对像(如DOM对象)                  ,也就是document和window   ,以及window的各种对象和方法             ,例如setTimeout         、setInterval                   、localStorage         、sessionStorage等;

有上述需求的初始化逻辑                  ,可以放到created或mounted中初始化               。

【六      、其他规范与Q&A】

1. 关于pages

本框架路由采用约定式路由      ,即不再使用route.js进行路由声明          ,而是由框架根据pages目录自动生成路由                  ,详见路由 文件夹或者文件         ,如果以_开头       ,表示此为动态路由                  ,可以传入不同参数            ,在组件内容    ,可以使用上下文或者this.$router取到路由参数; 例如: /pages/news/detail/_id.vue                   、/pages/news/detail/_id/index.vue 访问: http://domain.com/pages/news/detail/12345 (上述两种写法均为这一路径) 【注意】 ① 使用_id.vue的写法                   ,表示id为可选参数               ,即可以通过http://domain.com/pages/news/detail访问。如果要对id进行限制或验证,可以在组件内使用validate()验证; ② 使用/_id/index.vue的写法                ,表示id为必选参数                  ,访问http://domain.com/pages/news/detail会报404                。如果只要求id必填   ,而没有其他格式限制             ,可以使用此方式                  。 ③ validate()验证示例 // return true表示验证通过                  ,return false表示验证失败 404 validate({ params }) { return /^\d+$/.test(params.id) },

2. 关于plugins

用于自定义框架所需的各种插件      ,声明插件后在nuxt.config.js中引入插件即可          ,类似于原框架main.js相关功能   。详见插件 框架已有的插件包(具体用户参照各插件的顶部注释): plugin.js用于全局引入各种npm包; global.js用于声明全局变量与全局方法; request.js实现了全局请求封装(对应@/utils/request.js); filter.js实现了全局请求封装(对应@/utils/filter.js); util.js实现了全局请求封装(对应@/utils/util.js); all.client.js只在客户端引入                  ,用于替代原框架中app.vue中的各种初始化操作; 其他插件可根据需要自行定义         ,*.js表示服务端客户端均导入;*.client.js表示仅在客户端导入;*.server.js表示只在服务端导入;

3. 关于layout

用于定义框架中的各种布局文件       ,可根据需要自行定义                  ,详见布局与视图 默认视图为default.vue            ,默认所有页面都将调用;error.vue是错误视图    ,当页面出现问题时                   ,自动调用; 其他视图               ,可根据需要自行定义,并在组件内部声明引用             。 【组件调用示例】 export default { // 需要调用的视图名称                ,不写默认调用default.vue layout: onlyBody, data(){ return {} } }

4. 关于components

用于定义框架中的各种自定义组件                  ,可根据需要自行定义                  。 自定义组件中的数据   ,一般应从页面传入             ,如果需要再组件内部获取数据                  ,应该使用fetch(子组件中不支持asyncData)      。 components中声明的各种组件      ,在使用时          ,无需import导入          。直接使用组件名按需调用即可                  。 【使用示例】 <template> <div> // Header组件 <Header /> </div> </template>

5. 关于store

store文件夹为Nuxt提供用于定义Vuex状态树的文件夹                  ,详细文档参照:Vuex状态树         。 此文件夹下面的xxx.js         ,分别表示一个模块       ,例如index.js对应$store.state.xxx                  ,而user.js对应$store.state.user.xxx 本框架中store中模块的定义与普通Vue框架大体相同            ,只是Nuxt框架会自动引用Vuex并加载到构建配置重    ,无需我们自己new Vuex() 【使用示例】 /** * 【注意区别】 * state mutations action不再是包裹在一个对象中                   ,并在new Vuex()的时候传入       。 而是分别作为单独模块使用export导出即可                  。 */ export const state = () => ({ counter: 0 }) export const mutations = { increment(state) { state.counter++ } }

6. 关于middleware

middleware是框架中用于声明中间件的文件夹               ,声明后在nuxt.config.js中配置中间件即可,详细文档参照:中间件            。 @/middleware/router.js为已经升级声明好的路由守卫中间件                ,可替代原框架中router.beforeEach中的路由守卫功能;

7. 关于modules

用于自定义模块的文件夹                  ,可以在模块中对Nuxt启动部署的各种声明周期设置监听   ,详细文档参照:模块    。 @/modules/generator.ts实现了一个对静态化结束generate:done时进行监听并处理的示例                   。 const generator: any = function () { this.nuxt.hook(generate:done, (context: any) => { // TODO samething }) } export default generator 类似this.nuxt.hook(generate:done,() => {})的Nuxt框架hooks还有很多             ,例如:ready            、error   、render:before                   、build:compile 等等……详细参见INTERNALS

8. 其他Q&A

1)每个页面                  ,必须使用head设置title      ,必要时还需在详情页设置description               。(!!!切记!!!) export default { head() { return { // title必须设置!!! 列表可以直接写“xxx列表            ”          ,详情页等有不同标题的                  ,要用新闻标题                、商品标题等作为title前缀。 title: this.detail.title + _新闻详情, meta: [ // 详情页         ,需要设置不同的description                。 this.$getDesc 为全局封装的从富文本中截取100字符的description { hid: description, name: description, content: this.$getDesc(this.detail.details) }, ], } } } 2)pages目录中的层级结构       ,务必按照功能梳理清楚                  ,比如“news(新闻)                   ”的列表、详情都要在一个文件夹中                  。

(!!!目录结构一旦确定            ,原则上不可再调整!!!)

3)框架中的其他重要文件之【CSS篇】!! 框架各种css文件    ,位于@/assets/css/中   。框架推荐使用scss语言                   ,使用"sass": "~1.32.13"进行编译; common.scss 为全局公共CSS               ,请将全局样式表声明于此             。或自行定义CSS文件,并在此文件中import导入; font.scss 用于定义本框架各种字体               、图标库等; variables.scss 声明了框架的各种全局Scss变量                ,可以在所有页面使用                  。 注意:全局主题色                  ,请用$mainColor表示   ,不要在各自文件中自行声明! element-variables.scss 是ElementUI的主题声明文件             ,如需全局调整ElementUI的配色                  ,请在此调整; 4)(未完待续…)其他任何框架问题      ,详询小仙男

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
2020互联网最新赚钱方法(互联网以后什么挣钱-零基础也能赚钱的5种互联网方式) win10关闭自动更新方法知乎怎么关(win10关闭自动更新方法是什么)