1. 从零搭建企业级 Monorepo 工程化模板:初始化、应用创建与共享 TypeScript 配置

导语

本文记录我在搭建企业级 HRMS 人事管理系统 Monorepo 模板时的学习笔记,涵盖第一步初始化基础结构、第二步创建第一个应用、第三步配置共享 TypeScript 配置。内容包含核心概念、操作步骤和避坑指南,适合刚开始接触 Monorepo 和 Vue3 + TS 工程化的开发者参考。

第一步:初始化 Monorepo 基础结构

1.1 初始化 Git

  • 作用 :在当前目录创建一个空的 Git 仓库,生成 .git 文件夹,用于版本控制。

  • 解决问题:让项目能够被 Git 跟踪,后续可以提交代码、回滚、协作等。

  • 操作步骤

    1. 在项目根目录执行 git init

    2. 关联远程仓库,在终端中执行以下命令(以 Gitee 为例):

      bash 复制代码
      git remote add origin https://gitee.com/xxxx/hrms-monorepo-2.git
      git push -u origin "master"
  • 我的理解:Git 是项目的地基,没有它后续的版本管理无从谈起,是搭建任何项目的第一步。

1.2 项目初始化(创建根 package.json)

  • 作用 :在项目根目录生成 package.json 文件,用于声明项目名称、版本、脚本、依赖等元信息,是 Node.js 项目的核心配置文件。

  • 解决问题 :没有 package.json,后续无法使用 pnpm 安装依赖、执行脚本命令;同时通过定制字段(如 privatepackageManagerengines)可以约束项目属性和环境。

  • 操作步骤

    1. 在项目根目录执行 pnpm init(会自动生成一个基础的 package.json)。

    2. 打开 package.json,将其内容修改为以下结构(可直接复制粘贴):

      json 复制代码
      {
        "name": "hrms-monorepo",
        "version": "1.0.0",
        "private": true,
        "description": "企业 HRMS 人事管理系统,采用 Monorepo 工程化架构,包含后台管理端、数据可视化大屏与公共工具包,配套完整代码规范、安全及无障碍校验体系,覆盖组织、员工、权限、薪资、考勤、审批等全量人事业务模块",
        "author": "咖啡无伴侣",
        "license": "UNLICENSED",
        "type": "module",
        "scripts": {
          "test": "echo "Error: no test specified" && exit 1"
        },
        "engines": {
          "node": ">= 22.14.0",
          "pnpm": ">=11.24.0"
        },
        "packageManager": "pnpm@11.24.0"
      }
    3. 修改说明:

      • 修改 description 为项目描述信息。
      • 添加 "private": true 防止项目被误发布到 npm。
      • 删除 main 字段:monorepo 多包项目的入口文件位于各子包中,根目录无需 main
      • 添加 "type": "module":表示项目采用 ES Module 规范(使用 importexport),而不是 CommonJS 模式。
      • 删除 keywords 字段:根包不发布,无需提供搜索关键词。
      • 删除 devEngines 对象:该字段尚未被广泛支持,且已通过 enginespackageManager 约束版本,避免冗余。
      • 添加 engines 对象:配置 Node.js 和 pnpm 的版本要求。
  • 我的理解package.json 是 Node.js 项目的配置文件,其中包含项目的基本信息与脚本配置。只有当项目中包含这个文件时,才能运行 npmpnpm 等脚本工具。

1.3 配置 pnpm Workspace

  • 概念 :pnpm workspace 允许在一个仓库中管理多个相互独立的包(packages),并通过 pnpm-workspace.yaml 声明哪些目录是包。这样 pnpm 能自动通过符号链接关联本地依赖,避免重复安装相同版本的包,节省磁盘空间。

  • 操作步骤

    1. 在项目根目录创建 pnpm-workspace.yaml,内容如下:

      yaml 复制代码
      packages:
        - "apps/*"
        - "packages/*"
    2. 创建目录 apps(如果尚未存在)。

  • 我的理解 :pnpm 通过 pnpm-workspace.yaml 文件来识别哪些目录是子项目,从而统一管理整个 monorepo 的依赖和脚本。

