【pnpm 】pnpm 执行 xxx 的 底层原理

公众号:AI小揭秘。

pnpm install / pnpm run dev / pnpm run build 底层原理

讲清楚 pnpm ipnpm run devpnpm run build 在底层做了什么:执行步骤、数据流、以及它们如何与 lockfile、store、node_modulespackage.json scripts 配合。附流程图方便对照。


一、总览:三条命令分别干啥

命令 缩写 主要职责
pnpm install pnpm i 解析依赖 → 拉包/复用 store → 算目录结构 → 链接到 node_modules
pnpm run dev --- 执行 package.jsondev 脚本(及 predev / postdev),通常跑开发服务器
pnpm run build --- 执行 build 脚本(及 prebuild / postbuild),通常做生产构建

pnpm run 的底层逻辑对 devbuild完全一致 ,只是脚本名不同;差异来自你在 scripts 里写的具体命令(如 vitenext build)。


二、pnpm installpnpm i)底层原理

2.1 核心目标

  • 根据 package.json (及 workspace 的 pnpm-workspace.yaml)确定要装哪些包、哪些版本。
  • pnpm-lock.yaml 锁定解析结果,保证可复现。
  • 把包实体 放进全局 store ,再通过硬链接 + 符号链接 挂到项目的 node_modules,避免重复拷贝。

2.2 整体执行流程(高层)

flowchart TD Start[pnpm install] --> ReadLock{存在 pnpm-lock.yaml?} ReadLock -->|否| Resolve[依赖解析,读 package.json 等] ReadLock -->|是| ParseLock[解析 lockfile] Resolve --> Fetch[从 registry 拉元数据与 tarball] Fetch --> BuildTree[构建依赖树] BuildTree --> WriteLock[写入/更新 pnpm-lock.yaml] ParseLock --> LockOK[锁内容与 package.json 一致?] LockOK -->|否且非 frozen| Resolve LockOK -->|是或 frozen 通过| CalcStruct[计算 node_modules 目录结构] WriteLock --> CalcStruct CalcStruct --> Store[包入 store 或复用已有] Store --> Link[硬链接到 .pnpm, 符号链接到 node_modules] Link --> Done[安装完成]

2.3 分阶段说明

阶段一:Lockfile 与依赖解析
  1. 读 lockfile

    • 若存在 pnpm-lock.yaml,先解析;得到「包名 → 解析后版本、integrity、resolved」等映射。
  2. package.json 对齐

    • 对比 package.json (及 workspace 子包)的 dependenciesdevDependencies 与 lockfile。
    • --frozen-lockfile :若不一致直接失败,不改 lockfile、不写 node_modules
    • 未 frozen:若不一致则重新解析,再更新 lockfile。
  3. 依赖解析(无 lockfile 或需要更新时)

    • registry (默认 npm)拉取元数据,按 semver 解析版本;workspace 内 workspace:* 等解析为本地包。
    • 递归处理传递依赖 ,得到整棵依赖树
    • 若有 overridescatalog 等,在此阶段应用。
  4. 写回 lockfile

    • 将解析结果写回 pnpm-lock.yaml--lockfile-only 时只做这一步,不进行后续链接)。
阶段二:目录结构计算
  1. 计算 node_modules 布局
    • 确定哪些包放在 node_modules (直接依赖)、哪些只在 .pnpm 下、以及 符号链接 的指向。
    • 满足 非扁平、严格依赖:未声明的包不会出现在项目可访问路径下。
阶段三:Store 与链接
  1. Store 存取

    • 实体 存到 全局 store (默认 ~/.local/share/pnpm/store 等,可 store-dir 配置)。
    • 内容寻址:同版本、同 integrity 只存一份;缺少则从 registry 下载 tarball 写入 store。
  2. 硬链接到 .pnpm

    • node_modules/.pnpm 下按 package@version 建目录,包内文件以硬链接从 store 链出。
    • 每个 package@version 有自己的 node_modules ,里面只放它自己的依赖的符号链接。
  3. 符号链接到「使用方」的 node_modules

    • node_modules:项目直接依赖 的包,符号链接到 .pnpm/<pkg>@<version>/node_modules/<pkg>
    • workspace 包workspace:* 解析出的本地包,链接到源码目录,不占 store。

2.4 pnpm install 流程简图(按阶段)

