Next.js啟動(dòng)打包部署的方法詳解(out、standalone)
前言
之前用Next.js開發(fā)了一個(gè)全棧項(xiàng)目,用得最新版本14.2.4,網(wǎng)上文檔偏少,踩了一些坑,故總結(jié)下,給有需要的朋友。
Next.js 支持在頁(yè)面級(jí)的 靜態(tài)生成 (SSG) 和 服務(wù)器端渲染 (SSR)
一、啟動(dòng)
- node.js版本需要大于18.17

- 指定文件路徑下執(zhí)行npx create-next-app@latest
npx create-next-app@latest
- 按需安裝可選項(xiàng)

- 安裝完成后進(jìn)入項(xiàng)目目錄,執(zhí)行npm run dev啟動(dòng)
npm run dev
瀏覽器打開:http://localhost:3000/ 即可看到頁(yè)面,隨意改點(diǎn)東西看到,頁(yè)面熱更新正常

- app路由
這里我們?cè)诎惭b時(shí)使用的是app router,約定式路由,src/app下創(chuàng)建/about/page.tsxt,
文件夾about即為路徑,文件page.tsx為頁(yè)面
eg: 簡(jiǎn)單創(chuàng)建一個(gè)about頁(yè)面

page頁(yè)面跳轉(zhuǎn)about


- api
正常api會(huì)操作數(shù)據(jù)庫(kù)等,這里簡(jiǎn)單寫一個(gè)服務(wù)端api,也是約定式路由,在src/app下創(chuàng)建/api/user/route.ts

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 即可看到數(shù)據(jù)返回

- 封裝axios
前端接口請(qǐng)求一般可以用fetch或者axios,這里項(xiàng)目用了axios,首先安裝axios,終端執(zhí)行npm i axios
npm i axios
app文件夾下新建兩個(gè)文件,/request/index.js和/request/app.js,一個(gè)是axios的封裝,一個(gè)是請(qǐng)求api方法


// request/index.js
import axios from 'axios'
const service = axios.create({
baseURL: '/',
timeout: 50000
})
// 請(qǐng)求攔截器
service.interceptors.request.use(config => {
return config
}, error => {
return error
})
// 響應(yīng)攔截器
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 })
- 頁(yè)面請(qǐng)求數(shù)據(jù)
在page.tsx請(qǐng)求數(shù)據(jù)渲染即可


至此,簡(jiǎn)單的項(xiàng)目搭建完成。
二、打包部署
1. 默認(rèn)打包
npm run build
打包完成后,需要拷貝.next、node_modules、public、package.json四個(gè)文件到服務(wù)器

★服務(wù)器需要安裝node環(huán)境,https://nodejs.cn/en/download
執(zhí)行npm run start
npm run start
頁(yè)面打開:http://localhost:3000 正常訪問

項(xiàng)目部署完成,四個(gè)文件占用356MB,node_modules占用303MB,我們正常開發(fā)vue、react項(xiàng)目打包后無需node_modules,能否去掉
刪除node_modules再啟動(dòng),發(fā)現(xiàn)無法啟動(dòng):

2. 靜態(tài)打包out
前面說了默認(rèn)打包,需要node.js環(huán)境和拷貝node_modules文件夾,如果我們只用了next.js靜態(tài)部分,沒用到api服務(wù),官方提供了靜態(tài)打包方式。
在配置文件next.config.mjs中添加output: ‘export’

再執(zhí)行npm run build打包
打包后,可以看到根目錄下生成了out文件夾(0.98MB),拷貝out到服務(wù)器,通過nginx等代理即可

nginx配置:

打開:http://localhost:82/ 訪問

可以看到頁(yè)面能正常訪問,而且api用戶列表也能顯示???
按理說都靜態(tài)打包了,咋還能看到api服務(wù),其實(shí)這是next.js的靜態(tài)處理,或者說緩存,是一種自動(dòng)行為,Next.js認(rèn)為并不是每次GET請(qǐng)求都需要重新計(jì)算,所以干脆直接處理成靜態(tài)數(shù)據(jù)提升性能。
如果想動(dòng)態(tài)處理:
- 操作cookies()、headers() 函數(shù)
const token = request.cookies.get('token')
- 改成POST方法
- 在頁(yè)面引入動(dòng)態(tài)模塊:
export const dynamic = 'force-dynamic'
但是動(dòng)態(tài)處理和靜態(tài)打包沖突報(bào)錯(cuò),所以靜態(tài)打包最好就不要api了