1.4 总结

  1. 项目创建之初就要初始化 Git 仓库,便于团队开发协同。

  2. 修改根目录 package.json

    • 添加 "private": true,防止根包被误发布到 npm。
    • 删除 main 字段:monorepo 的入口文件位于各子包中,根目录无需 main
    • 删除 keywords 字段:根包不发布,无需关键词。
    • 删除 devEngines 字段:该字段尚未被广泛支持,且已通过 enginespackageManager 约束版本。
    • 添加 "type": "module":声明使用 ES Modules 规范(import/export)。
    • 添加 engines 字段:要求 Node 和 pnpm 的最低版本。
    • 添加 packageManager 字段:指定使用的包管理器及精确版本,便于配合 corepack 统一环境。

第二步:创建第一个应用(hrms-admin)

2.1 理解 monorepo 的工作原理

核心问题:为什么 vue 放在子项目,typescript 放在根目录?

在 Monorepo 中,依赖不是随意放置的,而是遵循职责分离依赖隔离的原则。理解这一点,是掌握 Monorepo 工程化的关键。

1. 运行时依赖 vs 开发时依赖

  • 运行时依赖 :应用在浏览器运行时必需的包,例如 vuevue-routerpinia

    • 特征 :会被 import 到源码中,参与最终打包,应用离开它无法运行。
    • 放置位置 :子项目的 dependencies
  • 开发时依赖 :只在开发、构建、检查阶段使用的工具,例如 typescripteslintprettier

    • 特征:不参与最终打包,只辅助开发流程(类型检查、代码规范、格式化)。
    • 放置位置 :根目录的 devDependencies,因为工具链应当全仓库统一,避免版本不一致。

重点运行时依赖 放在子项目,开发工具 放在根目录。

原因:应用需要独立可控的框架版本,而工具链需要全仓库统一。

2. pnpm 的依赖隔离机制

pnpm 采用严格的依赖隔离 ,子项目只能访问自己 package.json 中显式声明的依赖。

  • import 语句 :必须在子项目声明对应依赖,否则报错。
    例如 hrms-admin 中写 import { createApp } from 'vue',那么 vue 必须出现在 hrms-admin/package.jsondependencies 中。
  • 终端命令 :如 tscvue-tsc,执行时会向上查找 node_modules/.bin
    因此根目录安装的 typescript 能被所有子项目直接使用,无需子项目重复声明。

重点import 看声明,命令看查找路径

子项目必须声明自己要 import 的包;而命令工具可以从根目录继承。

3. pnpm 的符号链接与全局 Store

pnpm 安装依赖时,不会将依赖文件复制到每个子项目的 node_modules,而是使用符号链接全局 Store

  • 全局 Store :所有依赖包的实际文件存储在一个统一位置(如 ~/.pnpm-store)。同一个版本的依赖只会保存一份,不同项目共享。
  • 虚拟存储 .pnpm :在项目 node_modules/.pnpm 下创建硬链接,指向全局 Store,并构建依赖关系图。
  • 子项目 node_modules :只包含符号链接,指向 .pnpm 中的实际包。
    例如 hrms-admin/node_modules/vue 是一个链接,指向 .pnpm/vue@3.5.31/node_modules/vue

重点依赖只有一份真实文件,项目通过链接共享

好处:节省磁盘空间、安装速度快、避免重复下载。

4. workspace 协议与跨包引用

pnpm 通过 pnpm-workspace.yaml 声明哪些目录是包,并支持 workspace 协议进行本地包引用。

  • 例如在 hrms-admin/package.json 中写:

    json 复制代码
    {
      "dependencies": {
        "@hrms/utils": "workspace:*"
      }
    }

    表示引用本地 packages/utils 包,pnpm 会自动链接它,无需发布到 npm。

  • 修改 packages/utils 后,依赖它的子项目立即生效,可以在一次 Git 提交中完成共享包和应用的联动更新。

重点workspace 协议让本地包像 npm 包一样被引用,实现跨包即时联动,这是 Monorepo 的核心优势。

5. 总结:Monorepo 依赖管理的黄金法则

对比维度 示例 放置位置 原因
运行时依赖 vuevue-routerpinia 子项目 dependencies 谁用谁声明,依赖隔离
应用级构建工具 vite@vitejs/plugin-vue 子项目 devDependencies 不同应用构建需求可能不同
通用开发工具 typescripteslintprettier 根目录 devDependencies 全仓库统一版本,避免冲突