flowchart LR subgraph Phase1 [阶段一 解析] A1[读 package.json] --> A2[读/解析 lockfile] A2 --> A3{一致?} A3 -->|否| A4[解析 + 拉 registry] A4 --> A5[写 lockfile] A3 -->|是| A5 end subgraph Phase2 [阶段二 结构] B1[算依赖树] --> B2[算 node_modules 布局] end subgraph Phase3 [阶段三 存储与链接] C1[store 取/存包] --> C2[硬链接到 .pnpm] C2 --> C3[符号链接到 node_modules] end Phase1 --> Phase2 --> Phase3

2.5 小结

  • pnpm i = 解析(含 lockfile)→ 算结构 → store + 硬链接 + 符号链接。
  • Workspace 下会多一步:解析 pnpm-workspace.yaml、处理 workspace:*,再统一算布局、链接。

三、node_modules 目录结构与执行相关文件

本节把 pnpm install 完成后 node_modules 里有哪些目录和文件、pnpm run dev / pnpm run build 执行时又会用到其中哪些,按「目录 → 文件 → 执行逻辑」列清楚,并详细列出与执行相关的文件清单

3.1 node_modules 顶层目录一览

以单包项目、依赖了 vitelodash 为例,项目根目录下的 node_modules 大致长这样:

ruby 复制代码
<项目根>/node_modules/
├── .bin/                    # 可执行命令的入口(见 3.3)
│   ├── vite                 # Unix 下执行 vite 时实际跑的文件
│   ├── vite.cmd             # Windows CMD
│   ├── vite.ps1             # Windows PowerShell
│   ├── tsc
│   ├── tsc.cmd
│   └── ...
├── .modules.yaml            # pnpm 元数据(store 路径、layout 版本等)
├── .pnpm/                   # 所有包实体所在处(硬链接到 store,见 3.2)
├── vite                     # 符号链接 → .pnpm/vite@x.x.x/node_modules/vite
├── lodash                   # 符号链接 → .pnpm/lodash@x.x.x/node_modules/lodash
└── ...
  • 直接依赖 (如 vitelodash):在顶层以包名 出现,实际是符号链接 ,指向 .pnpm/<包名>@<版本>/node_modules/<包名>
  • .bin :下面是对应各包 bin 字段的可执行入口 (脚本或符号链接),pnpm run dev / pnpm run build 时 PATH 里会带上这个目录。
  • .modules.yaml :pnpm 自己用的元数据,记录 store 路径、layout 版本等,run 不读它,install 会写。

3.1.1 与「执行」相关的 node_modules 内文件详细清单

下表按路径 列出 pnpm run dev / pnpm run build 执行链路中会读、会执行的 node_modules 内文件与目录;「执行逻辑」一列说明该文件在运行时的作用。

路径 类型 谁创建 执行时作用 / 执行逻辑
node_modules/.bin/ 目录 pnpm install 被加入 PATH 前面;shell 解析 vitetsc 等命令时在此目录查找可执行文件。
node_modules/.bin/vite 文件(脚本或符号链接) pnpm install(根据 vite 的 bin 字段) Unix/macOS :被 shell 执行。若为脚本,首行 shebang 调 node,正文调包内入口;若为符号链接,指向 .pnpm/vite@x.x.x/node_modules/vite/dist/node/cli.js 等,由 node 执行。
node_modules/.bin/vite.cmd 文件(批处理) pnpm install Windows CMD :执行时用 node "%~dp0\..\vite\dist\node\cli.js" 等形式调包内入口(%~dp0 为 .cmd 所在目录)。
node_modules/.bin/vite.ps1 文件(PowerShell) pnpm install Windows PowerShell :脚本内用 node $PSScriptRoot\..\vite\dist\node\cli.js 等调包内入口。
node_modules/.bin/tsc 文件 pnpm install(typescript 的 bin) 同上逻辑,最终执行 node .../typescript/bin/tsc 或 tsc.js。
node_modules/.bin/tsc.cmd / .ps1 文件 pnpm install Windows 下执行 tsc 时命中的 wrapper。
node_modules/.pnpm/ 目录 pnpm install 存所有包实体;run 不直接遍历,而是通过 .bin 里的 wrapper 间接执行到其下某包的 bin 入口文件
node_modules/.pnpm/vite@5.4.0/node_modules/vite/ 目录(硬链接到 store) pnpm install 包本体;.bin/vite 的 wrapper 最终会 node 这个目录下 package.json#bin 指定的入口(如 dist/node/cli.js)。
node_modules/.pnpm/vite@5.4.0/node_modules/vite/package.json 文件 包自带 定义 bin 入口路径;pnpm 安装时据此在 .bin 下生成 wrapper;运行时由 wrapper 或 node 间接读到入口路径。
node_modules/.pnpm/vite@5.4.0/node_modules/vite/dist/node/cli.js 文件 包自带 vite 的 CLI 入口;.bin/vite (或 .cmd/.ps1)最终执行 node .../cli.js,即此文件。
node_modules/.pnpm/typescript@x.x.x/node_modules/typescript/bin/tsctsc.js 文件 包自带 tsc 命令的真实入口;.bin/tsc 最终执行此文件。
node_modules/vite 符号链接 pnpm install 指向 .pnpm/vite@x.x.x/node_modules/viterun 时若脚本里用 node 的 require/import 解析 vite,会走到此链接再到 .pnpm 下包本体。
node_modules/.modules.yaml 文件 pnpm install 记录 store 路径、layout 版本;仅 install 使用run 不读。

