1. 为什么要尝试SSR实践
- 项目有SEO需求
 - 更适应于项目需求频繁变更,若采用传统的后端模版会使开发成本会更大,可以减轻后端开发成员负担
 - 加快单页面应用首屏加载速度
 - 方便前端接口服务端转发及独立部署
 
2. Next.js的使用
Next.js在SSR方面表现便捷而优越,这里选择其作为SSR技术框架,点击前往next.js官网
2.1 安装
yarn create next-app --typescript
2.2 脚手架默认添加的命令
yarn dev # 开发环境命令yarn build # 打包yarn start # 生产环境命令
2.3 初步尝试感悟
create next app的使用与create react app大致相同,此外Next还提供了一些内置组件如route、link、image、head、server等;如需添加项目配置,可编辑根目录next.config.js。
2.4 添加Less支持、Ant Mobile 支持
注:笔者使用的版本next 12+、 Ant Mobile 5+
添加依赖
# less需要用到的库yarn add less less-loader next-with-less# Ant Mobile需要用的库yarn add antd-mobile@nextyarn add -D next-transpile-modules next-images
编辑根目录next.config.js如下
/** @type {import('next').NextConfig} */const withLess = require("next-with-less")const withImages = require('next-images')const withTM = require('next-transpile-modules')(['antd-mobile',]);// const lessToJS = require('less-vars-to-js');// const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './static/modifyVars.less'), 'utf8'))module.exports = withLess({lessLoaderOptions: {// modifyVars: themeVariables, // make your antd custom effectivelessOptions: {modifyVars: {"@primary-color": "#ff0000",}},},reactStrictMode: true,env: {customKey: 'hello'},...withTM(withImages()),});
vscode 引入less文件虽然开发环境可用,但是build会报错无法识别less后缀文件,而且import行会出现红色下划线,强迫症锦囊: 在项目目录/node_modules/next/types/global.d.ts中新增代码如下:
declare module '*.module.less' {const classes: { readonly [key: string]: string }export default classes}
2.5 添加Antd
安装依赖,笔者安装时的最新版本:4.17.3
yarn add antd
默认是没有样式的,需要在pages/_app.ts中全局引入样式
import 'antd/dist/antd.css'
2.6 实现接口代理
接口代理常用来解决跨域问题以及提高安全性问题,接口代理需要启用Node服务,这里使用express作为服务框架
安装依赖
yarn add express http-proxy-middleware axios
在根目录添加server.js,添加内容如下
const express = require('express')const next = require('next')const { createProxyMiddleware } = require('http-proxy-middleware')const devProxy = {'/api/': {target: 'http://xx.xx.xx.xx:8080',pathRewrite: {'^/api': ''},changeOrigin: true}}const prodProxy = {'/api/': {target: 'http://xx.xx.xx.xx:8080',pathRewrite: {'^/api': ''},changeOrigin: true}}const port = process.env.PORT || 3000const hostanme = '0.0.0.0'const dev = process.env.NODE_ENV !== 'production'const app = next({dev})const handle = app.getRequestHandler()app.prepare().then(() => {const server = express()if (dev) {!!devProxy && Object.keys(devProxy).forEach(context => {server.use(createProxyMiddleware(context, devProxy[context]))})} else {!!prodProxy && Object.keys(devProxy).forEach(context => {server.use(createProxyMiddleware(context, prodProxy[context]))})}server.all('*', (req, res) => {handle(req, res)})server.listen(port, hostanme, err => {if (err) {throw err}console.log(`> Ready on http://${hostanme}:${port}`)})}).catch((err) => {console.log('An error occurred, unable to start the server')console.log('发生错误,无法启动服务器')console.log(err)})
配置启用命令,在package.json新增内容如下
{..."scripts": {"server": "node server.js","start": "next start","build": "next build","lint": "next lint"},...}
接口代理使用
import axios from "axios";const fetchData = async () => {const res = await axios.get('/api/day1/student?id=1');if(!res) return;Toast.show({icon: 'success',content: res.data,})}
启用服务(yarn server)即可愉快的进行编码了
2.7 使用pm2守护进程
使用node启用服务需要占用一个终端窗口,而且很容易挂掉服务,这里推荐pm2用来守护进程
安装依赖
yarn global add pm2@latest
切换到项目根目录执行如下命令,即可开启守护进程
pm2 start server.js# 默认在3000端口开启服务
添加pm2配置文件,在项目根目录执行pm2 ecosystem会生成一个ecosystem.config.js文件,编辑内容如下
module.exports = {apps: [{name: "demo02", // 应用名script: 'server.js', // 入口文件watch: false,// 配置环境变量env: {"PORT": 3001,"NODE_ENV": "development",},env_dev: {"PORT": 3001,"NODE_ENV": "development"},env_production: {"PORT": 3000,"NODE_ENV": "production",}}],deploy: {// 部署生产环境production: {user: 'root', // 服务器登录用户host: '122.xx.xx.xx', // 服务器地址ref: 'origin/main', // git发布分支repo: 'https://github.com/debugksir/ssr_next_demo.git', // 项目git库地址path: '/data/www/ssr_next', // 服务器路径'pre-deploy-local': '', // 部署前本地命令'post-deploy': 'git pull origin main && yarn start',// 'post-deploy': 'git pull origin main && yarn && yarn build && pm2 reload ecosystem.config.js --env production','pre-setup': '' // 启动前命令}}};
集成到项目命令集中,修改package.json如下,至此就可以使用yarn start来在服务器上部署生产服务啦
{..."scripts": {"server": "node server.js","start": "yarn && next build && pm2 reload ecosystem.config.js --env production","deploy": "pm2 deploy ecosystem.config.js production","build": "next build","lint": "next lint"},...}
yarn server : 开发模式
yarn start : 服务测一键部署
yarn deploy : 开发者测一键部署
到这里就可以使用以上命令来一键开发与部署自己的服务了
常用pm2命令如下:
pm2 -h # 查看帮助文档pm2 list # 列举pm2启动的服务列表pm2 start xxx # 启动服务pm2 restart xxx # 重启服务pm2 stop id # 停止服务pm2 delete|del id # 停止并删除服务pm2 kill # 杀掉所有进程查看pm2 日志: pm2 logs查看服务仪表盘:pm2 monit 或者 pm2 monitor 或者 pm2 pluspm2生成配置文件: pm2 ecosystempm2启动命令: pm2 reload ecosystem.config.js --env developmentpm2启动命令: pm2 reload ecosystem.config.js --env production (切记生产环境启动之前需要build)
使用Nginx
由于Nginx更擅长处理网络请求、反向代理、负载均衡、资源压缩等,所以使用Nginx处理它擅长的事物。点击查看在Mac安装Nginx
配置Nginx反向代理到Node服务
server {listen 8080;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location / {root html;index index.html index.htm;proxy_pass http://127.0.0.1:3000; # 反向代理到node服务}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
配置好后重启Nginx(nginx -s reload),访问 http://本机ip:8080 查看结果吧!
如果是linux系统启动命令为(service nginx reload 或者 systemctl reload nginx.service)
补充
在nginx配置文件中添加如下代码开启静态资源代理:
location /_next/ {alias /data/www/ssr_next/source/.next/;autoindex on;}
开启压缩开关:
gzip  on;
完整的nginx配置
#user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024;}http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;gzip on;server {listen 8080;location / {proxy_pass http://127.0.0.1:3000;}location /_next/ {alias /data/www/ssr_next/source/.next/;autoindex on;}}}
源码:
点击查看源码
