最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

服務端渲染nextjs項目接入經(jīng)驗總結分析

 更新時間:2023年11月09日 10:00:50   作者:路邊縣  
這篇文章主要為大家介紹了服務端渲染nextjs項目接入經(jīng)驗總結分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

背景介紹

服務端渲染 nextjs@13 項目接入經(jīng)驗總結,本文重點介紹基本知識點/常用的知識點/關鍵知識點

為提高首屏渲染速度減少白屏時間提高用戶體驗及豐富技術面,開始調研和接入nextjs框架

nextjs是一套成熟的同構框架(一套代碼能運行在服務端也能運行在瀏覽器)對比傳統(tǒng)的客戶端渲染的優(yōu)勢是首屏是帶數(shù)據(jù)的。其它后續(xù)操作是一樣的。理論上能比客戶端渲染看到數(shù)據(jù)能快個100-200ms具體看實際統(tǒng)計,

服務端渲染大概流程圖(圖片來源于網(wǎng)絡)

客戶端渲染大概流程圖

對比流程圖服務端渲染更加簡潔。

使用

環(huán)境

Node.js >= 18.17 nextjs13

安裝

npx create-next-app@13

選擇 src/ 目錄 和 使用 App Router

大致目錄結構

...
package.json
public
node_modules
src
|- app
  |- page.tsx
  |- layout.tsx
  |- blog
    |- page.tsx
    |- layout.tsx
  |- docs
    |- page.tsx
    |- layout.tsx
| -services
| -utils
...

路由

大致路由為

注意這是約定路由 需要用page.tsx layout.tsx文件命名

內置API

head標簽  import Head from 'next/head'

圖片標簽 import Image from 'next/image'

跳轉標簽 import Link from 'next/link'

script
import Script from 'next/script'

路由相關
import { useRouter, useSearchParams, useParams, redirect } from 'next/navigation'

請求頭 import { headers } from 'next/headers'

服務器組件和客戶端組件

服務器組件需要運行在服務器
主要特點有請求數(shù)據(jù),服務端環(huán)境等

客戶端組件運行在瀏覽器 標識 文件第一行增加 'use client'主要特點有事件,瀏覽器環(huán)境,react hooks

比較

操作服務器組件客戶端組件
請求數(shù)據(jù)??
訪問后端資源(直接)??
在服務器上保留敏感信息(訪問令牌、API密鑰等)??
保持對服務器的大量依賴性/減少客戶端JavaScript??
添加交互性和事件偵聽器(onClick、onChange等)??
使用狀態(tài)和生命周期(useState、useReducer、useEffect等)??
瀏覽器API??
自定義hooks??
使用React Class組件??

開始填充業(yè)務代碼

修改html頁面

文件位置在/src/app/layout.tsx,可以進行標題修改等一系操作

import Head from "next/head";
export default async function RootLayout(props: any) {
  return (
 <html lang="en">
   <Head>
     <title>頁面標題</title>
   </Head>
   <body>{props.children}</body>
 </html>
  );
}

獲取數(shù)據(jù)

async function getData() {
  const res = await fetch('https://xxxxx.com/', { cache: 'no-store' })
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
  return res.json()
}
export default async function Page() {
  const data = await getData()
  return <main>{JSON.stringify(data, null, 2)}</main>
}

把瀏覽器的信息轉發(fā)到服務端
這個例子是cookie有需求可以用放其它的

import { headers } from 'next/headers'
const getData = async () => {
  const headersList = headers();
  const cookie = headersList.get('Cookie');
  const res = await fetch('https://xxx.com', {
 cache: 'no-store',
 headers: { cookie }
  });
  return res.json()
};

處理全局通訊和數(shù)據(jù)

在/src/app 目錄下增加 context.tsx/src/app/context.tsx

'use client';
import { createContext, useMemo } from 'react';
import { useImmer } from 'use-immer';
export const PropsContext = createContext({});
export function Context({ children, ...other }: any) {
  const [GlobalState, setGlobalState] = useImmer<any>({
    ...other
  });
  const providerValue = useMemo(
    () => ({ GlobalState, setGlobalState }),
    [GlobalState]
  );
  return (
    <PropsContext.Provider value={providerValue}>
      {children}
    </PropsContext.Provider>
  );
}

 /src/app/layout.tsx

import React from 'react';
import { headers } from 'next/headers'
import { Context } from './context';
const getData = async () => {
  const headersList = headers();
  const cookie = headersList.get('Cookie');
  const res = await fetch('https://xxx.com', {headers: {
      cookie
    }});
  return res.json()
};
export default async function RootLayout(props: any) {
  const useInfo = await getData();
  return (
    <html lang="en">
      <body>
        <div>header</div>
        <Context useInfo={useInfo}>{props.children}</Context>
        <div>footer</div>
      </body>
    </html>
  );
}

使用/src/app/blog/page.tsx

'use client';
import { PropsContext } from '@/app/context';
import { useContext } from 'react';
export default function A2() {
  const { GlobalState, setGlobalState } = useContext<any>(PropsContext);
  return (
    <main>
      {JSON.stringify(GlobalState, null, 2)}
      <div
        onClick={() => {
          setGlobalState((s: any) => {
            s.useInfo.name = '修改之后的名稱';
          });
        }}
      >
        修改名稱
      </div>
    </main>
  );
}

跳轉

如果沒有用戶信息需要跳轉到登錄頁