理解这些原则,你就知道了在 Monorepo 中每个依赖应该放在哪里,以及 pnpm 如何通过隔离 + 链接实现高效、安全的依赖管理。

2.2 创建 hrms-admin 应用的核心知识点

1. 子包 package.json 的关键字段

字段 作用 关键点
name 定义包名 使用作用域命名,如 @hrms/admin,区分不同子包
private 防止包被发布 设为 true,仅用于内部应用
type 声明模块规范 "module" 使 import/export 语法生效
scripts 定义常用命令 dev 启动开发服务器,build 先类型检查再构建,preview 预览产物
dependencies 运行时依赖 vue,浏览器运行必需
devDependencies 开发/构建依赖 vite@vitejs/plugin-vuetypescriptvue-tsc,不参与最终打包

重点 :Monorepo 中谁用谁声明 。子包必须声明自己 import 的依赖;通用开发工具(如 typescript)可提升到根目录,但 vite 和 Vue 插件通常留在子包,因为它们与应用强绑定。

2. index.html 的作用

  • Vite 的入口文件,浏览器直接加载。
  • 包含 <div id="app">,Vue 应用挂载点。
  • 通过 <script type="module" src="/src/main.ts"> 引入入口模块。
  • type="module" :让浏览器按 ES Module 加载脚本,支持 import 语法,并具有延迟执行和作用域隔离特性。

3. src/main.ts 的挂载流程

ts 复制代码
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#app");
  • createApp(App):创建 Vue 应用实例。
  • .mount('#app'):将应用挂载到 index.html 中 id 为 app 的元素。
  • 这是 Vue3 启动应用的标准写法。

4. App.vue 中的响应式基础

vue 复制代码
<script setup lang="ts">
import { ref } from "vue";
const msg = ref("Hello HRMS");
function changeMsg() {
  msg.value = "Hello Vue3 + TypeScript";
}
</script>

<template>
  <h1>{{ msg }}</h1>
  <button @click="changeMsg">点击我改变文字</button>
</template>
  • 使用 <script setup lang="ts"> 语法糖,更简洁。
  • ref 创建响应式数据,模板中自动解包(直接写 msg,无需 .value)。
  • @click 绑定事件,修改 ref 值会触发视图更新。

5. vite.config.mts 的作用

ts 复制代码
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [vue()],
});
  • defineConfig 用于获得类型提示。
  • 必须从 @vitejs/plugin-vue 导入插件 ,不能从 'vue' 导入(否则报错)。
  • 插件让 Vite 能编译 .vue 文件。

6. tsconfig.json 的核心作用(理解即可,不深究所有字段)

  • 告诉 TypeScript 如何检查类型。
  • "strict": true:开启严格模式,是 TS 的核心价值。
  • "include" :指定要检查的文件(如 src/**/*)。
  • tsconfig.node.json 专门用于 Node 环境下的配置文件(如 vite.config.mts)。

重点:现在不需要背所有字段,遇到类型错误再反查即可。

7. pnpm 安装与依赖链接

  • 执行 pnpm install 后,pnpm 会:

    • 识别 workspace 中的子包。
    • 将依赖下载到全局 store。
    • 在子包 node_modules 中创建符号链接,指向全局 store 中的真实文件。
  • 同一个依赖版本只存储一份,多个项目共享,节省磁盘空间。

  • 若出现 Ignored build scripts 提示(如 esbuild),执行 pnpm approve-builds 批准构建脚本。

8. 总结表格

文件 作用 关键点
package.json 声明依赖和脚本 type: "module", private: true
index.html 浏览器入口 <div id="app">, type="module"
src/main.ts 应用启动 createApp(App).mount('#app')
src/App.vue 根组件 <script setup>, ref, @click
vite.config.mts Vite 配置 导入 @vitejs/plugin-vue
tsconfig.json TS 检查配置 strict: true, include
pnpm install 依赖安装 全局 store + 符号链接,去重节省空间

第三步:共享 TypeScript 配置

前置知识:TypeScript 是什么?

TypeScript 是 JavaScript 的超集,它在 JavaScript 的基础上添加了静态类型系统。简单说,TypeScript 允许你在写代码时声明变量、参数、返回值的类型,编译器会在开发阶段检查类型错误,提前发现潜在问题,而不是等到运行时才报错。它最终会被编译成纯 JavaScript 运行在浏览器或 Node.js 中。

