Next.js启动打包部署(out、standalone)
创始人
2024-11-04 14:04:35
0

之前用Next.js开发了一个全栈项目,用得最新版本14.2.4,网上文档偏少,踩了一些坑,故总结下,给有需要的朋友。

Next.js 支持在页面级的 静态生成 (SSG) 和 服务器端渲染 (SSR)

一、启动

  1. node.js版本需要大于18.17

在这里插入图片描述

  1. 指定文件路径下执行npx create-next-app@latest
npx create-next-app@latest 
  1. 按需安装可选项

![[Pasted image 20240701094602.png]]

  1. 安装完成后进入项目目录,执行npm run dev启动
npm run dev 

浏览器打开:http://localhost:3000/ 即可看到页面,随意改点东西看到,页面热更新正常

![[Pasted image 20240701095321.png]]

  1. app路由

这里我们在安装时使用的是app router,约定式路由,src/app下创建/about/page.tsxt,
文件夹about即为路径,文件page.tsx为页面

eg: 简单创建一个about页面

![[Pasted image 20240701100652.png]]

page页面跳转about

![[Pasted image 20240701100754.png]]
![[Pasted image 20240701100829.png]]

  1. api

正常api会操作数据库等,这里简单写一个服务端api,也是约定式路由,在src/app下创建/api/user/route.ts
![[Pasted image 20240701102229.png]]

import { NextResponse } from 'next/server'  export async function GET(req: any) {   try {     const data = [       { id: 1, name: '张三', age: 18 },       { id: 2, name: '李四', age: 20 },     ]     return NextResponse.json({ data }, { status: 200 })   } catch (error) {     console.error('Error:', error)     return NextResponse.json(       { error: 'Internal Server Error' },       { status: 500 }     )   } } 

浏览器访问:http://localhost:3000/api/user 即可看到数据返回

![[Pasted image 20240701102347.png]]

  1. 封装axios

前端接口请求一般可以用fetch或者axios,这里项目用了axios,首先安装axios,终端执行npm i axios

npm i axios 

app文件夹下新建两个文件,/request/index.js和/request/app.js,一个是axios的封装,一个是请求api方法

![[Pasted image 20240701102926.png]]
![[Pasted image 20240701102938.png]]

// request/index.js import axios from 'axios'  const service = axios.create({   baseURL: '/',   timeout: 50000 })  // 请求拦截器 service.interceptors.request.use(config => {   return config }, error => {   return error })  // 响应拦截器 service.interceptors.response.use(response => {   if (response.status) {     switch (response.status) {       case 200:         return response.data       case 401:         //未登录处理方法         break       case 403:         //token过期处理方法         break       default:         console.log();(response.data.msg)     }   } else {     return response   } }) export default service 
// /request/app.js import service from "./index"  export const getUserList = (params) =>   service({ url: "/api/user", method: "get", params }) 
  1. 页面请求数据

在page.tsx请求数据渲染即可

![[Pasted image 20240701103859.png]]
![[Pasted image 20240701103914.png]]

至此,简单的项目搭建完成。

二、打包部署

1. 默认打包
npm run build 

打包完成后,需要拷贝.next、node_modules、public、package.json四个文件到服务器

![[Pasted image 20240701105539.png]]

★服务器需要安装node环境,https://nodejs.cn/en/download

执行npm run start

npm run start 

页面打开:http://localhost:3000 正常访问

![[Pasted image 20240701105449.png]]

项目部署完成,四个文件占用356MB,node_modules占用303MB,我们正常开发vue、react项目打包后无需node_modules,能否去掉

删除node_modules再启动,发现无法启动:

![[Pasted image 20240701110517.png]]

2. 静态打包out

前面说了默认打包,需要node.js环境和拷贝node_modules文件夹,如果我们只用了next.js静态部分,没用到api服务,官方提供了静态打包方式。

在配置文件next.config.mjs中添加output: ‘export’

![[Pasted image 20240701110919.png]]

再执行npm run build打包

打包后,可以看到根目录下生成了out文件夹(0.98MB),拷贝out到服务器,通过nginx等代理即可

![[Pasted image 20240701142202.png]]

nginx配置:

![[Pasted image 20240701111824.png]]

打开:http://localhost:82/ 访问

![[Pasted image 20240701111845.png]]

可以看到页面能正常访问,而且api用户列表也能显示???