import { redirect } from 'next/navigation'
async function fetchTeam(id) {
  const res = await fetch('https://...')
  // 具體邏輯根據(jù)實際的來
  if (!res.ok) return undefined
  return res.json()
}
export default async function Profile({ params }) {
  const team = await fetchTeam(params.id)
  if (!team) {
 redirect('/login')
  }
  // ...
}

部署

如果不在根域名下需要在 next.config.js添加

路由名稱根據(jù)實際來

{
  basePath: '/router'
}

然后在流水線nginx配置路由 /router* 轉發(fā)到這個應用

如果 basePath 配置的 /router/' 對應nginx配置 /router/*

編寫 Dockerfile

由于 FROM nodejs@xx 過不了鏡像掃描 鏡像里面又沒有Node.js >= 18.17的只能使用提供最基礎的鏡像了

Dockerfile

FROM hub.xxx.com/basics/alpine:3.18.2
RUN apk add nodejs=18.18.2-r0 npm=9.6.6-r0
WORKDIR /app
ADD . .
RUN npm i
RUN npm run build
EXPOSE 3000
CMD ["sh", "-c", "NODE_ENV=$NODE_ENV npm run start"]

參考文檔

https://nextjs.org/docs

https://vercel.com/guides/react-context-state-management-nextjs

以上就是服務端渲染nextjs項目接入經(jīng)驗總結分析的詳細內容,更多關于服務端渲染nextjs項目接入的資料請關注腳本之家其它相關文章!

相關文章

  • 一文帶你掌握JavaScript異步編程的五種方式

    一文帶你掌握JavaScript異步編程的五種方式

    異步可以理解為把一個任務分成了兩段,先執(zhí)行第一段,轉而去執(zhí)行其它任務,等準備完畢后,再回過頭來執(zhí)行第二段, 本文主要來和大家聊聊JavaScript異步編程的五種方式,感興趣的可以了解下
    2025-07-07
  • es6中l(wèi)et和const的使用方法詳解

    es6中l(wèi)et和const的使用方法詳解

    這篇文章主要介紹了es6中l(wèi)et和const的使用方法,結合實例形式詳細分析了es6中l(wèi)et和const的基本功能、原理、使用方法及操作注意事項,需要的朋友可以參考下
    2020-02-02
  • Openlayers實現(xiàn)地圖全屏顯示

    Openlayers實現(xiàn)地圖全屏顯示

    這篇文章主要為大家詳細介紹了Openlayers實現(xiàn)地圖全屏顯示,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • JavaScript求一個數(shù)組中重復出現(xiàn)次數(shù)最多的元素及其下標位置示例

    JavaScript求一個數(shù)組中重復出現(xiàn)次數(shù)最多的元素及其下標位置示例

    這篇文章主要介紹了JavaScript求一個數(shù)組中重復出現(xiàn)次數(shù)最多的元素及其下標位置,涉及javascript數(shù)組元素遍歷、判斷、正則過濾、追加等相關操作技巧,需要的朋友可以參考下
    2018-07-07
  • JavaScript判斷數(shù)組是否存在key的簡單實例

    JavaScript判斷數(shù)組是否存在key的簡單實例

    下面小編就為大家?guī)硪黄狫avaScript判斷數(shù)組是否存在key的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • JavaScript 數(shù)組常見操作技巧

    JavaScript 數(shù)組常見操作技巧

    這篇文章主要給大家分享的是JavaScript 數(shù)組常見操作技巧,數(shù)組是 JavaScript 中常見數(shù)據(jù)類型之一,關于它的一些操作方法,我在這里做一下簡單記錄和總結,需要的小伙伴可以參考一下
    2022-02-02
  • JavaScript indexOf忽略大小寫

    JavaScript indexOf忽略大小寫

    javascript中indexOf函數(shù)是嚴格區(qū)分大小寫的,也就是當我們使用javascript的indexOf函數(shù)的時候, 是無法進行大小寫同時進行的。為我們的一些字符串操作造成了困難。
    2009-03-03
  • JavaScript中DOM核心操作的實戰(zhàn)指南

    JavaScript中DOM核心操作的實戰(zhàn)指南

    本文詳細介紹了JavaScript中DOM元素操作的實戰(zhàn)指南,從查找、創(chuàng)建、修改、插入、刪除、屬性操作、事件綁定及遍歷等節(jié)點等常見操作入手,對比了各種方法的優(yōu)缺點,希望對大家有所幫助
    2026-04-04
  • 跨瀏覽器開發(fā)經(jīng)驗總結(三)   警惕“IE依賴綜合癥”

    跨瀏覽器開發(fā)經(jīng)驗總結(三) 警惕“IE依賴綜合癥”

    跨瀏覽器開發(fā)經(jīng)驗總結(三) 警惕“IE依賴綜合癥”
    2010-05-05
  • JavaScript中工廠函數(shù)與構造函數(shù)示例詳解

    JavaScript中工廠函數(shù)與構造函數(shù)示例詳解

    這篇文章主要給大家介紹了關于JavaScript中工廠函數(shù)與構造函數(shù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用JavaScript具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-05-05

最新評論

镇平县| 定西市| 赤峰市| 黑河市| 陆丰市| 兴隆县| 邢台市| 沈阳市| 遵化市| 保亭| 麦盖提县| 闻喜县| 土默特右旗| 抚远县| 定襄县| 宜川县| 永丰县| 抚松县| 昭苏县| 枣阳市| 达拉特旗| 景东| 锦屏县| 沂水县| 洪洞县| 阳信县| 唐海县| 武城县| 平罗县| 嘉善县| 平南县| 河间市| 龙山县| 区。| 平遥县| 诏安县| 弋阳县| 祥云县| 中阳县| 通化县| 岱山县|