<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      2個(gè)小時(shí)1.5w字| React & Golang 全棧微服務(wù)實(shí)戰(zhàn)

      目錄

      前言

      本文分為6個(gè)小節(jié),帶你全方位入門 React & Golang 微服務(wù)全棧開發(fā)。

      1. golang
      2. kratos
      3. react
      4. next.js
      5. docker
      6. 博客案例

      每一個(gè)小節(jié)均有豐富的代碼案例,倉庫地址如下:https://github.com/BaiZe1998/go-learning

      image-20250427231439177

      Golang|AI 主題知識(shí)星球:白澤說 試運(yùn)營當(dāng)中,添加 wx:baize_talk02 咨詢,免費(fèi)加入。

      image-20250427221707115

      Golang 入門教程

      1. 下載與環(huán)境配置

      安裝 Go

      Windows 安裝

      1. 訪問 Go 官方下載頁面
      2. 下載 Windows 安裝包 (MSI)
      3. 運(yùn)行安裝程序,按照提示完成安裝
      4. 安裝完成后,打開命令提示符,輸入 go version 確認(rèn)安裝成功

      macOS 安裝

      1. 訪問 Go 官方下載頁面
      2. 下載 macOS 安裝包 (PKG)
      3. 運(yùn)行安裝程序,按照提示完成安裝
      4. 或者使用 Homebrew: brew install go
      5. 安裝完成后,打開終端,輸入 go version 確認(rèn)安裝成功

      Linux 安裝

      1. 訪問 Go 官方下載頁面

      2. 下載對(duì)應(yīng)的 Linux 壓縮包

      3. 解壓到 /usr/local

        sudo tar -C /usr/local -xzf go1.x.x.linux-amd64.tar.gz
        
      4. 添加環(huán)境變量到 ~/.profile~/.bashrc

        export PATH=$PATH:/usr/local/go/bin
        
      5. 使環(huán)境變量生效:source ~/.profilesource ~/.bashrc

      6. 驗(yàn)證安裝:go version

      理解 GOROOT 和 GOPATH

      GOROOT

      GOROOT 是 Go 語言的安裝目錄,它包含了 Go 標(biāo)準(zhǔn)庫、編譯器、工具等。安裝 Go 時(shí)會(huì)自動(dòng)設(shè)置這個(gè)環(huán)境變量。

      • 作用:告訴 Go 工具鏈在哪里可以找到 Go 的標(biāo)準(zhǔn)庫和工具

      • 默認(rèn)位置

        • Windows: C:\go
        • macOS/Linux: /usr/local/go 或 Homebrew 安裝位置
      • 查看 GOROOT

        go env GOROOT
        
      • 手動(dòng)設(shè)置(通常不需要,除非安裝在非標(biāo)準(zhǔn)位置):

        • Windows: 添加系統(tǒng)環(huán)境變量 GOROOT=C:\path\to\go
        • macOS/Linux: 在 ~/.profile~/.bashrc 中添加 export GOROOT=/path/to/go

      GOPATH

      GOPATH 是 Go 的工作目錄,用于存放 Go 代碼、包和依賴等。

      • 作用

        • 在 Go Modules 出現(xiàn)前(Go 1.11之前),所有 Go 項(xiàng)目必須位于 GOPATH 內(nèi)
        • 在 Go Modules 時(shí)代,GOPATH 主要用于存儲(chǔ)下載的依賴包和編譯后的二進(jìn)制文件
      • 默認(rèn)位置

        • Windows: %USERPROFILE%\go (例如:C:\Users\YourName\go)
        • macOS/Linux: $HOME/go (例如:/home/username/go/Users/username/go)
      • GOPATH 目錄結(jié)構(gòu)

        • src: 存放源代碼(如你的項(xiàng)目和依賴包的源碼)
        • pkg: 存放編譯后的包文件
        • bin: 存放編譯后的可執(zhí)行文件
      • 設(shè)置多個(gè) GOPATH
        可以設(shè)置多個(gè)目錄,用冒號(hào)(Unix)或分號(hào)(Windows)分隔

        # Unix/macOS
        export GOPATH=$HOME/go:$HOME/projects/go
        
        # Windows
        set GOPATH=%USERPROFILE%\go;D:\projects\go
        

      Go Modules 與 GOPATH 的關(guān)系

      從 Go 1.11 開始,Go 引入了 Go Modules 作為官方的依賴管理解決方案,逐漸弱化了 GOPATH 的作用:

      • Go Modules 模式下

        • 項(xiàng)目可以位于任何目錄,不必在 GOPATH 內(nèi)
        • 依賴通過 go.mod 文件管理,而不是通過 GOPATH 目錄結(jié)構(gòu)
        • 下載的依賴緩存在 $GOPATH/pkg/mod 目錄
        • 編譯的命令仍安裝到 $GOPATH/bin
      • 環(huán)境變量 GO111MODULE

        • GO111MODULE=off: 禁用模塊支持,使用 GOPATH 模式
        • GO111MODULE=on: 啟用模塊支持,忽略 GOPATH
        • GO111MODULE=auto: 在 GOPATH 內(nèi)禁用模塊支持,在 GOPATH 外啟用模塊支持

      查看和設(shè)置 Go 環(huán)境變量

      # 查看所有 Go 環(huán)境變量
      go env
      
      # 查看特定環(huán)境變量
      go env GOPATH
      go env GOROOT
      
      # 設(shè)置環(huán)境變量(Go 1.14+)
      go env -w GOPATH=/custom/path
      

      配置 GOPATH

      GOPATH 是工作目錄,用于存放 Go 代碼、包和依賴等:

      1. 創(chuàng)建 GOPATH 目錄,例如:mkdir -p $HOME/go
      2. 設(shè)置環(huán)境變量:
        • Windows: 添加 GOPATH 系統(tǒng)環(huán)境變量,值為你創(chuàng)建的目錄路徑
        • macOS/Linux: 在 ~/.profile~/.bashrc 中添加 export GOPATH=$HOME/go
      3. GOPATH 目錄結(jié)構(gòu):
        • src: 源代碼
        • pkg: 包文件
        • bin: 可執(zhí)行文件

      2. 語法與包管理

      Go 基礎(chǔ)語法

      查看 hello.go 文件了解 Go 的基本語法,包括:

      • 包聲明與導(dǎo)入
      • 變量聲明與使用
      • 基本數(shù)據(jù)類型
      • 控制流(條件語句、循環(huán))
      • 函數(shù)定義與調(diào)用
      • 切片與數(shù)組操作

      運(yùn)行 Go 程序

      go run hello.go
      

      構(gòu)建 Go 程序

      go build hello.go
      ./hello  # 運(yùn)行編譯后的可執(zhí)行文件
      

      包管理 (Go Modules)

      從 Go 1.11 開始,Go 引入了 Go Modules 作為官方的依賴管理解決方案:

      1. 初始化一個(gè)新模塊:

        go mod init example.com/myproject
        
      2. 添加依賴:

        go get github.com/some/dependency
        
      3. 整理和更新依賴:

        go mod tidy
        
      4. 查看所有依賴:

        go list -m all
        

      常用標(biāo)準(zhǔn)庫

      • fmt: 格式化輸入輸出
      • io: 基本 I/O 接口
      • os: 操作系統(tǒng)功能
      • net/http: HTTP 客戶端和服務(wù)器
      • encoding/json: JSON 編解碼
      • time: 時(shí)間相關(guān)功能
      • sync: 同步原語

      推薦學(xué)習(xí)資源

      擴(kuò)展練習(xí)

      1. 修改 hello.go 添加更多功能
      2. 創(chuàng)建一個(gè)簡單的 HTTP 服務(wù)器
      3. 實(shí)現(xiàn)文件讀寫操作
      4. 使用 Go 實(shí)現(xiàn)一個(gè)簡單的 CLI 工具

      Kratos 微服務(wù)框架入門

      Kratos 是一個(gè)輕量級(jí)的、模塊化的、可插拔的Go微服務(wù)框架,專注于幫助開發(fā)人員快速構(gòu)建微服務(wù)。本教程將帶你深入了解 Kratos 的核心概念和使用方法。

      1. Kratos 核心介紹

      Kratos 是嗶哩嗶哩開源的一款Go微服務(wù)框架,具有以下核心特點(diǎn):

      1.1 核心理念

      • 簡潔:提供了簡潔、統(tǒng)一的接口定義和使用方式
      • 模塊化:各個(gè)組件可獨(dú)立使用,也可組合使用
      • 可擴(kuò)展:支持各類中間件和插件的擴(kuò)展
      • 高性能:追求極致的性能優(yōu)化

      1.2 主要特性

      • 傳輸層:支持 HTTP 和 gRPC 服務(wù),并提供統(tǒng)一抽象
      • 中間件:豐富的內(nèi)置中間件,如日志、指標(biāo)、跟蹤、限流等
      • 注冊(cè)發(fā)現(xiàn):支持多種服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制
      • 配置管理:靈活的配置加載和動(dòng)態(tài)配置
      • 錯(cuò)誤處理:統(tǒng)一的錯(cuò)誤處理和錯(cuò)誤碼管理
      • API定義:使用 Protocol Buffers 作為 API 定義語言
      • 依賴注入:使用 Wire 進(jìn)行依賴管理和注入

      1.3 設(shè)計(jì)架構(gòu)

      Kratos 采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì) (DDD) 的六邊形架構(gòu),將應(yīng)用分為以下層次:

      • API層:定義服務(wù)接口,通常使用Proto文件
      • Service層:處理服務(wù)業(yè)務(wù)邏輯的實(shí)現(xiàn)
      • Biz層:核心業(yè)務(wù)邏輯和領(lǐng)域模型
      • Data層:數(shù)據(jù)訪問層,負(fù)責(zé)與持久化存儲(chǔ)交互
      • Server層:傳輸層,提供HTTP/gRPC服務(wù)

      2. 項(xiàng)目初始化方法

      Kratos 提供了完善的項(xiàng)目初始化流程,幫助開發(fā)者快速創(chuàng)建項(xiàng)目骨架。

      2.1 安裝 Kratos 命令行工具

      # 安裝最新版本的 Kratos 命令行工具
      go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
      

      2.2 創(chuàng)建新項(xiàng)目

      # 創(chuàng)建名為 myproject 的新項(xiàng)目
      kratos new myproject
      
      # 進(jìn)入項(xiàng)目目錄
      cd myproject
      

      2.3 添加 API 定義

      # 創(chuàng)建 API 文件
      kratos proto add api/myproject/v1/myproject.proto
      

      2.4 生成 API 代碼

      在編寫完 proto 文件后,使用 kratos 命令生成相應(yīng)代碼:

      # 生成客戶端代碼
      kratos proto client api/myproject/v1/myproject.proto
      
      # 生成服務(wù)端代碼
      kratos proto server api/myproject/v1/myproject.proto -t internal/service
      

      3. CLI 工具詳解

      Kratos CLI 是 Kratos 框架的命令行工具,提供了豐富的功能幫助開發(fā)者提高效率。

      3.1 主要命令

      命令 說明 用法示例
      new 創(chuàng)建新項(xiàng)目 kratos new myproject
      proto 管理 Proto 文件與代碼生成 kratos proto add/client/server
      run 運(yùn)行項(xiàng)目 kratos run
      build 構(gòu)建項(xiàng)目 kratos build
      upgrade 更新 Kratos 工具 kratos upgrade

      3.2 Proto 相關(guān)命令

      # 添加新的 proto 文件
      kratos proto add api/helloworld/v1/greeter.proto
      
      # 生成 client 代碼
      kratos proto client api/helloworld/v1/greeter.proto
      
      # 生成 server 代碼
      kratos proto server api/helloworld/v1/greeter.proto -t internal/service
      
      # 生成所有代碼
      kratos proto all api/helloworld/v1/greeter.proto -t internal/service
      

      3.3 工具依賴

      使用 Kratos 相關(guān)功能需要安裝以下組件:

      # 安裝 protoc 編譯器依賴
      go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
      go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
      go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
      go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2@latest
      

      4. 依賴注入

      Kratos 使用 Wire 框架進(jìn)行依賴注入,實(shí)現(xiàn)了組件的松耦合和代碼的可測(cè)試性。

      4.1 Wire 基礎(chǔ)

      Wire 是 Google 開發(fā)的編譯時(shí)依賴注入工具,通過代碼生成而非反射實(shí)現(xiàn)依賴注入。

      4.2 Provider 定義

      在 Kratos 中,各個(gè)組件通過 Provider 函數(shù)提供實(shí)例:

      // data層 provider
      func NewData(conf *conf.Data, logger log.Logger) (*Data, func(), error) {
          // 實(shí)例化數(shù)據(jù)層
          cleanup := func() {
              // 清理資源
          }
          return &Data{}, cleanup, nil
      }
      
      // biz層 provider
      func NewGreeterUsecase(repo GreeterRepo, logger log.Logger) *GreeterUsecase {
          return &GreeterUsecase{repo: repo}
      }
      
      // service層 provider
      func NewGreeterService(uc *biz.GreeterUsecase, logger log.Logger) *GreeterService {
          return &GreeterService{uc: uc}
      }
      

      4.3 Wire 注入點(diǎn)

      cmd/server/wire.go 中定義依賴注入:

      // ProviderSet 是各層的依賴集合
      var ProviderSet = wire.NewSet(
          data.ProviderSet,
          biz.ProviderSet,
          service.ProviderSet,
          server.ProviderSet,
      )
      
      // 應(yīng)用實(shí)例化函數(shù)
      func initApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, error) {
          panic(wire.Build(ProviderSet, newApp))
      }
      

      4.4 生成注入代碼

      # 生成依賴注入代碼
      cd cmd/server
      wire
      

      5. 項(xiàng)目結(jié)構(gòu)詳解

      Kratos 項(xiàng)目結(jié)構(gòu)遵循 DDD 六邊形架構(gòu),組織清晰。

      5.1 標(biāo)準(zhǔn)目錄結(jié)構(gòu)

      ├── api                    # API 定義目錄 (protobuf)
      │   └── helloworld
      │       └── v1
      │           └── greeter.proto
      ├── cmd                    # 應(yīng)用程序入口
      │   └── server
      │       ├── main.go
      │       ├── wire.go        # 依賴注入
      │       └── wire_gen.go    # 自動(dòng)生成的依賴注入代碼
      ├── configs                # 配置文件目錄
      │   └── config.yaml
      ├── internal               # 私有應(yīng)用代碼
      │   ├── biz                # 業(yè)務(wù)邏輯層 (領(lǐng)域模型)
      │   │   ├── biz.go
      │   │   └── greeter.go
      │   ├── conf               # 配置處理代碼
      │   │   ├── conf.proto
      │   │   └── conf.pb.go
      │   ├── data               # 數(shù)據(jù)訪問層 (持久化)
      │   │   ├── data.go
      │   │   └── greeter.go
      │   ├── server             # 傳輸層(HTTP/gRPC)
      │   │   ├── server.go
      │   │   ├── http.go
      │   │   └── grpc.go
      │   └── service            # 服務(wù)實(shí)現(xiàn)層
      │       └── greeter.go
      ├── third_party            # 第三方 proto 文件
      └── go.mod
      

      5.2 各目錄職責(zé)

      1. api: 定義服務(wù) API 接口,使用 Protocol Buffers
      2. cmd: 程序入口,包含 main 函數(shù)和依賴注入
      3. configs: 配置文件
      4. internal: 私有代碼,不對(duì)外暴露
        • biz: 核心業(yè)務(wù)邏輯,包含領(lǐng)域模型和業(yè)務(wù)規(guī)則
        • data: 數(shù)據(jù)訪問層,實(shí)現(xiàn)數(shù)據(jù)庫操作和緩存
        • server: 服務(wù)器定義,包括 HTTP 和 gRPC 服務(wù)器配置
        • service: 服務(wù)實(shí)現(xiàn),連接 API 和業(yè)務(wù)邏輯
      5. third_party: 第三方依賴的 proto 文件

      6. 項(xiàng)目運(yùn)行鏈路分析

      Kratos 應(yīng)用從啟動(dòng)到處理請(qǐng)求的完整流程。

      6.1 啟動(dòng)流程

      1. 初始化配置:加載 configs 目錄的配置文件
      2. 依賴注入:通過 Wire 構(gòu)建應(yīng)用依賴關(guān)系
      3. 創(chuàng)建服務(wù)器:初始化 HTTP/gRPC 服務(wù)器
      4. 注冊(cè)服務(wù):注冊(cè) API 實(shí)現(xiàn)
      5. 啟動(dòng)服務(wù):啟動(dòng)服務(wù)監(jiān)聽
      // main.go 中的啟動(dòng)流程
      func main() {
          // 1. 初始化 logger
          logger := log.NewStdLogger(os.Stdout)
          
          // 2. 加載配置
          c := config.New(config.WithSource(file.NewSource(flagconf)))
          if err := c.Load(); err != nil {
              panic(err)
          }
          
          // 3. 通過依賴注入創(chuàng)建 app 實(shí)例
          app, cleanup, err := wireApp(c, logger)
          if err != nil {
              panic(err)
          }
          defer cleanup()
          
          // 4. 啟動(dòng)應(yīng)用
          if err := app.Run(); err != nil {
              panic(err)
          }
      }
      

      6.2 請(qǐng)求處理流程

      HTTP 請(qǐng)求從接收到響應(yīng)的完整流程:

      1. 接收請(qǐng)求:HTTP/gRPC 服務(wù)器接收請(qǐng)求
      2. 中間件處理:請(qǐng)求經(jīng)過中間件鏈(日志、跟蹤、限流等)
      3. 路由匹配:根據(jù)路徑匹配對(duì)應(yīng)處理器
      4. 參數(shù)解析:解析和驗(yàn)證請(qǐng)求參數(shù)
      5. 服務(wù)層處理:Service 層實(shí)現(xiàn)請(qǐng)求處理
      6. 業(yè)務(wù)邏輯:調(diào)用 Biz 層的領(lǐng)域邏輯
      7. 數(shù)據(jù)訪問:通過 Data 層訪問數(shù)據(jù)庫或緩存
      8. 響應(yīng)構(gòu)建:構(gòu)建響應(yīng)數(shù)據(jù)
      9. 中間件后處理:響應(yīng)經(jīng)過中間件鏈
      10. 返回響應(yīng):返回給客戶端

      6.3 HTTP服務(wù)示例

      以下是一個(gè)簡化的 HTTP 服務(wù)示例:

      import (
          "github.com/go-kratos/kratos/v2"
          "github.com/go-kratos/kratos/v2/log"
          "github.com/go-kratos/kratos/v2/middleware/recovery"
          "github.com/go-kratos/kratos/v2/transport/http"
      )
      
      func main() {
          // 初始化 logger
          logger := log.NewStdLogger(os.Stdout)
          
          // 創(chuàng)建 HTTP 服務(wù)器
          httpSrv := http.NewServer(
              http.Address(":8000"),
              http.Middleware(
                  recovery.Recovery(), // 異常恢復(fù)中間件
              ),
          )
          
          // 注冊(cè)路由
          r := httpSrv.Route("/")
          r.GET("/hello", func(ctx http.Context) error {
              return ctx.String(200, "Hello Kratos!")
          })
          
          // 創(chuàng)建 Kratos 應(yīng)用
          app := kratos.New(
              kratos.Name("example"),
              kratos.Server(httpSrv),
              kratos.Logger(logger),
          )
          
          // 啟動(dòng)應(yīng)用
          if err := app.Run(); err != nil {
              log.Error(err)
          }
      }
      

      6.4 完整服務(wù)架構(gòu)

      在實(shí)際項(xiàng)目中,請(qǐng)求處理鏈路涉及多個(gè)組件和層次:

      客戶端 → 負(fù)載均衡 → HTTP/gRPC服務(wù)器 → 中間件鏈 → 路由 → Service層 → Biz層 → Data層 → 數(shù)據(jù)庫/緩存
                   ↑                                                             ↓
      服務(wù)注冊(cè)/發(fā)現(xiàn) ← ←  ←  ←  ←  ←  ←  ←  ←  ←  ←  ←  ←  ← 響應(yīng)  ←  ←  ←  ←  ← ←
      

      擴(kuò)展閱讀與資源

      React 入門教程

      React 是由 Facebook 開發(fā)的一個(gè)用于構(gòu)建用戶界面的 JavaScript 庫。React 使開發(fā)人員能夠構(gòu)建快速、可擴(kuò)展的 Web 應(yīng)用程序。

      1. 下載與環(huán)境配置

      要開始使用 React,您需要一個(gè)現(xiàn)代的 JavaScript 環(huán)境和 Node.js 開發(fā)環(huán)境。

      安裝 Node.js 和 pnpm

      首先,安裝 Node.js(包含 npm):

      • Windows/macOS: 從 Node.js 官網(wǎng) 下載并安裝
      • macOS (使用 Homebrew): brew install node
      • Linux: sudo apt install nodejs npmsudo yum install nodejs npm

      驗(yàn)證安裝:

      node -v
      

      然后安裝 pnpm (性能更好的包管理器):

      # 使用npm安裝pnpm
      npm install -g pnpm
      
      # 驗(yàn)證pnpm安裝
      pnpm --version
      

      創(chuàng)建新的 React 應(yīng)用

      使用 Create React App 工具創(chuàng)建新的 React 應(yīng)用:

      # 創(chuàng)建新項(xiàng)目
      pnpm create react-app my-react-app
      
      # 進(jìn)入項(xiàng)目目錄
      cd my-react-app
      
      # 啟動(dòng)開發(fā)服務(wù)器
      pnpm start
      

      或者使用 Vite 創(chuàng)建(更快的啟動(dòng)速度,推薦):

      # 使用 Vite 創(chuàng)建 React 項(xiàng)目
      pnpm create vite my-react-app --template react
      
      # 進(jìn)入項(xiàng)目目錄
      cd my-react-app
      
      # 安裝依賴
      pnpm install
      
      # 啟動(dòng)開發(fā)服務(wù)器
      pnpm dev
      

      2. React 基本語法與包管理

      基本概念

      1. 組件 (Components):React 應(yīng)用由組件構(gòu)成

        • 函數(shù)組件(推薦)
        • 類組件
      2. JSX:JavaScript 的語法擴(kuò)展,允許在 JS 中編寫類似 HTML 的代碼

      3. Props:向組件傳遞數(shù)據(jù)的方式

      4. State:組件的內(nèi)部狀態(tài)

      5. Hooks:在函數(shù)組件中使用狀態(tài)和其他 React 特性的 API

      函數(shù)組件示例

      import React from 'react';
      
      function Greeting(props) {
        return <h1>你好,{props.name}!</h1>;
      }
      
      export default Greeting;
      

      使用 State Hook

      import React, { useState } from 'react';
      
      function Counter() {
        const [count, setCount] = useState(0);
      
        return (
          <div>
            <p>你點(diǎn)擊了 {count} 次</p>
            <button onClick={() => setCount(count + 1)}>
              點(diǎn)擊我
            </button>
          </div>
        );
      }
      

      使用 Effect Hook

      import React, { useState, useEffect } from 'react';
      
      function Timer() {
        const [seconds, setSeconds] = useState(0);
      
        useEffect(() => {
          const interval = setInterval(() => {
            setSeconds(seconds => seconds + 1);
          }, 1000);
          
          return () => clearInterval(interval);
        }, []);
      
        return <div>計(jì)時(shí)器:{seconds} 秒</div>;
      }
      

      包管理與依賴

      React 項(xiàng)目使用 pnpm 管理依賴(pnpm比npm和yarn更快、更高效):

      # 安裝依賴
      pnpm add react-router-dom
      
      # 安裝開發(fā)依賴
      pnpm add -D typescript @types/react
      
      # 更新所有依賴
      pnpm update
      
      # 運(yùn)行腳本
      pnpm run dev
      

      pnpm的主要優(yōu)勢(shì):

      • 磁盤空間高效:pnpm使用內(nèi)容尋址存儲(chǔ)來避免重復(fù)安裝
      • 快速安裝:比npm和yarn快2-3倍
      • 嚴(yán)格的依賴管理:更好的避免依賴地獄問題
      • 支持monorepo:內(nèi)置對(duì)工作空間的支持

      常用的包:

      • react-router-dom: 路由管理
      • axios: HTTP 請(qǐng)求
      • zustandredux-toolkit: 狀態(tài)管理
      • styled-componentsemotion: CSS-in-JS 解決方案
      • MUIAnt Design: UI 組件庫

      本目錄代碼示例說明

      本目錄包含兩個(gè)主要文件:

      1. App.jsx: 包含三個(gè)示例組件

        • 計(jì)數(shù)器:展示基本的狀態(tài)管理
        • 計(jì)時(shí)器:展示 useEffect 的使用
        • 待辦事項(xiàng)列表:展示更復(fù)雜的狀態(tài)管理
      2. App.css: 為組件提供樣式

      如何運(yùn)行示例代碼

      要運(yùn)行本示例,需要將這些文件集成到一個(gè) React 項(xiàng)目中:

      1. 創(chuàng)建新的 React 應(yīng)用:

        pnpm create vite react-demo --template react
        cd react-demo
        pnpm install
        
      2. 替換 src/App.jsxsrc/App.css 為本目錄中的文件

      3. 啟動(dòng)應(yīng)用:

        pnpm dev
        

      pnpm 常用命令參考

      # 初始化新項(xiàng)目
      pnpm init
      
      # 安裝依賴
      pnpm add [package]
      
      # 安裝開發(fā)依賴
      pnpm add -D [package]
      
      # 全局安裝
      pnpm add -g [package]
      
      # 運(yùn)行腳本
      pnpm [script]
      
      # 移除依賴
      pnpm remove [package]
      
      # 更新依賴
      pnpm update
      
      # 查看過時(shí)依賴
      pnpm outdated
      

      學(xué)習(xí)資源

      練習(xí)建議

      1. 修改計(jì)數(shù)器組件,添加最大值和最小值限制
      2. 為待辦事項(xiàng)添加優(yōu)先級(jí)功能
      3. 添加一個(gè)新的表單組件,練習(xí)表單處理
      4. 嘗試使用 Context API 在組件之間共享狀態(tài)

      Next.js 入門教程

      Next.js 是一個(gè)基于 React 的輕量級(jí)框架,用于構(gòu)建靜態(tài)和服務(wù)器渲染的應(yīng)用程序。它提供了豐富的功能,如服務(wù)器端渲染、靜態(tài)網(wǎng)站生成、API 路由、自動(dòng)代碼分割等。本教程基于 Next.js 13+ 的 App Router。

      1. 項(xiàng)目目錄與優(yōu)雅實(shí)踐

      Next.js 項(xiàng)目結(jié)構(gòu) (App Router)

      一個(gè)典型的 Next.js 項(xiàng)目結(jié)構(gòu)如下:

      my-nextjs-app/
      │
      ├── app/               # App Router 目錄(基于文件約定的路由)
      │   ├── layout.tsx     # 根布局組件
      │   ├── page.tsx       # 首頁 (/)
      │   ├── about/         # 關(guān)于頁面路由
      │   │   └── page.tsx   # 關(guān)于頁面 (/about)
      │   ├── blogs/         # 博客路由
      │   │   ├── [id]/      # 動(dòng)態(tài)路由
      │   │   │   └── page.tsx # 博客文章頁面 
      │   │   ├── new/       # 創(chuàng)建新博客
      │   │   │   └── page.tsx # 創(chuàng)建博客頁面
      │   │   └── page.tsx   # 博客列表頁面 
      │   ├── api/           # API 路由
      │   │   └── route.ts   # API 處理器 
      │   ├── globals.css    # 全局樣式
      │   └── error.tsx      # 錯(cuò)誤處理頁面
      │
      ├── components/        # React 組件
      │   ├── ui/            # UI 組件
      │   └── ClientComponent.tsx # 客戶端組件示例
      │
      ├── lib/               # 工具函數(shù)和庫
      │   └── utils.ts
      │
      ├── public/            # 靜態(tài)資源
      │   ├── favicon.ico    
      │   └── images/
      │
      ├── .next/             # Next.js 構(gòu)建輸出 (git ignored)
      ├── node_modules/      # 依賴 (git ignored)
      ├── package.json       # 項(xiàng)目依賴和腳本
      ├── pnpm-lock.yaml     # pnpm 鎖文件
      ├── next.config.js     # Next.js 配置
      ├── tsconfig.json      # TypeScript 配置
      └── README.md          # 項(xiàng)目說明
      

      Next.js App Router 優(yōu)雅實(shí)踐

      1. 文件系統(tǒng)路由約定

        • app/page.tsx/ (首頁)
        • app/about/page.tsx/about (關(guān)于頁面)
        • app/blogs/[id]/page.tsx/blogs/:id (動(dòng)態(tài)路由)
        • 特殊文件:
          • layout.tsx: 布局組件
          • loading.tsx: 加載狀態(tài)
          • error.tsx: 錯(cuò)誤處理
          • not-found.tsx: 404頁面
      2. 數(shù)據(jù)獲取方法

        • React Server Components 中的直接獲取
        • generateStaticParams: 靜態(tài)路徑生成
        • revalidatePath/revalidateTag: 按需重新驗(yàn)證
        • 客戶端數(shù)據(jù)獲取: SWR 或 React Query
      3. API 路由

        • app/api/*/route.ts 文件定義 API 端點(diǎn)
        • 使用 NextResponse 進(jìn)行響應(yīng)處理
      4. 布局系統(tǒng)

        • 嵌套布局
        • 平行路由和攔截路由
        • 模板和分組
      5. 渲染策略

        • 服務(wù)器組件(默認(rèn))
        • 客戶端組件 ('use client')
        • 流式渲染和部分渲染

      2. 快速啟動(dòng)案例前端

      安裝 Node.js 和 pnpm

      首先,確保你已安裝 Node.js 和 pnpm:

      # 安裝 pnpm (如果尚未安裝)
      npm install -g pnpm
      
      # 驗(yàn)證安裝
      pnpm --version
      

      創(chuàng)建 Next.js 項(xiàng)目

      使用 pnpm 創(chuàng)建新的 Next.js 項(xiàng)目:

      # 使用 create-next-app 創(chuàng)建TypeScript項(xiàng)目
      pnpm create next-app my-nextjs-app --typescript
      
      # 進(jìn)入項(xiàng)目目錄
      cd my-nextjs-app
      

      在創(chuàng)建項(xiàng)目過程中,會(huì)提示你選擇一些選項(xiàng)。請(qǐng)確保選擇 "Yes" 當(dāng)詢問是否使用 App Router 時(shí)。

      項(xiàng)目結(jié)構(gòu)設(shè)置

      默認(rèn)情況下,create-next-app 生成的項(xiàng)目已經(jīng)包含基本結(jié)構(gòu)。您可以根據(jù)需要添加額外的目錄。

      創(chuàng)建首頁

      首頁是訪問者首先看到的頁面,在 app/page.tsx 文件中創(chuàng)建:

      // app/page.tsx
      import Link from 'next/link';
      
      export default function Home() {
        return (
          <div className="container mx-auto px-4 py-8">
            <section className="py-12 text-center">
              <h1 className="text-4xl font-bold mb-4">歡迎來到我的博客</h1>
              <p className="text-lg text-gray-600 mb-8">探索技術(shù)、設(shè)計(jì)和創(chuàng)意的世界</p>
              <Link 
                href="/blog" 
                className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
              >
                瀏覽博客文章
              </Link>
            </section>
            
            <section className="py-8">
              <h2 className="text-2xl font-bold mb-6 text-center">最新文章</h2>
              <div className="grid md:grid-cols-3 gap-6">
                <div className="border rounded-lg p-6 hover:shadow-md transition-shadow">
                  <h3 className="text-xl font-semibold mb-3">Next.js入門指南</h3>
                  <p className="text-gray-600 mb-4">了解如何使用Next.js構(gòu)建現(xiàn)代Web應(yīng)用</p>
                  <Link href="/blog/1" className="text-blue-600 hover:underline">
                    閱讀更多 &rarr;
                  </Link>
                </div>
                <div className="border rounded-lg p-6 hover:shadow-md transition-shadow">
                  <h3 className="text-xl font-semibold mb-3">React服務(wù)器組件詳解</h3>
                  <p className="text-gray-600 mb-4">深入理解React服務(wù)器組件的工作原理</p>
                  <Link href="/blog/2" className="text-blue-600 hover:underline">
                    閱讀更多 &rarr;
                  </Link>
                </div>
                <div className="border rounded-lg p-6 hover:shadow-md transition-shadow">
                  <h3 className="text-xl font-semibold mb-3">TypeScript與Next.js</h3>
                  <p className="text-gray-600 mb-4">如何在Next.js項(xiàng)目中充分利用TypeScript</p>
                  <Link href="/blog/3" className="text-blue-600 hover:underline">
                    閱讀更多 &rarr;
                  </Link>
                </div>
              </div>
            </section>
            
            <section className="py-8">
              <h2 className="text-2xl font-bold mb-6 text-center">關(guān)于客戶端組件</h2>
              <div className="border rounded-lg p-6">
                <p className="text-gray-700 mb-4">
                  Next.js的App Router架構(gòu)區(qū)分<strong>服務(wù)器組件</strong>和<strong>客戶端組件</strong>。
                  默認(rèn)情況下,所有組件都是服務(wù)器組件,在服務(wù)器上渲染并發(fā)送到客戶端。
                </p>
                <p className="text-gray-700 mb-4">
                  當(dāng)需要使用瀏覽器API、添加交互性或使用React hooks時(shí),應(yīng)該使用客戶端組件。
                  通過在文件頂部添加 <code className="bg-gray-100 px-2 py-1 rounded">'use client'</code> 指令來聲明客戶端組件。
                </p>
                <div className="bg-gray-50 p-4 rounded-lg">
                  <h3 className="font-semibold mb-2">客戶端組件示例:</h3>
                  <pre className="bg-gray-800 text-white p-4 rounded overflow-x-auto">
                    <code>{`'use client'
      
      import { useState, useEffect } from 'react'
      
      export default function ClientComponent() {
        const [count, setCount] = useState(0)
        
        return (
          <div>
            <h3>計(jì)數(shù)器: {count}</h3>
            <button onClick={() => setCount(count + 1)}>
              增加
            </button>
          </div>
        )
      }`}</code>
                  </pre>
                </div>
              </div>
            </section>
      
            <section className="py-8">
              <h2 className="text-2xl font-bold mb-6 text-center">功能演示</h2>
              <div className="grid md:grid-cols-2 gap-6">
                <div className="border rounded-lg p-6 hover:shadow-md transition-shadow">
                  <h3 className="text-xl font-semibold mb-3">博客列表</h3>
                  <p className="text-gray-600 mb-4">查看使用服務(wù)器組件和模擬數(shù)據(jù)實(shí)現(xiàn)的博客列表頁面</p>
                  <Link href="/blog" className="text-blue-600 hover:underline">
                    查看示例 &rarr;
                  </Link>
                </div>
                <div className="border rounded-lg p-6 hover:shadow-md transition-shadow">
                  <h3 className="text-xl font-semibold mb-3">客戶端組件</h3>
                  <p className="text-gray-600 mb-4">了解如何在Next.js中使用客戶端組件實(shí)現(xiàn)交互功能</p>
                  <Link href="/client-example" className="text-blue-600 hover:underline">
                    查看示例 &rarr;
                  </Link>
                </div>
              </div>
            </section>
          </div>
        );
      }
      

      首頁包含了以下元素:

      • 歡迎區(qū)域,包含標(biāo)題和指向博客列表的鏈接
      • 最新文章區(qū)域,展示最近的博客文章

      創(chuàng)建頁面

      app 目錄中創(chuàng)建 page.tsx 文件以添加新頁面:

      // app/about/page.tsx
      export default function AboutPage() {
        return (
          <div>
            <h1>關(guān)于我們</h1>
            <p>這是 Next.js 示例項(xiàng)目的關(guān)于頁面。</p>
          </div>
        )
      }
      

      創(chuàng)建布局

      使用 layout.tsx 文件創(chuàng)建布局:

      // app/layout.tsx
      import type { ReactNode } from 'react';
      
      interface RootLayoutProps {
        children: ReactNode;
      }
      
      export default function RootLayout({ children }: RootLayoutProps) {
        return (
          <html lang="zh">
            <body>
              <header>
                <nav>
                  {/* 導(dǎo)航欄組件 */}
                </nav>
              </header>
              <main>{children}</main>
              <footer>? {new Date().getFullYear()} 我的 Next.js 應(yīng)用</footer>
            </body>
          </html>
        )
      }
      

      創(chuàng)建動(dòng)態(tài)路由

      使用方括號(hào)語法創(chuàng)建動(dòng)態(tài)路由:

      // app/blogs/[id]/page.tsx
      import { notFound } from 'next/navigation';
      import Link from 'next/link';
      
      // 模擬博客數(shù)據(jù)
      const blogPosts = [
        { 
          id: '1', 
          title: 'Next.js入門指南',
          content: `
            <p>Next.js是一個(gè)基于React的強(qiáng)大框架,它提供了許多內(nèi)置功能,使得構(gòu)建現(xiàn)代Web應(yīng)用變得更加簡單。</p>
            <h2>主要特性</h2>
            <ul>
              <li>服務(wù)器端渲染 (SSR)</li>
              <li>靜態(tài)站點(diǎn)生成 (SSG)</li>
              <li>API路由</li>
              <li>文件系統(tǒng)路由</li>
              <li>內(nèi)置CSS和Sass支持</li>
              <li>代碼分割和打包優(yōu)化</li>
            </ul>
            <p>使用Next.js,你可以快速開發(fā)出高性能的React應(yīng)用,無需復(fù)雜的配置。</p>
          `,
          author: {
            name: '張三',
            avatar: 'https://randomuser.me/api/portraits/men/1.jpg'
          },
          publishedAt: '2023-05-15',
          tags: ['Next.js', 'React', '前端開發(fā)']
        },
        { 
          id: '2', 
          title: 'React服務(wù)器組件詳解',
          content: `
            <p>React服務(wù)器組件是React的一項(xiàng)新特性,它允許開發(fā)者創(chuàng)建在服務(wù)器上渲染的組件,從而提高性能并減少客戶端JavaScript的體積。</p>
            <h2>服務(wù)器組件的優(yōu)勢(shì)</h2>
            <ol>
              <li>減少客戶端JavaScript包大小</li>
              <li>直接訪問服務(wù)器資源(數(shù)據(jù)庫、文件系統(tǒng)等)</li>
              <li>自動(dòng)代碼分割</li>
              <li>改善首次加載性能</li>
            </ol>
            <p>在Next.js的App Router中,所有組件默認(rèn)都是服務(wù)器組件,除非你顯式聲明為客戶端組件。</p>
          `,
          author: {
            name: '李四',
            avatar: 'https://randomuser.me/api/portraits/women/2.jpg'
          },
          publishedAt: '2023-06-22',
          tags: ['React', '服務(wù)器組件', '性能優(yōu)化']
        },
        { 
          id: '3', 
          title: 'TypeScript與Next.js',
          content: `
            <p>TypeScript是JavaScript的超集,添加了靜態(tài)類型檢查,在Next.js項(xiàng)目中使用TypeScript可以帶來諸多好處。</p>
            <h2>TypeScript的優(yōu)勢(shì)</h2>
            <ul>
              <li>靜態(tài)類型檢查,減少運(yùn)行時(shí)錯(cuò)誤</li>
              <li>更好的IDE支持,包括代碼補(bǔ)全和智能提示</li>
              <li>更容易維護(hù)的代碼庫</li>
              <li>自文檔化的代碼</li>
            </ul>
            <h2>在Next.js中使用TypeScript</h2>
            <p>Next.js原生支持TypeScript,你可以直接創(chuàng)建.tsx或.ts文件,無需額外配置。</p>
            <p>對(duì)于頁面和API路由,你可以使用TypeScript接口來定義props和請(qǐng)求參數(shù)的類型。</p>
          `,
          author: {
            name: '王五',
            avatar: 'https://randomuser.me/api/portraits/men/3.jpg'
          },
          publishedAt: '2023-07-10',
          tags: ['TypeScript', 'Next.js', '類型安全']
        }
      ];
      
      // 獲取博客帖子函數(shù)
      const getBlogPost = (id: string) => {
        return blogPosts.find(post => post.id === id);
      };
      
      // 博客詳情頁面組件
      export default function BlogPostPage({ params }: { params: { id: string } }) {
        const post = getBlogPost(params.id);
        
        // 如果沒有找到文章,返回404
        if (!post) {
          notFound();
        }
        
        return (
          <div className="container mx-auto px-4 py-8">
            <article className="max-w-3xl mx-auto">
              <div className="mb-8">
                <Link href="/blog" className="text-blue-600 hover:underline mb-4 inline-block">
                  &larr; 返回博客列表
                </Link>
                <h1 className="text-4xl font-bold mb-4">{post.title}</h1>
                
                <div className="flex items-center mb-6">
                  <img 
                    src={post.author.avatar} 
                    alt={post.author.name}
                    className="w-10 h-10 rounded-full mr-3"
                  />
                  <div>
                    <p className="font-medium">{post.author.name}</p>
                    <p className="text-gray-500 text-sm">發(fā)布于 {post.publishedAt}</p>
                  </div>
                </div>
                
                <div className="flex flex-wrap gap-2 mb-8">
                  {post.tags.map(tag => (
                    <span key={tag} className="bg-blue-100 text-blue-800 text-sm px-3 py-1 rounded-full">
                      {tag}
                    </span>
                  ))}
                </div>
              </div>
              
              <div 
                className="prose prose-lg max-w-none"
                dangerouslySetInnerHTML={{ __html: post.content }}
              />
              
              <div className="mt-12 pt-8 border-t border-gray-200">
                <h3 className="text-xl font-bold mb-4">分享這篇文章</h3>
                <div className="flex space-x-4">
                  <button className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
                    分享到微信
                  </button>
                  <button className="px-4 py-2 bg-blue-400 text-white rounded hover:bg-blue-500">
                    分享到微博
                  </button>
                </div>
              </div>
            </article>
          </div>
        );
      } 
      

      創(chuàng)建 API 路由

      app/api 目錄中創(chuàng)建 API 端點(diǎn):

      // app/api/hello/route.ts
      // app/api/route.ts
      import { NextRequest, NextResponse } from 'next/server'
      
      // 模擬用戶數(shù)據(jù)
      const users = [
        { id: '1', name: '張三', email: 'zhangsan@example.com' },
        { id: '2', name: '李四', email: 'lisi@example.com' },
        { id: '3', name: '王五', email: 'wangwu@example.com' }
      ];
      
      export async function GET() {
        return NextResponse.json({ 
          success: true,
          data: users,
          timestamp: new Date().toISOString()
        })
      }
      
      export async function POST(request: NextRequest) {
        try {
          const body = await request.json()
          
          // 驗(yàn)證請(qǐng)求數(shù)據(jù)
          if (!body.name) {
            return NextResponse.json(
              { success: false, error: '名稱不能為空' },
              { status: 400 }
            )
          }
          
          // 模擬創(chuàng)建新用戶
          const newUser = {
            id: (users.length + 1).toString(),
            name: body.name,
            email: body.email || null
          }
          
          // 在真實(shí)應(yīng)用中,這里會(huì)將用戶添加到數(shù)據(jù)庫
          // 這里只是模擬
          
          return NextResponse.json({ 
            success: true, 
            data: newUser 
          }, { status: 201 })
        } catch (error) {
          return NextResponse.json(
            { success: false, error: '請(qǐng)求處理失敗' },
            { status: 500 }
          )
        }
      }
      

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

      在服務(wù)器組件中進(jìn)行數(shù)據(jù)獲取(默認(rèn)情況下,page.tsx 是服務(wù)器組件):

      // app/blog/page.tsx - 服務(wù)器組件
      import Link from 'next/link';
      import BlogActions from './components/BlogActions';
      
      // 模擬博客數(shù)據(jù)
      const blogs = [
        { 
          id: '1', 
          title: 'Next.js入門指南',
          excerpt: '了解如何使用Next.js構(gòu)建現(xiàn)代Web應(yīng)用',
          author: {
            name: '張三',
            avatar: 'https://randomuser.me/api/portraits/men/1.jpg'
          },
          publishedAt: '2023-05-15',
          tags: ['Next.js', 'React', '前端開發(fā)']
        },
        { 
          id: '2', 
          title: 'React服務(wù)器組件詳解',
          excerpt: '深入理解React服務(wù)器組件的工作原理',
          author: {
            name: '李四',
            avatar: 'https://randomuser.me/api/portraits/women/2.jpg'
          },
          publishedAt: '2023-06-22',
          tags: ['React', '服務(wù)器組件', '性能優(yōu)化']
        },
        { 
          id: '3', 
          title: 'TypeScript與Next.js',
          excerpt: '如何在Next.js項(xiàng)目中充分利用TypeScript',
          author: {
            name: '王五',
            avatar: 'https://randomuser.me/api/portraits/men/3.jpg'
          },
          publishedAt: '2023-07-10',
          tags: ['TypeScript', 'Next.js', '類型安全']
        }
      ];
      
      // 模擬獲取博客列表函數(shù)
      async function getBlogs() {
        // 模擬網(wǎng)絡(luò)延遲
        await new Promise(resolve => setTimeout(resolve, 500));
        return blogs;
      }
      
      export default async function BlogsPage() {
        // 獲取博客數(shù)據(jù)
        const blogList = await getBlogs();
        
        return (
          <div className="container mx-auto px-4 py-8">
            <div className="flex justify-between items-center mb-8">
              <h1 className="text-3xl font-bold">博客列表</h1>
              <Link 
                href="/blog/new" 
                className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition"
              >
                創(chuàng)建新博客
              </Link>
            </div>
            
            <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
              {blogList.map(blog => (
                <div key={blog.id} className="border rounded-lg overflow-hidden hover:shadow-md transition">
                  <div className="p-6">
                    <h2 className="text-xl font-bold mb-3">{blog.title}</h2>
                    <p className="text-gray-600 mb-4">{blog.excerpt}</p>
                    
                    <div className="flex flex-wrap gap-2 mb-4">
                      {blog.tags.map(tag => (
                        <span 
                          key={tag} 
                          className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded"
                        >
                          {tag}
                        </span>
                      ))}
                    </div>
                    
                    <div className="flex items-center text-sm text-gray-500 mb-4">
                      <img 
                        src={blog.author.avatar} 
                        alt={blog.author.name}
                        className="w-6 h-6 rounded-full mr-2"
                      />
                      <span>{blog.author.name}</span>
                      <span className="mx-2">?</span>
                      <span>{new Date(blog.publishedAt).toLocaleDateString('zh-CN')}</span>
                    </div>
                    
                    <div className="flex space-x-2">
                      <Link 
                        href={`/blog/${blog.id}`} 
                        className="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm"
                      >
                        查看全文
                      </Link>
                      <Link 
                        href={`/blog/edit/${blog.id}`} 
                        className="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600 text-sm"
                      >
                        編輯
                      </Link>
                      <BlogActions blogId={blog.id} />
                    </div>
                  </div>
                </div>
              ))}
            </div>
            
            {blogList.length === 0 && (
              <div className="text-center py-12">
                <p className="text-gray-500 mb-4">暫無博客內(nèi)容</p>
                <Link 
                  href="/blog/new" 
                  className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
                >
                  創(chuàng)建第一篇博客
                </Link>
              </div>
            )}
            
            <div className="mt-8 text-center">
              <Link 
                href="/" 
                className="text-blue-600 hover:underline"
              >
                返回首頁
              </Link>
            </div>
          </div>
        );
      } 
      

      使用客戶端組件進(jìn)行交互:

      // blog/components/BlogActions.tsx
      'use client';
      
      interface BlogActionsProps {
        blogId: string;
      }
      
      export default function BlogActions({ blogId }: BlogActionsProps) {
        const handleDelete = () => {
          alert(`刪除功能尚未實(shí)現(xiàn):${blogId}`);
          // 這里可以實(shí)現(xiàn)實(shí)際的刪除邏輯
        };
      
        return (
          <button 
            className="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 text-sm"
            onClick={handleDelete}
          >
            刪除
          </button>
        );
      } 
      

      安裝依賴

      使用 pnpm 安裝項(xiàng)目依賴:

      # 安裝依賴
      pnpm add axios swr
      
      # 安裝開發(fā)依賴
      pnpm add -D typescript @types/react eslint
      

      運(yùn)行開發(fā)服務(wù)器

      pnpm dev
      

      構(gòu)建和部署

      # 構(gòu)建應(yīng)用
      pnpm build
      
      # 啟動(dòng)生產(chǎn)環(huán)境服務(wù)器
      pnpm start
      

      pnpm 優(yōu)勢(shì)

      pnpm相比npm和yarn有以下優(yōu)勢(shì):

      1. 磁盤空間效率:pnpm使用硬鏈接和內(nèi)容尋址存儲(chǔ),減少了重復(fù)的依賴
      2. 安裝速度快:比npm和yarn快2-3倍
      3. 更嚴(yán)格的依賴管理:通過使用符號(hào)鏈接確保依賴訪問更安全
      4. 內(nèi)置monorepo支持:無需額外工具即可管理多包項(xiàng)目

      pnpm 常用命令

      # 初始化項(xiàng)目
      pnpm init
      
      # 安裝所有依賴
      pnpm install
      
      # 添加依賴
      pnpm add [package]
      
      # 添加開發(fā)依賴
      pnpm add -D [package]
      
      # 更新依賴
      pnpm update
      
      # 運(yùn)行腳本
      pnpm [script]
      
      # 刪除依賴
      pnpm remove [package]
      

      Node.js 與 Next.js 的關(guān)系

      Node.js 與 Next.js 的基本關(guān)系

      Next.js 是構(gòu)建在 Node.js 之上的 React 框架。這種關(guān)系可以從多個(gè)方面理解:

      1. 運(yùn)行時(shí)環(huán)境:Next.js 使用 Node.js 作為其服務(wù)器端運(yùn)行時(shí)環(huán)境
      2. 構(gòu)建工具:Next.js 利用 Node.js 生態(tài)系統(tǒng)中的工具(如 webpack、babel)進(jìn)行代碼構(gòu)建和轉(zhuǎn)換
      3. 包管理:Next.js 項(xiàng)目通過 npm、yarn 或 pnpm 等 Node.js 包管理器管理依賴
      4. API 實(shí)現(xiàn):Next.js 的服務(wù)器端 API 路由基于 Node.js 的 HTTP 模塊實(shí)現(xiàn)

      Next.js 的運(yùn)行時(shí)環(huán)境

      Next.js 確實(shí)在 Node.js 環(huán)境中啟動(dòng)了一個(gè)服務(wù)器來接收來自瀏覽器的請(qǐng)求。這個(gè)過程在不同模式下有所不同:

      開發(fā)環(huán)境

      (pnpm dev)

      在開發(fā)模式下:

      1. Next.js 啟動(dòng)一個(gè) Node.js HTTP 服務(wù)器(默認(rèn)監(jiān)聽 3000 端口)
      2. 該服務(wù)器具有熱模塊替換(HMR)功能,允許實(shí)時(shí)更新
      3. 當(dāng)瀏覽器請(qǐng)求到達(dá)時(shí),Next.js 服務(wù)器根據(jù)請(qǐng)求的路徑:
        • 對(duì)于頁面請(qǐng)求:執(zhí)行服務(wù)器端渲染(SSR)或提供靜態(tài)生成(SSG)的內(nèi)容
        • 對(duì)于 API 請(qǐng)求:執(zhí)行相應(yīng)的 API 路由處理函數(shù)
        • 對(duì)于靜態(tài)資源:提供 public 目錄中的文件
      4. 開發(fā)服務(wù)器還處理源代碼編譯、打包和監(jiān)視文件變化
      瀏覽器請(qǐng)求 → Node.js服務(wù)器(Next.js) → 路由解析 → 頁面渲染/API處理 → 響應(yīng)返回
      

      生產(chǎn)環(huán)境

      (pnpm build 然后 pnpm start)

      在生產(chǎn)模式下:

      1. pnpm build 預(yù)先構(gòu)建所有可能的頁面和資源

        • 靜態(tài)生成(SSG)的頁面被預(yù)渲染為HTML
        • 服務(wù)器組件被優(yōu)化和序列化
        • JavaScript包被優(yōu)化和代碼分割
      2. pnpm start 啟動(dòng)一個(gè)優(yōu)化的 Node.js 生產(chǎn)服務(wù)器

        • 這個(gè)服務(wù)器比開發(fā)服務(wù)器輕量得多
        • 它主要負(fù)責(zé):
          • 提供預(yù)構(gòu)建的靜態(tài)資源
          • 處理動(dòng)態(tài)SSR請(qǐng)求
          • 執(zhí)行API路由
      瀏覽器請(qǐng)求 → Node.js生產(chǎn)服務(wù)器 → 提供預(yù)構(gòu)建資源/動(dòng)態(tài)渲染 → 響應(yīng)返回
      

      渲染模式與Node.js的關(guān)系

      1. 服務(wù)器端渲染(SSR)

        • 每次請(qǐng)求都在 Node.js 環(huán)境中執(zhí)行React組件渲染
        • 生成HTML并發(fā)送給瀏覽器
        • 適用于需要最新數(shù)據(jù)的頁面
      2. 靜態(tài)站點(diǎn)生成(SSG)

        • 在構(gòu)建時(shí)在 Node.js 環(huán)境中預(yù)渲染HTML
        • 請(qǐng)求來臨時(shí)直接提供靜態(tài)HTML
        • 適用于內(nèi)容不經(jīng)常變化的頁面
      3. 增量靜態(tài)再生成(ISR)

        • 結(jié)合SSG和SSR的優(yōu)點(diǎn)
        • 預(yù)渲染HTML,但在指定間隔后在Node.js環(huán)境中重新生成
      4. 客戶端渲染

        • 初始HTML由服務(wù)器提供
        • 后續(xù)渲染和數(shù)據(jù)獲取在瀏覽器中發(fā)生
        • 減輕Node.js服務(wù)器負(fù)載

      Node.js 環(huán)境的限制

      在使用Next.js時(shí),需要注意Node.js環(huán)境的一些特點(diǎn)和限制:

      1. 服務(wù)器組件 vs 客戶端組件

        • 服務(wù)器組件在Node.js環(huán)境中運(yùn)行,可以訪問文件系統(tǒng)、環(huán)境變量等
        • 客戶端組件無法訪問Node.js特有的功能和API
      2. API路由的Node.js能力

        • API路由在Node.js環(huán)境中執(zhí)行,可以使用完整的Node.js功能
        • 包括數(shù)據(jù)庫連接、文件系統(tǒng)操作、復(fù)雜計(jì)算等
      3. 邊緣運(yùn)行時(shí)

        • Next.js還支持Edge Runtime(一種輕量級(jí)運(yùn)行時(shí))
        • Edge Runtime比Node.js更受限,但部署和冷啟動(dòng)更快

      部署架構(gòu)

      Next.js應(yīng)用的部署涉及到Node.js服務(wù)器的管理:

      1. 傳統(tǒng)服務(wù)器

        • 部署完整的Node.js服務(wù)器
        • 例如在AWS EC2、DigitalOcean等上運(yùn)行
      2. 無服務(wù)器函數(shù)

        • 將Next.js應(yīng)用部署為無服務(wù)器函數(shù)
        • 例如AWS Lambda、Vercel等
      3. 靜態(tài)導(dǎo)出

        • 完全靜態(tài)導(dǎo)出,不需要Node.js服務(wù)器
        • 使用 next export 命令
        • 適用于不需要SSR或API路由的項(xiàng)目

      本目錄示例代碼說明

      本目錄包含以下示例文件:

      1. page.tsx: 一個(gè)簡單的 Next.js 首頁示例,展示了:

        • 頁面組件結(jié)構(gòu)
        • 使用 next/head 管理頭部元素
        • 使用 next/link 進(jìn)行客戶端導(dǎo)航
        • React hooks 在 Next.js 中的使用
      2. [id].tsx: 展示動(dòng)態(tài)路由的實(shí)現(xiàn),包括:

        • 動(dòng)態(tài)路由參數(shù)獲取
        • 靜態(tài)生成 (generateStaticParams)
        • 數(shù)據(jù)獲取模式
      3. route.ts: API 路由示例,展示了:

        • 基于請(qǐng)求方法的處理邏輯
        • 響應(yīng)處理
        • 錯(cuò)誤處理

      注意:這些示例基于 App Router 模式實(shí)現(xiàn)。

      App Router 和 Pages Router 的區(qū)別

      特性 App Router (app/) Pages Router (pages/)
      組件模型 React Server Components 客戶端組件
      數(shù)據(jù)獲取 組件中的 fetch 函數(shù) getServerSideProps/getStaticProps
      布局 layout.tsx _app.tsx 和布局組件
      嵌套布局 多個(gè) layout.tsx 需手動(dòng)實(shí)現(xiàn)
      加載狀態(tài) loading.tsx 需手動(dòng)實(shí)現(xiàn)
      錯(cuò)誤處理 error.tsx 需手動(dòng)實(shí)現(xiàn)或使用 Error Boundaries
      API 路由 route.ts 處理程序 pages/api/*.ts

      進(jìn)階資源

      練習(xí)建議

      1. 創(chuàng)建一個(gè)包含多個(gè)頁面的 Next.js 應(yīng)用(使用 App Router)
      2. 實(shí)現(xiàn)動(dòng)態(tài)路由和數(shù)據(jù)獲取
      3. 添加多級(jí)嵌套布局
      4. 創(chuàng)建 API 路由
      5. 實(shí)現(xiàn)錯(cuò)誤處理和加載狀態(tài)
      6. 將項(xiàng)目部署到 Vercel 或其他托管平臺(tái)

      容器知識(shí)入門教程

      容器技術(shù)是現(xiàn)代應(yīng)用開發(fā)和部署的基石,本教程將介紹 Docker 容器的基礎(chǔ)知識(shí)。

      Docker 背景介紹

      什么是 Docker

      Docker 是一個(gè)開源的應(yīng)用容器引擎,讓開發(fā)者可以打包他們的應(yīng)用以及依賴包到一個(gè)可移植的容器中,然后發(fā)布到任何流行的 Linux 或 Windows 操作系統(tǒng)的機(jī)器上。Docker 使用了 Linux 內(nèi)核的多種功能(如 Namespaces、Cgroups)來創(chuàng)建獨(dú)立的容器。

      Docker 的發(fā)展歷史

      • 2013年:Docker 由 dotCloud 公司(后更名為 Docker Inc.)推出,最初是 dotCloud 平臺(tái)的內(nèi)部項(xiàng)目
      • 2014年:Docker 1.0 發(fā)布,正式進(jìn)入生產(chǎn)環(huán)境
      • 2015年:Docker Compose、Docker Swarm 和 Docker Machine 等工具發(fā)布,生態(tài)系統(tǒng)開始繁榮
      • 2016年:引入內(nèi)置的編排功能
      • 2017年:集成 Kubernetes 支持
      • 至今:持續(xù)迭代發(fā)展,成為容器化技術(shù)的事實(shí)標(biāo)準(zhǔn)

      為什么需要 Docker

      在 Docker 出現(xiàn)之前,開發(fā)者面臨以下問題:

      1. 環(huán)境不一致:開發(fā)、測(cè)試、生產(chǎn)環(huán)境的差異導(dǎo)致"在我電腦上能運(yùn)行"的問題
      2. 部署復(fù)雜:應(yīng)用依賴安裝復(fù)雜,配置繁瑣
      3. 資源利用率低:傳統(tǒng)虛擬化方案資源占用高,啟動(dòng)慢
      4. 應(yīng)用隔離困難:不同應(yīng)用之間相互影響
      5. 擴(kuò)展性差:難以快速擴(kuò)容和縮容

      Docker 通過容器化技術(shù)解決了這些問題:

      1. 一致的環(huán)境:無論在哪里運(yùn)行,容器內(nèi)的環(huán)境都是一樣的
      2. 輕量級(jí):容器共享主機(jī)系統(tǒng)內(nèi)核,比傳統(tǒng)虛擬機(jī)占用資源少,啟動(dòng)更快
      3. 隔離:容器之間彼此隔離,不會(huì)相互影響
      4. 可移植性:構(gòu)建一次,到處運(yùn)行
      5. 微服務(wù)支持:適合現(xiàn)代微服務(wù)架構(gòu),每個(gè)服務(wù)獨(dú)立容器化

      Docker vs 虛擬機(jī)

      特性 Docker 容器 虛擬機(jī)
      啟動(dòng)時(shí)間 秒級(jí) 分鐘級(jí)
      存儲(chǔ)空間 MB級(jí) GB級(jí)
      性能 接近原生 有所損耗
      系統(tǒng)資源 共享宿主機(jī)內(nèi)核 獨(dú)立內(nèi)核
      隔離性 進(jìn)程級(jí)隔離 完全隔離
      運(yùn)行密度 單機(jī)可運(yùn)行數(shù)十至數(shù)百個(gè)容器 單機(jī)通常運(yùn)行數(shù)個(gè)虛擬機(jī)

      1. Docker 安裝

      Windows 安裝

      1. 下載 Docker Desktop for Windows
      2. 雙擊安裝程序并按照提示完成安裝
      3. 安裝完成后,Docker Desktop 會(huì)自動(dòng)啟動(dòng)
      4. 在系統(tǒng)托盤中可以看到 Docker 圖標(biāo),表示 Docker 服務(wù)正在運(yùn)行

      macOS 安裝

      1. 下載 Docker Desktop for Mac
      2. 將下載的 .dmg 文件拖到應(yīng)用程序文件夾
      3. 啟動(dòng) Docker Desktop 應(yīng)用
      4. 等待 Docker 初始化完成,頂部狀態(tài)欄會(huì)顯示 Docker 圖標(biāo)

      Linux 安裝 (Ubuntu)

      # 更新軟件包索引
      sudo apt-get update
      
      # 安裝依賴
      sudo apt-get install \
          apt-transport-https \
          ca-certificates \
          curl \
          gnupg \
          lsb-release
      
      # 添加 Docker 官方 GPG 密鑰
      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
      
      # 設(shè)置穩(wěn)定版?zhèn)}庫
      echo \
        "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
        $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
      
      # 安裝 Docker Engine
      sudo apt-get update
      sudo apt-get install docker-ce docker-ce-cli containerd.io
      
      # 將當(dāng)前用戶添加到 docker 組(避免每次都使用 sudo)
      sudo usermod -aG docker $USER
      # 需要重新登錄使配置生效
      

      驗(yàn)證安裝

      # 查看 Docker 版本
      docker --version
      
      # 運(yùn)行測(cè)試容器
      docker run hello-world
      

      2. 常用 Docker 命令

      鏡像相關(guān)命令

      # 搜索鏡像
      docker search ubuntu
      
      # 拉取鏡像
      docker pull ubuntu:latest
      
      # 列出本地鏡像
      docker images
      
      # 刪除鏡像
      docker rmi ubuntu:latest
      
      # 構(gòu)建鏡像
      docker build -t myapp:1.0 .
      

      容器相關(guān)命令

      # 創(chuàng)建并啟動(dòng)容器
      docker run -d -p 8080:80 --name mywebserver nginx
      
      # 列出所有運(yùn)行中的容器
      docker ps
      
      # 列出所有容器(包括已停止的)
      docker ps -a
      
      # 停止容器
      docker stop mywebserver
      
      # 啟動(dòng)已停止的容器
      docker start mywebserver
      
      # 重啟容器
      docker restart mywebserver
      
      # 刪除容器
      docker rm mywebserver
      
      # 進(jìn)入容器交互式終端
      docker exec -it mywebserver bash
      
      # 查看容器日志
      docker logs mywebserver
      
      # 查看容器資源使用情況
      docker stats mywebserver
      

      Docker Compose 命令

      # 啟動(dòng)所有服務(wù)
      docker-compose up -d
      
      # 停止所有服務(wù)
      docker-compose down
      
      # 查看服務(wù)狀態(tài)
      docker-compose ps
      
      # 查看服務(wù)日志
      docker-compose logs
      
      # 重建服務(wù)
      docker-compose build
      

      網(wǎng)絡(luò)和存儲(chǔ)命令

      # 創(chuàng)建網(wǎng)絡(luò)
      docker network create mynetwork
      
      # 列出網(wǎng)絡(luò)
      docker network ls
      
      # 創(chuàng)建卷
      docker volume create mydata
      
      # 列出卷
      docker volume ls
      

      示例項(xiàng)目說明

      本目錄包含一個(gè)簡單的 Docker 示例項(xiàng)目,包括:

      1. Dockerfile: 定義如何構(gòu)建應(yīng)用容器鏡像
      2. docker-compose.yml: 定義多容器應(yīng)用的服務(wù)、網(wǎng)絡(luò)和卷
      3. app.js: 一個(gè)簡單的 Node.js Express 應(yīng)用
      4. package.json: Node.js 應(yīng)用依賴定義

      如何運(yùn)行示例項(xiàng)目

      1. 確保已安裝 Docker 和 Docker Compose

      2. 在此目錄下運(yùn)行:

        docker-compose up -d
        
      3. 訪問應(yīng)用:

      項(xiàng)目文件說明

      Dockerfile

      這個(gè)文件定義了如何構(gòu)建應(yīng)用容器:

      • 使用 Node.js 16 Alpine 作為基礎(chǔ)鏡像
      • 設(shè)置工作目錄
      • 復(fù)制和安裝依賴
      • 配置環(huán)境變量
      • 指定啟動(dòng)命令

      docker-compose.yml

      這個(gè)文件定義了完整的應(yīng)用棧:

      • Web 應(yīng)用服務(wù) (使用 Dockerfile 構(gòu)建)
      • PostgreSQL 數(shù)據(jù)庫服務(wù)
      • Redis 緩存服務(wù)
      • 網(wǎng)絡(luò)配置
      • 卷配置(持久存儲(chǔ))

      app.js

      一個(gè)簡單的 Express 服務(wù)器,展示容器環(huán)境信息和健康檢查端點(diǎn)。

      Docker 網(wǎng)絡(luò)詳解

      Docker 網(wǎng)絡(luò)是容器化環(huán)境中的關(guān)鍵組件,提供了容器間的通信基礎(chǔ)設(shè)施。

      Docker 網(wǎng)絡(luò)的主要作用

      1. 容器間通信:允許不同容器在不暴露端口到主機(jī)的情況下相互通信
      2. 隔離環(huán)境:可以創(chuàng)建完全隔離的網(wǎng)絡(luò)環(huán)境,提高應(yīng)用安全性
      3. 服務(wù)發(fā)現(xiàn):容器可以通過容器名稱而非IP地址相互訪問,簡化服務(wù)發(fā)現(xiàn)
      4. 多主機(jī)連接:使用overlay網(wǎng)絡(luò)可以連接不同主機(jī)上的容器
      5. 網(wǎng)絡(luò)策略控制:可以精細(xì)控制哪些容器可以相互通信

      常用網(wǎng)絡(luò)類型

      # 查看可用的網(wǎng)絡(luò)驅(qū)動(dòng)
      docker info | grep "Network"
      
      # 創(chuàng)建自定義網(wǎng)絡(luò)
      docker network create --driver bridge my-network
      
      # 在創(chuàng)建容器時(shí)連接到指定網(wǎng)絡(luò)
      docker run --network=my-network -d --name container1 nginx
      
      # 將已有容器連接到網(wǎng)絡(luò)
      docker network connect my-network container2
      

      網(wǎng)絡(luò)驅(qū)動(dòng)類型

      • bridge: 默認(rèn)網(wǎng)絡(luò)驅(qū)動(dòng),適用于同一主機(jī)上的容器
      • host: 直接使用主機(jī)網(wǎng)絡(luò),移除容器與主機(jī)間的網(wǎng)絡(luò)隔離
      • overlay: 用于Docker Swarm環(huán)境中,連接多個(gè)Docker守護(hù)進(jìn)程
      • macvlan: 允許容器擁有獨(dú)立的MAC地址,直接連接到物理網(wǎng)絡(luò)
      • none: 禁用所有網(wǎng)絡(luò)

      Docker 卷詳解

      Docker卷提供了容器數(shù)據(jù)的持久化存儲(chǔ)解決方案,解決了容器銷毀后數(shù)據(jù)丟失的問題。

      Docker 卷的主要作用

      1. 數(shù)據(jù)持久化:即使容器被刪除,存儲(chǔ)在卷中的數(shù)據(jù)依然保留
      2. 數(shù)據(jù)共享:多個(gè)容器可以掛載相同的卷,實(shí)現(xiàn)數(shù)據(jù)共享
      3. 備份與恢復(fù):簡化數(shù)據(jù)備份和恢復(fù)流程
      4. 性能優(yōu)化:與容器內(nèi)部存儲(chǔ)相比,卷通常提供更好的I/O性能
      5. 存儲(chǔ)解耦:將應(yīng)用與數(shù)據(jù)分離,提高系統(tǒng)靈活性和可維護(hù)性

      卷的使用方式

      # 創(chuàng)建卷
      docker volume create my-data
      
      # 查看卷的詳細(xì)信息
      docker volume inspect my-data
      
      # 在容器中使用卷
      docker run -d --name my-container -v my-data:/app/data nginx
      
      # 使用綁定掛載(掛載主機(jī)目錄)
      docker run -d --name my-container -v $(pwd):/app/data nginx
      
      # 備份卷中的數(shù)據(jù)
      docker run --rm -v my-data:/source -v $(pwd):/backup alpine tar -czvf /backup/my-data-backup.tar.gz -C /source .
      

      卷的類型

      • 命名卷: 由Docker管理的命名存儲(chǔ)空間
      • 綁定掛載: 直接映射主機(jī)文件系統(tǒng)的路徑到容器
      • tmpfs掛載: 將數(shù)據(jù)存儲(chǔ)在主機(jī)的內(nèi)存中,不寫入文件系統(tǒng)

      使用卷時(shí)要考慮權(quán)限、備份策略和數(shù)據(jù)生命周期管理,以確保數(shù)據(jù)安全和可靠性。

      Docker 進(jìn)階概念

      1. Docker 多階段構(gòu)建:優(yōu)化鏡像大小和構(gòu)建過程
      2. Docker 網(wǎng)絡(luò):bridge、host、overlay 等不同網(wǎng)絡(luò)驅(qū)動(dòng)
      3. Docker 卷:持久化數(shù)據(jù)存儲(chǔ)
      4. Docker Swarm:Docker 原生集群和編排工具
      5. Docker 安全:最佳實(shí)踐和安全配置
      6. Docker Registry:鏡像倉庫和分發(fā)

      相關(guān)資源

      練習(xí)建議

      1. 嘗試為不同語言的應(yīng)用創(chuàng)建 Dockerfile
      2. 練習(xí)使用 Docker Compose 設(shè)置多容器應(yīng)用
      3. 探索 Docker 卷和網(wǎng)絡(luò)
      4. 學(xué)習(xí)如何在生產(chǎn)環(huán)境中安全地部署 Docker 容器

      全棧博客案例

      代碼倉庫

      go-learning:https://github.com/BaiZe1998/go-learning/tree/main/doutok-course/basic-knowledge

      posted on 2025-04-27 23:56  白澤talk  閱讀(931)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 福利一区二区视频在线| 九九成人免费视频| 97视频精品全国免费观看| 国产精品任我爽爆在线播放6080 | 丰满人妻熟妇乱又精品视| 久久天天躁夜夜躁狠狠| 国产AV影片麻豆精品传媒| 亚洲国产精品第一二三区| 在线a级毛片无码免费真人 | 国产精品大片中文字幕| 日韩无专区精品中文字幕| 国产精品自在线拍国产手机版| 久激情内射婷内射蜜桃| 成人免费视频一区二区三区| 人妻一区二区三区人妻黄色| 久久综合亚洲色一区二区三区| 亚洲国产精品一二三区| 蜜臀av性久久久久蜜臀aⅴ麻豆| 亚洲国产成人无码影院| 国产成人啪精品午夜网站| 国产最新AV在线播放不卡| 国产偷国产偷亚洲清高APP| 登封市| 色综合色综合色综合频道| 人妻日韩精品中文字幕| 欧美精品v国产精品v日韩精品| 9久9久热精品视频在线观看| 国产中文一区卡二区不卡| 99精品国产在热久久婷婷| 欧美激烈精交gif动态图| 中文字幕国产精品第一页| 免费特黄夫妻生活片| 九九热久久只有精品2| 亚洲熟妇自偷自拍另亚洲| 国产自产av一区二区三区性色| 熟女精品视频一区二区三区| 亚洲精品一区三区三区在| 中文字幕乱码亚洲无线三区| 免费人成视频网站在线观看18| 亚洲综合精品第一页| 亚洲人成网站色7799|