3. standalone單獨(dú)部署
前面說了默認(rèn)打包時(shí)需要拷貝node_modules,導(dǎo)致項(xiàng)目體積很大;而且隨著項(xiàng)目的開發(fā),依賴包一般可能達(dá)到1個(gè)G左右,這就導(dǎo)致部署成本相當(dāng)高。做過express應(yīng)用應(yīng)該知道,node的服務(wù)依賴包其實(shí)不多,這里的node_modules很多都是前端的依賴,我們都打包了,其實(shí)沒必要帶著這些依賴。所以next.js還推出了一種打包方式:standalone。
直接在配置文件next.config.mjs中加上output: ‘standalone’

再執(zhí)行npm run build打包,可以看到在.next文件夾中生成了standalone和static文件夾

standalone相當(dāng)于一個(gè)express應(yīng)用,包含server.js和少量的服務(wù)端依賴node_modules
static是前端包
部署時(shí),需要拷貝static到standalone/.next文件夾下,拷貝外層public文件夾到standalone下

進(jìn)入standalone目錄,執(zhí)行node server.js
node server.js
打開頁(yè)面:http://localhost:3000/和接口:http://localhost:3000/api/user都能正常訪問。
standalone只有19MB,相對(duì)于默認(rèn)打包方式存儲(chǔ)大大減少,不知道官方為啥不作為默認(rèn)打包方式,有時(shí)間再研究。
嫌拷貝static麻煩的朋友可以在package.json中增加配置:

"build": "next build && npm run move",
"move": "xcopy /e /i .next\\static .next\\standalone\\.next\\static"
三、其它問題
Q1:接口有緩存?
實(shí)際項(xiàng)目時(shí),發(fā)現(xiàn)查詢sql數(shù)據(jù)不對(duì),后面發(fā)現(xiàn)是get請(qǐng)求緩存了,前面也說過使用動(dòng)態(tài)模塊避免緩存:
export const dynamic = 'force-dynamic'

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.
常見的錯(cuò)誤,當(dāng)頁(yè)面使用useState等功能時(shí),需要在頂部引入use client指令,表明當(dāng)前組件/模塊應(yīng)該在客戶端渲染(Client-side Rendering,CSR)

項(xiàng)目地址:https://github.com/qsya/nextjs
中文官網(wǎng):https://www.nextjs.cn/
英文官網(wǎng):https://nextjs.org/
總結(jié)
到此這篇關(guān)于Next.js啟動(dòng)打包部署方法的文章就介紹到這了,更多相關(guān)Next.js啟動(dòng)打包部署內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)的簡(jiǎn)單的表單驗(yàn)證
這篇文章主要介紹了javascript實(shí)現(xiàn)的簡(jiǎn)單的表單驗(yàn)證的相關(guān)資料,需要的朋友可以參考下2015-07-07
使用Javascript在HTML中顯示實(shí)時(shí)時(shí)間
這篇文章主要為大家詳細(xì)介紹了使用Javascript在HTML中顯示實(shí)時(shí)時(shí)間,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明
本篇文章主要介紹了js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-12-12
JS實(shí)現(xiàn)拖拽元素時(shí)與另一元素碰撞檢測(cè)
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)拖拽元素時(shí)與另一元素碰撞檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
網(wǎng)易JS面試題與Javascript詞法作用域說明
Javascript函數(shù)在定義它們的作用域里運(yùn)行,而不是在執(zhí)行它們的作用域里運(yùn)行。2010-11-11
JavaScript實(shí)現(xiàn)無窮滾動(dòng)加載數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)無窮滾動(dòng)加載數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
javascript cookie的簡(jiǎn)單應(yīng)用
這篇文章主要介紹了javascript cookie的簡(jiǎn)單應(yīng)用,我們先介紹一下cookie的使用,以及我后面簡(jiǎn)單封裝一個(gè)cookie操作的單例,便于實(shí)現(xiàn)cookie的設(shè)置,獲取,刪除的方法,感興趣的小伙伴們可以參考一下2016-02-02

