Next Js 服务端渲染实战

Nextjs实战开发中遇到的一些问题

  • 1.部署类
    • 1.1静态资源CDN目录
    • 1.2 Node服务的进程守护
    • 1.3 自定义服务器
    • 1.4 多环境部署
  • 2.开发类
    • 2.1 session 用户信息持久化
    • 2.2 配合 Redux使用
  • 3.其他问题
    • 3.1 配合Typescript
    • 3.2 其他方案选择
      • 3.2.1 Umi SSR 方案
      • 3.2.2 Nuxt SSR 方案

1.部署类

项目中使用的是纯SSR方案,以下非特指不包含静态导出方案

1.1静态资源CDN目录

项目开发中使用gitLab的CICD 做持续集成,docker 部署, 静态文件存放阿里云oss

有两个目录可以使用CDN 部署。一个是打包生成的_next/static 目录。一个是项目目录中的static 目录。
_next/static 存放的是打包产生的一些静态资源,每次打包都会变更,有hash值。static存放项目的一些静态资源图片,第三方的库等。

cicd 执行完buildJob,取到_next/staticstatic 目录,上传到阿里云oss

项目中需要修改配置(代码中用到的环境变量会在1.1.4 中说明)

module.exports = withBundleAnalyzer(withLess({
  // CDN 配置 对应`_next/static` 
  assetPrefix: process.env.ASSET_PREFIX || '',
  serverRuntimeConfig: {
  },
  publicRuntimeConfig: {
    NEXT_PUBLIC_APIURL: process.env.NEXT_PUBLIC_APIURL,
     // CDN 配置 对应`static` 
    NEXT_PUBLIC_STATIC: process.env.NEXT_PUBLIC_STATIC
  }
  }))

1.2 Node服务的进程守护

直接安装pm2运行即可。可能会遇到配置文件执行命令传递参数的问题。

后面我们采用了docker 就没有采用pm2 进程守护,每次打包都是全新的容器,都会重新启动。

1.3 自定义服务器

1.4 多环境部署

nextjs 本身支持的环境数量有限,支持四种环境[生产,开发,本地].env.production.env.development.env.local。直接在根目录建这几个文件就好了。作者也做了解释,通用环境就是这么多,不打算做更多兼容。

但是这显然不满足我们公司的所需的环境[本地,测试,预发布,生产],因此引入cross-env ,dotenv自定义环境。

yarn add cross-env dotenv -D

首先在next.config.js 做以下配置

next.config.js
// 环境变量配置
const dotenv = require('dotenv')
const envPath = process.env.DOT_ENV_FILE ? `.dotenv.${process.env.DOT_ENV_FILE}` : '.dotenv.local'
const dotEnvResult = dotenv.config({ path: envPath })
if (dotEnvResult.error) {
  throw dotEnvResult.error
}
console.log(`[运行环境] ======= ${process.env.NEXT_PUBLIC_APIURL} ========`)

根目录添加配置文件,(NEXT_PUBLIC前缀可以在客户端访问,其他只能在服务端访问)

//.dotenv.dev
NEXT_PUBLIC_APIURL=https://api-dev.baidu.com
//.dotenv.test
NEXT_PUBLIC_APIURL=https://api-test.baidu.com
//.dotenv.pre
NEXT_PUBLIC_APIURL=https://api-pre.baidu.com
//.dotenv.prod
NEXT_PUBLIC_APIURL=https://api.baidu.com

最后修改package.json script 配置

  "scripts": {
    "build:dev": "cross-env DOT_ENV_FILE=dev next build",
    "build:test": "cross-env DOT_ENV_FILE=test next build",
    "build:pre": "cross-env DOT_ENV_FILE=pre next build",
    "build:prod": "cross-env DOT_ENV_FILE=prod next build",
  },

在项目中即可使用该环境变量

process.env.NEXT_PUBLIC_APIURL

2.开发类

2.1 session 用户信息持久化

服务端渲染登录真的是十分令人头疼的问题,服务端没法做当前用户信息持久化,用户登录的Token信息无法保存。只能使用Cookie来保存这类信息。流程如下,

  1. 登录完成后拿到token
  2. 把token保存到cookie里面,这里要注意服务端设置cookie跟客户端不同,客户端就忽略了,服务端是通过NextPageContext 或者是 AppContext 来设置的,直接取context 对象的req.header.cookies 修改。
  3. 每次请求的是否去cookie里面去token,带给后台就可以实现登录。这里取token 跟 设置token 一样不同端不同处理,服务端通过context 处理

推荐一个库 next-cookie 自动帮你处理,支持hooks 用法

// 安装
yarn add next-cookie

// 使用
import { useCookie } from 'next-cookie';
const cookies = useCookie(context)
cookies.set('XX_TOKEN', 'XXXXXX')

2.2 配合 Redux使用

没有很复杂的状态管理不建议用Redux,不是很好用

在Nextjs 里 Redux 也是分端使用的,也就是说服务端的redux 并不能持久。官方推荐的方案时在初始化是把服务端的state,同步到客户端。在客户端做持久化。

3.其他问题

3.1 配合Typescript

大部分问题都还是React 配合 TS 的问题,Nextjs 这块基本还好,几个声明周期钩子声明即可。

import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'

export const getStaticProps: GetStaticProps = async (context) => {
  // ...
}

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

export const getServerSideProps: GetServerSideProps = async (context) => {
  // ...
}

详细的参考next 官网,无法解决的使用any大法。
Next Typescript

3.2 其他方案选择

3.2.1 Umi SSR 方案

上线后,自己在看umi框架的时候发现umi支持SSR

umi 官方给出的umi 与 nextjs 对比。

next.js 是个很好的选择,Umi 很多功能是参考 next.js 做的。要说有哪些地方不如 Umi,我觉得可能是不够贴近业务,不够接地气。比如 antd、dva 的深度整合,比如国际化、权限、数据流、配置式路由、补丁方案、自动化 external 方面等等一线开发者才会遇到的问题。

umi 的优点就是简单配置,开箱即用封装了很多东西在里面,你能省掉很大一部分折腾的实践。文档以及社区都是中文的,还有一些论坛,IM群都是国内的在沟通,沟通成本低。

缺点:

  1. umi ssr 大部分参考nextjs ,甚至除了框架本身,其他的库也参考了,umi-request 基本上跟SWR 差不多。目前的话最新的一些特性,肯定是nextjs 先有的。后续就看umi 的生态搞的怎么样了。

  2. umi 默认预装一堆没用的插件进去,有些插件不用打包的时候也硬打进去了,移除时候有点儿麻烦

如果说有精力去踩坑,英文水平还可以的同学可以直接使用nextjs 方案,最新的特性,生态整个也比umi要好些。(中文文档是有些欠缺的)

想省事的话可以直接使用umi的(虽然最终不一定省事)

3.2.2 Nuxt SSR 方案

你可能感兴趣的:(框架踩坑,学习提升,typescript,reactjs,react,node.js)