为什么需要 TypeScript?

  • 提升代码可读性和可维护性,类型即文档。
  • 减少低级错误(如拼写错误、类型不匹配、空值访问)。
  • 更好的编辑器支持(智能提示、重构、跳转)。
  • 适合大型项目和团队协作。

3.1 创建共享配置包 packages/typescript-config

1. 在 packages/typescript-config 下新建 package.json 文件

json 复制代码
{
  "name": "@hrms/typescript-config",
  "version": "0.0.1",
  "private": true,
  "type": "module",
  "exports": {
    "./base.json": "./base.json",
    "./vue.json": "./vue.json",
    "./node.json": "./node.json"
  }
}

2. 标量字段说明

字段 作用
name @hrms/typescript-config 包名,@hrms 是作用域,用于在 monorepo 中引用该配置包
version 0.0.1 包版本,目前为初始版本
private true 防止误发布到 npm,仅内部使用
type module 声明包使用 ES Module 规范

3. exports 字段说明

exports 定义了导出映射 ,允许使用者通过 @hrms/typescript-config/子路径 的方式导入配置文件。

json

perl 复制代码
"exports": {
  "./base.json": "./base.json",  // 导入 @hrms/typescript-config/base.json 时,返回包内根目录的 base.json
  "./vue.json": "./vue.json",    // 导入 @hrms/typescript-config/vue.json 时,返回包内根目录的 vue.json
  "./node.json": "./node.json"   // 导入 @hrms/typescript-config/node.json 时,返回包内根目录的 node.json
}

3.2 子项目继承与路径别名配置

1. base.json 文件

json 复制代码
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,
    "noEmit": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  }
}

字段说明

