SSR
?SSR
就是 服务器渲染
,什么是 服务器渲染
?由 服务器
组装好 DOM
元素,生成 HTML
字符串给到浏览器,也就是在浏览器里面是可以看到整个页面的 DOM
源码的。
SSR
解决的问题:
SEO
:搜索引擎的优先爬取级别是页面的 HTML
结构,当我们使用 SSR
的时候,服务端已经生成了与业务相关联的 HTML
,这样的信息对于 SEO
是很友好的。
内容呈现
:客户端无需等待所有的 JS
文件加载完成即可看见渲染的业务相关视图(压力来到了服务端这边,这也是需要做权衡的地方,需要区分哪些由服务端渲染,哪些可以交给客户端)。
SSR
相关的弊端:
代码兼容
:对于开发人员来讲,需要去兼容代码在不同环境的运行 Vue SSR
所需要的服务端环境是 Node
,有一些客户端的对象,比如 dom
、windows
之类的则无法使用。
服务器负载
:相对于前后端分离模式下服务器只需要提供静态资源来说,SSR
需要的服务器负载更大,所以在项目中使用 SSR
模式要慎重,比如一整套图表页面,相对于服务端渲染,可能用户不会在乎初始加载的前几秒,可以交由客户端使用类似于骨架屏,或者懒加载之类的提升用户体验。
Vue
与 Vue SSR
与 原生HTML
页面源码区别对比,在网页上右键查看源码:
Vue SSR
与 原生HTML
是可以看到源码标签的
Vue
默认是看不到源码标签的,因为它是 JS 组装的。
目前做 SSR
的方式有几种,大概列举一下:
1、前端编写 原生静态页面
,给到服务器,通过服务器框架进行组合数据,例如 php
的 Web 开发
。
2、使用 prerender-spa-plugin 插件,作者是 Vue
核心团队的成员,这种实现方式并不叫 SSR
,而是 预渲染
。不过效果上是一样的,甚至某种程度上来说可能要比 SSR
更好。相比官方提供的 SSR 繁琐配置
,prerender
配置更简单快捷。
3、Vue
官方提供的轮子在 Node
端做 SSR
, 相对于 prerender
插件来说,SSR
上手真的超级复杂,有兴趣可以自行查看 Vue SSR 指南。这种方法可以做到真实数据实时渲染,完全可供 SEO
小蜘蛛尽情的爬来爬去,完全前后端同构,路由配置共享,不再影响服务器 404
请求,但是配置比较麻烦、处理流程比较复杂 (比对预渲染插件,复杂太多)约束较多,对服务器会造成较大的压力,服务器成本太高了。
4、Nuxt.js 是使用 Webpack
和 Node.js
进行封装的基于 Vue
的 SSR
框架,不需要自己搭建一套 SSR
程序,而是通过其约定好的文件结构和 API
就可以实现一个首屏渲染的 Web
应用。
我这里选择使用 Nuxt.js 来做 SSR
。
Nuxt.js 官方安装流程,项目需要依赖 Node
环境,我这里用的包管理工具是 NPM
,Nuxt.js
版本是 2.14.5
。
创建项目,确保安装了 npx
(npx
在 NPM
版本 5.2.0
默认安装了):
$ npx create-nuxt-app <项目名>
或者用 yarn
:
$ yarn create nuxt-app <项目名>
我这里用 npx
创建一个测试项目,例如:
$ npx create-nuxt-app nuxt-test
// 进入到文件夹,执行创建项目命令
dengzemiaodeMacBook-Pro:test dengzemiao$ npx create-nuxt-app nuxt-test
create-nuxt-app v3.5.2
✨ Generating Nuxt.js project in nuxt-test
// 项目初始配置,自己看着选,用什么选什么 不懂就选 None,后面也可以装的。
? Project name: nuxt-test
? Programming language: JavaScript
? Package manager: Npm
? UI framework: None
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: (Press to select, to toggle all, to invert sele
ction)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using
typescript)
? What is your GitHub username? dengzemiao
? Version control system: None
.....等待一段时间,就会提示创建项目成功
Successfully created project nuxt-test
// 如果是开发中,运行 npm run dev 就可以,开发者模式
To get started:
cd nuxt-test
npm run dev
// 如果是需要发布到线上了,需要先 build 在 start 才能正式发布
To build & start for production:
cd nuxt-test
npm run build
npm run start
这篇文章只讲 创建项目
到 发布服务器,以及服务器怎么部署才能通过服务器访问
,其他项目细节配置放在其他文章中去写。
创建完成项目之后,可以先运行项目一下,用上面 To get started
或 To build & start for production
中的方式运行起来项目,只是前者是 development
模式,后者是 production
模式。
dengzemiaodeMacBook-Pro:test dengzemiao$ cd nuxt-test
dengzemiaodeMacBook-Pro:nuxt-test dengzemiao$ npm run dev
> [email protected] dev /Users/dengzemiao/Desktop/Project/web/test/nuxt-test
> nuxt
╭───────────────────────────────────────╮
│ │
│ Nuxt @ v2.14.12 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Listening: http://localhost:3000/ │
│ │
╰───────────────────────────────────────╯
然后通过上面的 http://localhost:3000/
打开浏览器进行访问,但是这个是开发环境。
在 pages
里面的 .vue
文件都会被自动转成路由,文件夹也是一样。
例如:项目 pages
文件夹里面有个 index.vue
文件,它会被编译成 index.html
,在路由中也就是 /index
,可以尝试修改 index.vue
里面的内容,或者新建一个 .vue
文件进行测试内容。
例如:我在 pages
里面创建一个测试文件 dzm.vue
,运行起来项目,访问的路径就是 http://localhost:3000/dzm
ip
访问项目(正式和测试都适用)运行开发环境 $ npm run dev
╭───────────────────────────────────────╮
│ │
│ Nuxt @ v2.14.12 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Listening: http://localhost:3000/ │
│ │
╰───────────────────────────────────────╯
运行正式环境 $ npm run build
+ $ npm run start
╭──────────────────────────────────────────╮
│ │
│ Nuxt @ v2.14.12 │
│ │
│ ▸ Environment: production │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Memory usage: 29.1 MB (RSS: 73.1 MB) │
│ │
│ Listening: http://localhost:3000/ │
│ │
╰──────────────────────────────────────────╯
通过上面的两个运行的结果,得到的地址都是 http://localhost:3000/
,这个是固定本地 localhost:3000
才可以进访问,需要改成支持本地 ip
也能访问,也就是你拿到本机电脑的 ip
加上端口也能进行访问到,例如: http://10.0.93.169:3000
找到 nuxt.config.js
,添加下面代码:
export default {
head: {...},
css: [...],
// 配置服务器(主要是这个配置)
server: {
// port: 8000, // default: 3000
// host: '0.0.0.0', // default: localhost,
host: '0', // 等于 host: '0.0.0.0' 这样配置
timing: false
},
再次运行项目,正式或测试都行,访问地址就会变成本机的 ip
地址加端口:
╭─────────────────────────────────────────╮
│ │
│ Nuxt @ v2.14.12 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Memory usage: 29.4 MB (RSS: 74 MB) │
│ │
│ Listening: http://10.0.93.169:3000 │
│ │
╰─────────────────────────────────────────╯
本地运行项目就到这里结束了,下面需要将项目发布到服务器运行起来。
下面的这些操作如果需要测试,可以放在本地机器上进行搭建,把本地电脑当服务器使使。
服务器
安装 Nginx + Node + PM2
。
Nuxt.js
是依赖 Node
,所以 服务器
需要安装 Node
,装了 Node
就会自带 NPM
,然后通过 NPM
安装 PM2
:
$ npm install -g pm2
PM2
是 Node
的进程管理工具。为啥用这个
?举个例子
:运行项目之后,命令行窗口是不能关闭的,如果关闭了就无法访问这个项目地址了,所以需要支持关闭命令行窗口,运行的项目依然能够访问,也就是后台挂起进程,PM2
就可以做到这个事情。
安装好上面环境,在 Nginx
根目录里面通过 Git
拉下来 Nuxt.js
源码,可以新开文件夹存放也是可以的,随你自己
$ git clone xxxxx.git
// 如果存在代码就拉一下代码 保持最新
$ git pull
这里说一下,在网上搜一下会搜到很多只需要导入几个文件就可以运行项目的文章,但是有时候会出现 编译函数找不到
、资源文件找不到
之类的问题,所以如果不是特别熟悉 Nuxt.js
的话,直接将整个项目拉下来使用,不需要去单独导入某些文件,这样也完美的避开一些细节上的坑,例如导入下面几个文件:
.nuxt
static
nuxt.config.js
package.json
package-lock.json
将代码拉到服务器后,需要先走一遍 npm
安装,安装一下依赖包
$ npm install
然后编译项目
$ npm run build
PM2
运行项目,后台挂起,PM2
启动有个需要注意的,那就是 你的项目名称
必须跟项目 package.json
文件里面的 name
字段值一样,一模一样,它是根据这个去标识的,否则不会生效。
// 之前是通过 $ npm run dev 或者 $ npm run start,但是命令行窗口不能关闭
// 启动测试环境后台挂起
$ pm2 start npm --name "你的项目名称" -- run dev
// 启动正式环境后台挂起
$ pm2 start npm --name "你的项目名称" -- run start
在正式服务器就启动正式环境,例如:
$ pm2 start npm --name "nuxt-test" -- run start
然后可以通过 $ pm2 list
查看是否挂起成功,这样显示了就是挂起成功了
┌─────┬──────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├─────┼──────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ nuxt-test │ default │ N/A │ fork │ 1190 │ 0s │ 0 │ online │ 0% │ 7.8mb │ den… │ disabled │
└─────┴──────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
现在就可以通过你这台电脑或者服务器的 ip
地址加端口号进行访问了,例如:http://10.0.90.164:3000/
。
如果需要停掉后台挂起,执行删除命令即可,id
就是 $ pm2 list
列表中的 id
值:
$ pm2 delete id
例如:
$ pm2 delete 0
如果项目修改调整了,上传了新的东西,只需要拉下代码编译后,重启 PM2
对应环境进程即可:
测试环境 - 初始化:$ git pull
+ $ npm install
+ $ pm2 start npm --name "你的项目名称" -- run dev
测试环境 - 初始化:$ git pull
+ $ npm install
+ $ npm run build
+ $ pm2 start npm --name "你的项目名称" -- run start
注意:$ pm2 start ....
命令,每次启动都会在 $ pm2 list
列表中新增一个管理进程,所以只需要初始化创建了就行了,后面如果不是通过 $ pm2 delete id
手动删除了,就不需要每次 $ pm2 start ....
,只需要重启即可:
测试环境 - 后续版本更新:$ git pull
+ $ npm install
+ $ pm2 restart id
正式环境 - 后续版本更新:$ git pull
+ $ npm install
+ $ npm run build
+ $ pm2 restart id
额外说一句:如果 PM2
启动项目之后,不知道访问那个地址,那可以先 $ pm2 delete id
删除进程,执行自带的运行方式 $ npm run dev
或 $ npm run tart
,需要哪个环境就运行哪个命令,运行之后可以拿到访问地址,拿到之后关掉,在通过 PM2
运行访问同意一个地址,注意端口号别变化了,如果端口被占用,会分配一个新的端口:
╭──────────────────────────────────────────╮
│ │
│ Nuxt @ v2.14.12 │
│ │
│ ▸ Environment: production │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Memory usage: 29.4 MB (RSS: 74.6 MB) │
│ │
│ Listening: http://10.0.90.164:3000/ │
│ │
╰──────────────────────────────────────────╯
最终通过 PM2
启动挂起之后,现在需要配置一下 Nginx
,之前启动是 Node
服务,访问是没问题的,但是现在需要通过 Nginx
反代理到 Node
,也就是通过 Nginx
去访问到 Node
的资源地址。
找到 Nginx
的 nginx.conf
文件,在里面添加一个新的服务,以及一个反代理服务
http {
# 新建一个 nuxt server 服务
upstream nuxt {
# 这里就是上面配置的 Node ip + 端口号,之前默认是 localhost:3000
server 0.0.0.0:3000;
keepalive 64;
}
server {
listen 8083; #服务器端口
server_name www.nuxt.com; #这里对应你服务器的域名
location / {
proxy_pass http://nuxt; #这里对应上面 upstream 中新建的服务名
index index.html index.htm;
}
}
}
配置好这个之后,通过 $ nginx
启动 Nginx
或者 $ nginx -s reload
刷新 Nginx
配置文件生效。
配置好之后,启动 Node
,启动 Nginx
,这样就可以直接通过 Node
的 ip + :3000端口
直接访问,也可以通过 Nginx
的 ip或域名 + :8083端口
访问了,对外当然是走 Nginx
了,配置一下域名。
到这就完事了,其他就是项目内部的细节配置跟使用了,会写到另外的文章里面去!
Nuxt.js(Vue SSR)项目配置以及开发细节