按理说都静态打包了,咋还能看到api服务,其实这是next.js的静态处理,或者说缓存,是一种自动行为,Next.js认为并不是每次GET请求都需要重新计算,所以干脆直接处理成静态数据提升性能。

如果想动态处理:

  1. 操作cookies()、headers() 函数
const token = request.cookies.get('token') 
  1. 改成POST方法
  2. 在页面引入动态模块:
export const dynamic = 'force-dynamic' 

但是动态处理和静态打包冲突报错,所以静态打包最好就不要api了

![[Pasted image 20240701141305.png]]

3. standalone单独部署

前面说了默认打包时需要拷贝node_modules,导致项目体积很大;而且随着项目的开发,依赖包一般可能达到1个G左右,这就导致部署成本相当高。做过express应用应该知道,node的服务依赖包其实不多,这里的node_modules很多都是前端的依赖,我们都打包了,其实没必要带着这些依赖。所以next.js还推出了一种打包方式:standalone。

直接在配置文件next.config.mjs中加上output: ‘standalone’

![[Pasted image 20240701141955.png]]

再执行npm run build打包,可以看到在.next文件夹中生成了standalone和static文件夹

![[Pasted image 20240701142435.png]]

standalone相当于一个express应用,包含server.js和少量的服务端依赖node_modules
static是前端包

部署时,需要拷贝static到standalone/.next文件夹下,拷贝外层public文件夹到standalone下

![[Pasted image 20240701143104.png]]

进入standalone目录,执行node server.js

node server.js 

打开页面:http://localhost:3000/和接口:http://localhost:3000/api/user都能正常访问。

standalone只有19MB,相对于默认打包方式存储大大减少,不知道官方为啥不作为默认打包方式,有时间再研究。


嫌拷贝static麻烦的朋友可以在package.json中增加配置:

在这里插入图片描述

    "build": "next build && npm run move",     "move": "xcopy /e /i .next\\static .next\\standalone\\.next\\static" 

三、其它问题

Q1:接口有缓存?

实际项目时,发现查询sql数据不对,后面发现是get请求缓存了,前面也说过使用动态模块避免缓存:

export const dynamic = 'force-dynamic' 

![[Pasted image 20240701150502.png]]

Q2:You’re importing a component that needs useState. It only works in a Client Component but none of its parents are marked with “use client”, so they’re Server Components by default.

常见的错误,当页面使用useState等功能时,需要在顶部引入use client指令,表明当前组件/模块应该在客户端渲染(Client-side Rendering,CSR)

![[Pasted image 20240701145155.png]]


项目地址:https://github.com/qsya/nextjs
中文官网:https://www.nextjs.cn/
英文官网:https://nextjs.org/

相关内容

热门资讯

透视辅助!aapoker怎么拿... 透视辅助!aapoker怎么拿好牌,aapoker免费透视脚本,存在挂教程(有挂黑科技);1、透视辅...
小程序广东雀神智能插件免费,开... 小程序广东雀神智能插件免费,开心泉州小程序辅助免费下载,白金岛手游的作弊码细节1、小程序广东雀神智能...
透视数据!wepoker怎么买... 透视数据!wepoker怎么买辅助(透视)一直真的是有挂(玩家教程)1、每一步都需要思考,不同水平的...
透视了解!aapoker怎么控... 透视了解!aapoker怎么控制牌,aapoker辅助软件合法吗,解密教程(有挂辅助)1、任何aap...
广东麻雀有什么技巧,来趣广西辅... 广东麻雀有什么技巧,来趣广西辅助,白金岛辅助有用吗解说;1、来趣广西辅助系统规律教程、来趣广西辅助辅...
透视了解!wepoker私人局... 透视了解!wepoker私人局俱乐部(透视)果然真的有挂(新2025教程);1、操作简单,无需注册,...
透视私人局!aapoker透视... 透视私人局!aapoker透视脚本,aapoker怎么控制牌,透视教程(有挂插件);在进入aapok...
广东雀神智能ios插件安装包,... 广东雀神智能ios插件安装包,欢乐联盟辅助软件,闲逸透视app为什么免费介绍;1)欢乐联盟辅助软件辅...
透视能赢!wepoker可以免... 透视能赢!wepoker可以免费玩吗(透视)总是真的是有挂(微扑克教程)1、上手简单,内置详细流程视...
透视挂透视!aapoker透视... 透视挂透视!aapoker透视脚本,aapoker辅助器怎么用,科技教程(有挂插件)在进入aapok...