字段 作用
$schema https://json.schemastore.org/tsconfig 指定 JSON Schema 地址,让编辑器(如 VS Code)提供智能提示和校验
compilerOptions 对象 TypeScript 编译选项的容器,所有具体配置都写在这个对象内
target ES2020 指定编译后 JavaScript 的语法版本,确保代码能在支持 ES2020 的环境中运行
module ESNext 指定模块系统标准,使用最新的 ES 模块语法(即 import/export
moduleResolution bundler 模块解析策略,告诉 TS 使用打包器(如 Vite、Webpack)的方式解析模块路径,支持 exports 字段和省略扩展名
strict true 开启所有严格类型检查选项,是 TS 类型安全的核心保障
jsx preserve 保留 JSX 语法,不进行转换,交给后续工具(如 Vite)处理。在 Vue 项目中用于支持 TSX
resolveJsonModule true 允许导入 .json 文件,并自动推断其类型
isolatedModules true 确保每个文件可以独立编译,兼容 Babel 等单文件转译工具,防止某些不安全语法
esModuleInterop true 允许用 ESM 默认导入 CommonJS 模块,避免 import react from 'react' 这类写法报错
lib ["ES2020", "DOM", "DOM.Iterable"] 指定编译时可用的全局类型库,包含 ES2020 API、DOM 接口和 DOM 可迭代对象类型
skipLibCheck true 跳过对所有 .d.ts 声明文件的类型检查,加快编译速度,避免第三方库类型冲突
noEmit true 不生成输出文件,仅做类型检查(通常配合 vue-tsc --noEmit 使用)
noUnusedLocals true 报告未使用的局部变量错误,保持代码整洁
noUnusedParameters true 报告未使用的函数参数错误
noFallthroughCasesInSwitch true 禁止 switch 语句中 case 出现贯穿(fallthrough),必须显式 break 或 return

2. node.json 文件

在 Monorepo 共享 TypeScript 配置中,node.json 没有继承 base.json有意为之,主要基于以下原因:

  • 运行环境不同

    • base.json 面向浏览器 + Vue 应用,包含 "lib": ["ES2020", "DOM", "DOM.Iterable"]"jsx": "preserve" 等浏览器/前端相关选项。
    • node.json 用于 Node.js 环境(例如 vite.config.mts),它不需要 DOM 类型,也不应该包含 JSX 配置。如果继承 base.json,就会把这些不必要的选项带入 Node 配置,可能引发类型错误或混淆。
  • noEmit 与项目引用的冲突

    • base.json 中设置了 "noEmit": true,目的是让 vue-tsc --noEmit 只做类型检查,不输出文件。

    • 但 TypeScript 的项目引用(Project References) 要求被引用的项目(如 tsconfig.node.json)必须设置 "composite": true,且不能同时设置 "noEmit": true,否则会报错:

      text 复制代码
      Referenced project may not disable emit.
    • 因此 node.json 必须覆盖 noEmitfalse。如果它继承了 base.json,就需要显式覆盖,容易遗漏且逻辑混乱。

  • 独立性更清晰

    node.json 独立定义,可以让每个配置文件职责单一:

    • base.json:前端通用基础配置(浏览器、Vue、严格模式等)
    • vue.json:继承 base.json 并添加 Vue 相关类型(如 vite/client
    • node.json:专门针对 Node 工具链配置,不继承,避免耦合
  • 代码块

    json 复制代码
    {
      "$schema": "https://json.schemastore.org/tsconfig",
      "compilerOptions": {
        "composite": true,
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "lib": ["ES2020"],
        "skipLibCheck": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "noEmit": false
      }
    }
  • 字段说明

    字段 作用
    skipLibCheck true 跳过对所有 .d.ts 声明文件的类型检查,加速编译,避免第三方库类型冲突
    allowSyntheticDefaultImports true 允许从没有默认导出的模块中使用默认导入(例如 import path from 'path'),方便在 Node 环境中使用 CommonJS 模块
    lib ["ES2020"] 指定编译时可用的全局类型库。这里只引入 ES2020,不包含 DOM,避免 Node 环境下误用浏览器 API
    noEmit false 允许输出文件。由于项目引用(references)要求被引用项目不能禁用 emit,这里设置为 false 以满足构建规则(实际 vue-tsc --noEmit 检查时不会真正输出)

3. vue.json

json

json 复制代码
{
  "extends": "./base.json",
  "compilerOptions": {
    "types": ["vite/client"]
  }
}
  • 字段说明

    字段 作用
    extends ./base.json 继承同目录下的基础 TypeScript 配置,避免重复定义通用编译选项
    types ["vite/client"] 引入 Vite 客户端类型声明,使 import.meta.env、静态资源导入(如 .vue.svg)等获得类型支持
  • 补充说明

    • extends:允许当前配置文件复用另一个配置文件的设置,同时可以覆盖或增加特定选项。这里 vue.json 继承 base.json 的所有浏览器相关配置,只需额外声明 Vite 客户端类型即可。

    • types:默认情况下 TypeScript 会加载 node_modules/@types 下的所有类型包。但通过 types 字段可以显式限制要包含的类型声明包,避免无关类型干扰。vite/client 是 Vite 提供的类型定义文件,包含:

      • import.meta.env 的环境变量类型
      • .vue.svg.css 等资源的模块声明
      • Vite 特有的 HMR API 类型

3.3 避坑指南(常见错误与解决方案)

坑 1:baseUrl 已弃用警告

现象

TypeScript 编译时提示:

text

arduino 复制代码
选项"baseUrl"已弃用,并将停止在 TypeScript 7.0 中运行。

原因

TypeScript 6.0 开始弃用 baseUrl,因为 paths 已经可以独立工作,不再需要基准目录。

解决方案

删除 baseUrl,将 paths 中的路径改为相对于 tsconfig.json 文件的相对路径。

json

json 复制代码
// 错误写法
{
  "baseUrl": ".",
  "paths": {
    "@/*": ["src/*"]
  }
}

// 正确写法
{
  "paths": {
    "@/*": ["./src/*"]
  }
}

预防

配置路径别名时,不要依赖 baseUrl,直接使用以 ./../ 开头的相对路径。

坑 2:项目引用要求 compositenoEmit 冲突

现象

执行 vue-tsc --noEmit 时报错:

text

bash 复制代码
Referenced project 'tsconfig.node.json' may not disable emit.

原因

TypeScript 项目引用(references)要求被引用项目必须设置 "composite": true,并且不能同时设置 "noEmit": true。而 base.json 中为了类型检查设置了 "noEmit": true,被继承后导致冲突。

解决方案

在子项目的 tsconfig.node.json 中显式覆盖 "noEmit": false,并确保 "composite": true 存在。

json

json 复制代码
{
  "extends": "@hrms/typescript-config/node.json",
  "compilerOptions": {
    "composite": true,
    "noEmit": false
  },
  "include": ["vite.config.mts"]
}

同时建议在共享配置 node.json 中直接设置 "noEmit": false,避免每个子项目都要重复覆盖。

预防

在设计共享配置时,node.json 最好不继承 base.json,而是独立定义,从根本上避免环境差异带来的冲突。

坑 3:路径别名在 Vite 中无效

现象

TypeScript 能识别 @/ 别名,但 Vite 构建或开发服务器报错找不到模块。

原因

TypeScript 的 paths 只影响类型检查,不会影响构建工具。Vite 需要单独配置 resolve.alias

解决方案

vite.config.mts 中添加与 tsconfig.json 一致的别名配置。

ts

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
})