目录小结

  • 执行 dev/build 直接用到package.json(scripts)、node_modules/.bin/* (wrapper)、.pnpm/<包>@<版本>/node_modules/<包>/bin 入口文件
  • 间接用到 :顶层 node_modules/<包名> 符号链接(Node 解析 require('vite') 等时)、.pnpm 下各依赖的 node_modules(运行时模块解析)。

3.2 .pnpm 目录结构(包实体与依赖链)

.pnpm 里才是「包的真实内容」所在位置(内容来自 store 的硬链接)。每个 package@version 一个目录,且每个包有自己的 node_modules ,只放自己声明的依赖的符号链接。

示例(项目依赖 vitevite 又依赖 esbuild 等):

ruby 复制代码
node_modules/.pnpm/
├── vite@5.4.0
│   └── node_modules/
│       ├── vite          # 指向 store 的硬链接(包本体)
│       ├── esbuild       # 符号链接 → ../../esbuild@x.x.x/node_modules/esbuild
│       ├── rollup        # 符号链接 → ...
│       └── ...
├── esbuild@0.19.x
│   └── node_modules/
│       └── esbuild       # 指向 store
├── lodash@4.17.21
│   └── node_modules/
│       └── lodash
└── ...
  • <包名>@<版本>/node_modules/<包名>:包本体(目录或硬链接到 store 的目录)。
  • <包名>@<版本>/node_modules/<依赖名> :该包的依赖,以符号链接 指到 ../../<依赖名>@<版本>/node_modules/<依赖名>
  • 根目录的 node_modules/vite :符号链接到 .pnpm/vite@5.4.0/node_modules/vite ,所以你在代码里 import 'vite' 时,Node 解析到的就是 .pnpm 里这一份。

执行逻辑

  • pnpm install 只写 storenode_modules (含 .pnpm 与顶层符号链接、.bin);不执行任何业务脚本。
  • pnpm run dev / pnpm run build 不会去「遍历 .pnpm」;它们只是执行 package.json 里配置的命令 ,命令里若写 vite,就会通过 PATH 找到 node_modules/.bin/vite ,再由该文件间接执行到 .pnpm 里对应包的入口

3.3 .bin 目录:有哪些文件、怎么被执行

.bin 下的文件来自各依赖包 package.jsonbin 字段。pnpm 在 install 阶段会为每个 bin 项在 node_modules/.bin 下生成可执行入口 ,名字即 bin 的 key(如 vitetsc)。

平台 / 类型 文件名示例 说明
Unix / Linux / macOS vitetsc(无后缀) 一般为脚本 (shebang 调用 node)或符号链接到包内 bin 文件。
Windows CMD vite.cmdtsc.cmd 批处理,内部通常用 node "%~dp0\..\vite\dist\cli.js" 等形式调包内入口。
Windows PowerShell vite.ps1tsc.ps1 PowerShell 脚本,同样会去调包内对应 js。

.bin 下典型文件内容示例(执行逻辑)

  • Unix:node_modules/.bin/vite (脚本形式时)

    内容通常类似:

    bash 复制代码
    #!/usr/bin/env node
    require('../vite/dist/node/cli.js')

    或直接为符号链接 ,指向 .pnpm/vite@5.4.0/node_modules/vite/dist/node/cli.js 。执行时:shell 调起该文件 → 若为脚本则 #!/usr/bin/env node 导致用 node 执行本文件,进而 require 包内 cli.js ;若为符号链接则 node 执行链接目标(即 cli.js)。

  • Windows CMD:node_modules/.bin/vite.cmd

    内容通常类似:

    bat 复制代码
    @echo off
    node "%~dp0..\vite\dist\node\cli.js" %*

    执行逻辑%~dp0 为当前 .cmd 所在目录(即 node_modules/.bin),..\vite 为顶层符号链接 vite (在 pnpm 下会解析到 .pnpm 里对应包),最终用 node 执行 cli.js%* 把命令行参数原样传给 cli.js。

  • Windows PowerShell:node_modules/.bin/vite.ps1

    逻辑类似,用 $PSScriptRoot 定位到 .bin,再 node 执行上一级 vite 下的入口 js。

执行逻辑(以 pnpm run dev 且 scripts.dev 为 vite 为例)

  1. pnpm 在当前包package.json 里读到 scripts.dev = "vite"
  2. pnpm 把 <包目录>/node_modules/.bin (及 workspace 根同路径)加到 PATH 前面,再在子 shell 里执行 vite
  3. 系统在 PATH 里找到第一个 名为 vite 的可执行文件:
    • Unix :即 node_modules/.bin/vite(无后缀),可能是脚本或符号链接;
    • Windows CMD :会找 vite.cmd ;PowerShell 可能用 vite.ps1
  4. 执行该文件:
    • 若是脚本 ,内容通常类似 #!/usr/bin/env node + 调 node <包内入口> ,或直接 node path/to/vite/dist/node/cli.js
    • 若是符号链接 ,会指向 .pnpm/vite@x.x.x/node_modules/vite 下的 bin 入口 (如 dist/node/cli.js),再由 node 执行该 js。
  5. 最终实际运行的是 node + .pnpm/vite@x.x.x/node_modules/vite 里声明的 bin 入口文件

因此:执行链路 = package.json#scripts.dev → shell 执行 vite → PATH 解析到 node_modules/.bin/vite (或 .cmd/.ps1)→ 该文件内部执行 node + .pnpm 里 vite 的 bin 入口

执行时文件与目录关系(示意)

flowchart LR A[package.json] -->|读 scripts.dev/build| B[命令字符串 vite 等] B --> C[PATH 含 node_modules/.bin] C --> D[node_modules/.bin/vite] D --> E[.pnpm/vite@x.x.x/node_modules/vite 下 bin 入口] E --> F[node 执行 cli.js]

3.4 执行 dev / build 时涉及的文件与目录(按顺序)

步骤 类型 路径 / 文件 作用
1 <包目录>/package.json 确定当前包、查 scripts.dev / scripts.build 等。
2 scripts.predev / scripts.dev / scripts.build 得到要执行的命令字符串 (如 vitevite build)。
3 环境 <包目录>/node_modules/.bin<workspace根>/node_modules/.bin 被 pnpm 追加到 PATH 前面。
4 执行 node_modules/.bin/vite (或 vite.cmd / vite.ps1 shell 解析 vite 时命中的可执行文件。
5 执行 node_modules/.pnpm/vite@x.x.x/node_modules/vite/dist/node/cli.js(以 vite 为例) .bin 里的 wrapper 最终用 node 执行的真实入口
6 该包及其依赖下的 package.jsonnode_modules/... Node / Vite 等运行时按模块解析规则继续读,与 pnpm 无直接关系。

3.4.1 按「是否参与执行」区分的 node_modules 目录一览

下面用一棵更完整的目录树,标出执行 dev/build 时直接参与 的目录/文件(✅)与仅 install 使用、run 不读的(○):

python 复制代码
<项目根>/node_modules/
├── .bin/                          ✅ run 时 PATH 包含此目录,执行 vite/tsc 等命中此处
│   ├── vite                       ✅ Unix 下执行 vite 时运行
│   ├── vite.cmd                   ✅ Windows CMD 下执行 vite 时运行
│   ├── vite.ps1                   ✅ Windows PowerShell 下执行 vite 时运行
│   ├── tsc / tsc.cmd / tsc.ps1    ✅ 同上,tsc 命令
│   └── ...
├── .modules.yaml                  ○ 仅 pnpm install 读写,run 不读
├── .pnpm/                         ✅ run 时通过 .bin wrapper 间接执行到其下包的 bin 入口
│   ├── vite@5.4.0/
│   │   └── node_modules/
│   │       ├── vite/              ✅ 包本体,.bin/vite 最终 node 其下 bin 入口
│   │       │   ├── package.json   ✅ 定义 bin 入口路径
│   │       │   └── dist/node/cli.js  ✅ vite 命令的真实执行文件
│   │       ├── esbuild            ○ run 时由 vite 等按 require 解析
│   │       └── ...
│   ├── typescript@5.x.x/
│   │   └── node_modules/
│   │       └── typescript/bin/tsc ✅ tsc 命令的真实执行文件
│   └── ...
├── vite                           ✅ 符号链接;Node require('vite') 等会解析到此
├── lodash                         ✅ 同上
└── ...

执行链路小结
scripts.dev 字符串(如 vite)→ shell 在 PATH 里找到 node_modules/.bin/vite (或 .cmd/.ps1)→ 该文件内部执行 node + .pnpm 下 vite 的 bin 入口 (如 cli.js)→ 之后由 Vite/Node 按模块解析规则读 .pnpm 下各依赖,与 pnpm 无直接关系。

目录小结

  • install 生成并维护:node_modules/node_modules/.pnpm/node_modules/.bin/node_modules/.modules.yaml,以及顶层包名符号链接。
  • run 直接用到的是:package.json (读 scripts)、node_modules/.bin/* (执行入口),间接用到 .pnpm 里对应包的 bin 入口文件。

3.5 小结

  • node_modules 顶层:.bin (可执行入口)、.pnpm (包实体与依赖链)、.modules.yaml (pnpm 元数据)、以及直接依赖的符号链接。
  • .pnpm :按 包名@版本 存包本体(硬链接到 store),每个包有自己的 node_modules,里面是该包依赖的符号链接。
  • .bin :由 install 根据各包 bin 生成;run 时 PATH 包含 .bin,执行 vite 等会先走到 .bin 再转到 .pnpm 里对应包的入口文件。
  • 执行 dev/build :先读 package.json 的 scripts,再在子 shell 里执行命令字符串,通过 .bin 找到并执行对应包的 bin 入口。

四、pnpm run(含 dev / build)底层原理

4.1 核心目标

  • 当前包package.jsonscripts 里找到对应脚本(如 devbuild)。
  • pre / 本体 / post 顺序执行(若有)。
  • 执行时把 node_modules/.bin (及 workspace 根 node_modules/.bin)加入 PATH,以便直接跑本地安装的 CLI。

4.2 整体执行流程

flowchart TD Start[pnpm run scriptName] --> ResolvePkg[解析当前包,读 package.json] ResolvePkg --> FindScript{scripts.scriptName 存在?} FindScript -->|否| Err[报错 Missing script] FindScript -->|是| Pre{存在 pre scriptName?} Pre -->|是| RunPre[执行 pre scriptName] Pre -->|否| RunMain RunPre --> RunMain[执行 scriptName] RunMain --> Post{存在 post scriptName?} Post -->|是| RunPost[执行 post scriptName] Post -->|否| Done[结束] RunPost --> Done

4.3 分步骤说明

1. 确定「当前包」与 script
  • 当前目录 若不是 workspace 根,pnpm 会向上找 包含 package.json 的目录,当作当前包
  • Workspace :若在子包目录执行 pnpm run dev,则用该子包package.json;在根目录则用根包的。
2. 查找 script
  • package.jsonscripts 里找 scriptName (如 devbuild)。
  • 没有则报 Missing script: "dev" 等错误。
3. Pre / 本体 / Post 顺序
  • 若存在 prescriptName ,先执行 pnpm run prescriptName(递归,同样有 pre/post)。
  • 再执行 scriptName 对应的命令。
  • 若存在 postscriptName ,再执行 pnpm run postscriptName
  • 例如 pnpm run build → 有 prebuild 则先 prebuild,再 build,再 postbuild(若有)。
4. 准备执行环境(PATH 等)
  • <包目录>/node_modules/.bin 加入 PATH 前端。
  • Workspace :还会把 <workspace 根>/node_modules/.bin 加入 PATH,因此根目录装的 CLI(如 vitetsc)在子包里也能直接调用。
5. 执行命令
  • 子 shell 中执行 scripts[scriptName] 里的字符串(如 vitenext dev)。
  • 通常通过 nodenode_modules/.bin 下对应平台的 wrapper (如 vitevite.jsvite.cmd),再 node vite.js;具体由 npm lifecycles / run-script 等底层处理。

PATH 与 .bin 的关系

pnpm 先把 node_modules/.bin (及 workspace 根同路径)塞进 PATH 前面,再启子进程跑脚本。因此脚本里写的 vitetsc 等会解析到 node_modules/.bin 里的 wrapper,而 .bin 里的文件是 pnpm install 阶段根据各包 bin 字段创建的符号链接或脚本。流程关系如下:

flowchart LR subgraph Install [pnpm install] I1[解析依赖] --> I2[链接包到 node_modules] I2 --> I3[根据 bin 字段生成 .bin 下可执行文件] end subgraph Run [pnpm run dev 或 build] R1[查找 scripts.dev 或 scripts.build] --> R2[PATH 前追加 node_modules/.bin] R2 --> R3[子 shell 执行脚本命令] R3 --> R4[解析 vite 等到 .bin 对应 wrapper] end I3 -.->|install 完成后 .bin 就绪| R4

4.4 pnpm run 流程简图(环境 + 生命周期)

flowchart TD subgraph Env [环境准备] E1[确定当前包] --> E2[找 scripts.scriptName] E2 --> E3[PATH += node_modules/.bin] E3 --> E4[Workspace 时 PATH += 根 node_modules/.bin] end subgraph Lifecycle [生命周期] L1[pre scriptName] --> L2[scriptName] L2 --> L3[post scriptName] end Env --> Lifecycle Lifecycle --> Spawn[在子 shell 中执行命令] Spawn --> Exit[退出码决定 pnpm run 成功/失败]

4.5 devbuild 在「run」层面的区别

  • 执行机制完全相同 :都是 pnpm run <script> ,只是 <script> 名字不同。
  • 差异 来自你在 scripts 里写的命令,例如:
    • dev :常为 vitenext devwebpack serve长期进程
    • build :常为 vite buildnext buildtsc一次性构建
  • Pre/post :若你配置了 predev / postdevprebuild / postbuild,会按顺序跑;没配则只跑本体。

4.6 小结

  • pnpm run dev / pnpm run build = 找 script → 可能 pre → 本体 → 可能 post;执行前把 node_modules/.bin 等加入 PATH,在子 shell 中跑对应命令。
  • node_modules/.bin 里的可执行文件由 依赖包bin 字段生成,pnpm 在 install 阶段已经链好;run 只负责 查 script、改 PATH、调起这些 bin

五、三者之间的关系

flowchart LR subgraph Install [pnpm install] I1[解析依赖] --> I2[store 与链接] I2 --> I3[node_modules 就绪] I3 --> I4[.bin 可执行文件就绪] end subgraph Run [pnpm run dev / build] R1[读 scripts] --> R2[PATH += .bin] R2 --> R3[pre / 本体 / post] R3 --> R4[执行 vite / next 等] end I4 --> R1
  • pnpm install 准备好 node_modulesnode_modules/.binpnpm run dev / pnpm run build 才能正确找到 vitenext 等命令。
  • 未安装就 run ,通常会报 找不到命令Cannot find module

六、常用 flag 与行为

6.1 pnpm install

Flag 作用
--frozen-lockfile 不更新 lockfile;若与 package.json 不一致则失败
--lockfile-only 只更新 pnpm-lock.yaml ,不写 node_modules
--prefer-offline 尽量用 store,缺的再拉
--offline 只用 store,不访问 registry

6.2 pnpm run

Flag 作用
--silent 少打日志
--prefix <path> 以指定目录为包根(找 package.json

dev / build 本身没有专属 flag;传参会透传给脚本,例如:

bash 复制代码
pnpm run build -- --mode production

-- 后面的 --mode production 会交给 scripts.build 对应的命令。


七、参考

相关推荐
用户52709648744901 天前
前端登录菜单加载性能优化总结
前端
你觉得脆皮鸡好吃吗1 天前
Check Anti-CSRF Token (AI)
前端·网络·网络协议·安全·csrf·网络安全学习
一个快乐的咸鱼1 天前
nextjs接入AI实现流式输出
前端
誰在花里胡哨1 天前
Vue<前端页面装修组件>
前端·vue.js
张元清1 天前
Pareto 动态路由实战:[slug]、catch-all、嵌套布局
前端·javascript·面试
fix一个write十个1 天前
NativeWind v4 与 React Native UI Kit或三方库样式隔离指南
前端·react native
懂懂tty1 天前
React中BeginWork和CompleteWork解析
前端·react.js
_下雨天.1 天前
HAProxy搭建Web群集
前端
梦想CAD控件1 天前
在线CAD开发包图纸转换功能使用指南
前端·javascript·vue.js
亚空间仓鼠1 天前
Ansible之Playbook(三):变量应用
java·前端·ansible