项目中使用的是纯SSR方案,以下非特指不包含静态导出方案
项目开发中使用gitLab的CICD 做持续集成,docker
部署, 静态文件存放阿里云oss
。
有两个目录可以使用CDN 部署。一个是打包生成的_next/static
目录。一个是项目目录中的static
目录。
_next/static
存放的是打包产生的一些静态资源,每次打包都会变更,有hash值。static
存放项目的一些静态资源图片,第三方的库等。
cicd 执行完build
Job,取到_next/static
和 static
目录,上传到阿里云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
}
}))
直接安装pm2运行即可。可能会遇到配置文件执行命令传递参数的问题。
后面我们采用了docker 就没有采用pm2 进程守护,每次打包都是全新的容器,都会重新启动。
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
服务端渲染登录真的是十分令人头疼的问题,服务端没法做当前用户信息持久化,用户登录的Token信息无法保存。只能使用Cookie来保存这类信息。流程如下,
推荐一个库 next-cookie 自动帮你处理,支持hooks 用法
// 安装
yarn add next-cookie
// 使用
import { useCookie } from 'next-cookie';
const cookies = useCookie(context)
cookies.set('XX_TOKEN', 'XXXXXX')
没有很复杂的状态管理不建议用Redux,不是很好用
在Nextjs 里 Redux 也是分端使用的,也就是说服务端的redux 并不能持久。官方推荐的方案时在初始化是把服务端的state,同步到客户端。在客户端做持久化。
大部分问题都还是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
上线后,自己在看umi框架的时候发现umi支持SSR
umi 官方给出的umi 与 nextjs 对比。
next.js 是个很好的选择,Umi 很多功能是参考 next.js 做的。要说有哪些地方不如 Umi,我觉得可能是不够贴近业务,不够接地气。比如 antd、dva 的深度整合,比如国际化、权限、数据流、配置式路由、补丁方案、自动化 external 方面等等一线开发者才会遇到的问题。
umi 的优点就是简单配置,开箱即用封装了很多东西在里面,你能省掉很大一部分折腾的实践。文档以及社区都是中文的,还有一些论坛,IM群都是国内的在沟通,沟通成本低。
缺点:
umi ssr 大部分参考nextjs ,甚至除了框架本身,其他的库也参考了,umi-request 基本上跟SWR 差不多。目前的话最新的一些特性,肯定是nextjs 先有的。后续就看umi 的生态搞的怎么样了。
umi 默认预装一堆没用的插件进去,有些插件不用打包的时候也硬打进去了,移除时候有点儿麻烦
如果说有精力去踩坑,英文水平还可以的同学可以直接使用nextjs 方案,最新的特性,生态整个也比umi要好些。(中文文档是有些欠缺的)
想省事的话可以直接使用umi的(虽然最终不一定省事)