预防

修改路径别名时,记得同步更新 TypeScript 和 Vite 两处配置,保持一致性。

坑 4:忘记安装 @types/node 导致 Node 模块类型缺失

现象

vite.config.mts 中使用 import { fileURLToPath } from 'node:url' 时,TypeScript 报错找不到模块。

原因

node:url 是 Node.js 内置模块,但 TypeScript 需要对应的类型声明包 @types/node 才能识别。

解决方案

在根目录安装 @types/node 作为开发依赖(因为多个子包可能都需要)。

bash

sql 复制代码
pnpm add -D -w @types/node

预防

在 Monorepo 中,如果某个配置文件运行在 Node 环境,提前安装 @types/node 并放在根目录,统一管理。

坑 5:共享配置包 exports 未正确导出导致 extends 失败

现象

子项目 tsconfig.json 中写 "extends": "@hrms/typescript-config/vue.json" 时,TypeScript 报错找不到模块。

原因

共享配置包的 package.json 中没有正确配置 exports 字段,或者路径映射错误。

解决方案

确保共享包的 package.json 包含:

json

perl 复制代码
{
  "name": "@hrms/typescript-config",
  "exports": {
    "./base.json": "./base.json",
    "./node.json": "./node.json",
    "./vue.json": "./vue.json"
  }
}

并且子项目的 devDependencies 中通过 workspace:* 引用了该包。

预防

创建共享配置包后,先在子项目测试 extends 是否能正确解析,再继续其他配置。


写在最后

以上就是我搭建 Monorepo 模板前三步的完整记录,涵盖基础结构初始化、第一个 Vue3 应用创建、共享 TypeScript 配置包的设计与坑点。后续我还会继续完善 ESLint、Prettier、Husky 等工程化配置,并逐步引入 Turborepo 和 CI/CD,感兴趣的朋友可以持续关注。

如果本文对你有帮助,欢迎点赞、收藏、评论,也欢迎指出不足之处,一起交流进步。

相关推荐
moonsims18 分钟前
再议AiBrainBox-V的前左右三目布局-满足多目SLAM算法;对比单下视VIO(低空、地面纹理丰富、飞行速度适中无人机 )&多目VIO
前端·人工智能·量子计算
AI编程实验室19 分钟前
Agent Handoff 自动跟踪 Skill:安装、事件映射与证据分级
前端·ai编程
KoPa20 分钟前
HeySmart:事件总线——异步解耦的艺术
前端·后端
金花顺20 分钟前
ndroid 音频系统:AudioTrack 源码深度解析(从 Java 构造到 Native 启动)
前端·架构
用户9210802628620 分钟前
AI SSE Client 和普通 SSE Client 有什么不同:一次生成任务背后的坑与设计边界
前端
PedroQue9929 分钟前
@meng-xi/create-uni-app v1.0.0 正式发布
前端·uni-app
younuo365537 分钟前
广州网站搭建费用明细:域名、服务器与开发成本全解析
服务器·前端·github
恋猫de小郭1 小时前
Flutter A2UI 深度解析,它是怎么提供动态生产力的,然后为什么 A2UI 不只是 Flutter
android·前端·flutter
snow@li1 小时前
服务器运维:Alibaba Cloud Linux 4 LTS・Vue前端 Java 后端 K3S 部署 CICD 目录规范清单
linux·前端·vue.js