作者:京东零售 姜欣
关于服务器端渲染方案,之前只接触了基于react的Next.js,最近业务开发vue用的比较多,所以调研了一下vue的服务器端渲染方案 。首先:长文预警,下文包括了两种方案的实践,没有耐心的小伙伴可以直接跳到方案标题下,down代码体验一下 。
前置知识:1、什么是服务器端渲染(ssr)?
简单来说就是用户第一次请求页面时,页面上的内容是通过服务器端渲染生成的,浏览器直接显示服务端返回的完整html就可以,加快首屏显示速度 。
举个栗子:
当我们访问一个商品列表时,如果使用客户端渲染(csr),浏览器会加载空白的页面,然后下载js文件,通过js在客户端请求数据并渲染页面 。如果使用服务器端渲染(ssr),在请求商品列表页面时,服务器会获取所需数据并将渲染后的HTML发送给浏览器,浏览器一步到位直接展示,而不用等待数据加载和渲染,提高用户的首屏体验 。
2、服务器端渲染的优缺点
优点:
(1)更好的seo:抓取工具可以直接查看完全渲染的页面 。现在比较常用的交互是页面初始展示 loading 菊花图,然后通过异步请求获取内容,但是但抓取工具并不会等待异步完成后再行抓取页面内容 。
(2)内容到达更快:不用等待所有的 js 都完成下载并执行,所以用户会更快速地看到完整渲染的页面 。
缺点:
(1)服务器渲染应用程序,需要处于 Node.js server 运行环境
(2)开发成本比较高
总结:
总得来说,决定是否使用服务器端渲染,取决于具体的业务场景和需求 。对于具有大量静态内容的简单页面,客户端渲染更合适一些,因为它可以更快地加载页面 。但是对于需要从服务器动态加载数据的复杂页面,服务器端渲染可能是一个更好的选择,因为他可以提高用户的首屏体验和搜索引擎优化 。
下面进入正文
方案一:vue插件vue-server-render
git 示例demo地址
结论前置:不建议用,配置成本高
官网地址: https://v2.ssr.vuejs.org/zh/
首先要吐槽一下官网,按官网教程比较难搞,目录安排的不太合理,一顿操作项目都没起来...
并且官网示例的构建配置代码是webpack4的,现在初始化项目后基本安装的都是webpack5,有一些语法不同
(1)首先,先初始化一个npm项目,然后安装依赖得到一个基础项目。(此处要注意vue-server-renderer 和 vue 必须匹配版本)npm init -yyarn add vue vue-server-renderer -Syarn add express -Syarn add webpack webpack-cli friendly-errors-webpack-plugin vue-loader babel-loader @babel/core url-loader file-loader vue-style-loader css-loader sass-loader sass webpack-merge webpack-node-externals -Dyarn add clean-webpack-plugin @babel/preset-env -Dyarn add rimraf // 模拟linx的删除命令,在build时先删除distyarn add webpack-dev-middleware webpack-hot-middleware -Dyarn add chokidar -D //监听变化yarn add memory-fs -Dyarn add nodemon -D...实在太多,如有缺失可以在package.JSON中查找另外:我现在用的"vue-loader": "^15.9.0"版本,之前用的是"vue-loader": "^17.0.1",报了一个styles的错
(2)配置App.js,entry-client.js,entry-server.js,将官网参考中的示例代码拷贝至对应文件 。
app.js
import Vue from 'vue'import App from './App.vue'import { createRouter } from './router'import { createStore } from './store'import { sync } from 'vuex-router-sync'// 导出一个工厂函数,用于创建新的// 应用程序、router 和 store 实例export function createApp () {// 创建 router 和 store 实例const router = createRouter()const store = createStore()sync(store, router)const app = new Vue({router,store,render: h => h(App)return { app, router, store }
entry-client.js
import Vue from 'vue'import { createApp } from './app'Vue.mixin({beforeMount () {const { asyncData } = this.$optionsif (asyncData) {this.dataPromise = asyncData({store: this.$store,route: this.$routeconst { app, router, store } = createApp()if (window.__INITIAL_State__) {store.replaceState(window.__INITIAL_STATE__)router.onReady(() => {// 在初始路由 resolve 后执行,// 使用 `router.beforeResolve()`,以便确保所有异步组件都 resolve 。router.beforeResolve((to, from, next) => {const matched = router.getMatchedComponents(to)const prevMatched = router.getMatchedComponents(from)// 找出两个匹配列表的差异组件let diffed = falseconst activated = matched.filter((c, i) => {return diffed || (diffed = (prevMatched[i] !== c))if (!activated.length) {return next()Promise.all(activated.map(c => {if (c.asyncData) {return c.asyncData({ store, route: to })})).then(() => {next()}).catch(next)app.$mount('#app')
推荐阅读
- 免费开源、跨网段的机房电脑监控软件Veyon安装与配置
- 电压从1V到10亿V,都会发生怎样的神奇现象?
- 仅6.1%应届本科生起薪过万,幸福感高但工资不高的工作更受欢迎
- 车子保险在哪里查询,如何看二手车的车况
- 清洗草莓,正确的方法是这样的
- N档只是装饰?老司机:用来装饰你的车子就报废了
- 车辆经过就闪的摄像头,会被拍吗,是不是违章看仔细
- scott自行车哪国牌子?scott硬尾山地车假的多吗?
- 淘宝图片空间在哪里找?有没有免费的淘宝图片空间啊?
- 曲奇饼干的做法烤箱--饼干的做法大全电烤箱?