多层同心圆思维路径图编辑器部署实录
多层同心圆思维路径图编辑器部署实录
Ubuntu + Node.js + Vite + 宝塔 + Nginx + Windows Hosts + mkcert HTTPS
一、项目最终部署情况
| 项目 | 实际配置 |
|---|---|
| 应用名称 | 多层同心圆思维路径图编辑器 |
| 前端技术 | React + Vite |
| 服务器系统 | Ubuntu 26.04.1 LTS |
| Node.js | v22.23.4 |
| npm | v10.9.9 |
| Web 服务器 | Nginx 1.30.5 |
| 网站管理 | 宝塔面板 |
| 源码目录 | /opt/mindmap-editor-v2 |
| 网站目录 | /www/wwwroot/mindmap-editor |
| 本地域名 | mm.local |
| 访问地址 | https://mm.local |
| SSL 工具 | mkcert v1.4.4 |
| SSL 证书有效期 | 至 2029 年 1 月 22 日 |
整个过程的核心原理是:
1. ZIP 项目源码
2. Ubuntu 解压及检查
3. npm 安装依赖、修复冲突
4. Vite 构建 dist 静态文件
5. 复制到宝塔网站目录
6. Nginx 提供 HTTP 服务
7. Windows 解析 mm.local
8. mkcert 签发本地证书
9. 宝塔启用 HTTPS
二、第一阶段:准备 Ubuntu 服务器环境
2.1 检查操作系统
在 Ubuntu 服务器终端执行:
cat /etc/os-release
# 作用:查看操作系统发行版及版本号。
# 本次服务器:Ubuntu 26.04.1 LTS。
uname -m
# 作用:查看服务器 CPU 架构。
# 用于确认 Node.js 等软件应使用哪个架构版本。
2.2 检查 Node.js 和 npm
node -v
# 作用:查看 Node.js 版本。
# 本次环境:v22.23.4。
npm -v
# 作用:查看 npm 包管理器版本。
# 本次环境:10.9.9。
Node.js 用于安装依赖和构建项目。由于我们使用的是 Vite 前端工程,服务器需要 Node.js 完成构建,但不需要长期运行 Node.js 服务。
2.3 检查 Nginx
nginx -v
# 作用:查看 Nginx 版本。
# 本次环境:1.30.5。
Nginx 的职责是把构建完成的 HTML、JavaScript 和 CSS 文件提供给浏览器。
三、第二阶段:上传和解压项目源码
最开始,我们处理的是一个压缩包:
多层同心圆.zip
项目最终放在:
/opt/mindmap-editor-v2
3.1 创建项目目录
以下是复现部署时可使用的命令:
mkdir -p /opt/mindmap-editor-v2
# 作用:创建项目源码目录。
# -p:父目录不存在时自动创建;目录存在时不报错。
将 ZIP 文件上传到服务器后,进入项目目录:
cd /opt/mindmap-editor-v2
# 作用:进入源码目录,准备检查和构建项目。
3.2 解压源码
如果 ZIP 文件保存在当前目录,可以执行:
unzip "多层同心圆.zip" -d /opt/mindmap-editor-v2
# 作用:将 ZIP 文件解压到指定目录。
# -d:指定解压目标路径。
# 注意:实际使用时,应避免解压后产生多余的一层目录。
这一条是整理出的复现命令,并非对最初上传、解压操作的逐字记录。
3.3 检查源码结构
ls -la /opt/mindmap-editor-v2
# 作用:列出项目目录中的文件及权限信息。
# -l:显示详细信息。
# -a:包括隐藏文件。
我们当时确认项目包含 package.json、src 等必要内容,属于可以构建的前端工程。
典型的 Vite 项目结构如下:
/opt/mindmap-editor-v2/
├── package.json
├── package-lock.json
├── index.html
├── vite.config.ts
├── src/
├── node_modules/ # 安装依赖后生成
└── dist/ # 构建成功后生成
这里的结构是示意,不代表压缩包中每个文件都与示意完全一致。
四、第三阶段:安装 npm 依赖并解决冲突
这是本次部署过程中遇到的第一个实质性问题。
4.1 安装项目依赖
进入项目目录:
cd /opt/mindmap-editor-v2
# 作用:确保后续 npm 命令在项目根目录执行。
安装依赖:
npm install
# 作用:读取 package.json,安装项目运行和构建所需的依赖包。
# 安装结果通常保存在 node_modules 目录中。
4.2 遇到依赖版本冲突
当时项目存在以下依赖版本关系:
| 依赖 | 原配置 |
|---|---|
| Vite | ^8.3.0 |
| esbuild | ^0.25.0 |
安装过程中发生了依赖解析冲突。
问题不在于 Ubuntu,也不在于宝塔,而是项目中的 Vite 与直接声明的 esbuild 版本约束不兼容。
4.3 修复 esbuild 版本
我们采用的修复命令:
npm pkg set 'devDependencies.esbuild=^0.28.0'
# 作用:修改 package.json 中的开发依赖配置。
# devDependencies.esbuild:指定要修改的依赖项。
# ^0.28.0:将 esbuild 的版本约束更新为兼容范围。
这条命令直接修改 package.json,不需要手动打开文件编辑。
随后重新安装:
npm install
# 作用:按照修改后的依赖配置重新解析并安装依赖。
# 本次结果:安装成功,审计报告为 0 vulnerabilities。
这里最重要的经验:不要一遇到 npm 依赖冲突就直接使用 --force。 应优先检查版本约束并修复不兼容的依赖,否则可能安装成功但构建或运行时出错。
五、第四阶段:使用 Vite 构建生产版本
依赖安装成功后,执行:
cd /opt/mindmap-editor-v2
# 作用:进入项目根目录。
npm run build
# 作用:执行 package.json 中定义的 build 脚本。
# 本次项目使用 Vite 进行生产构建。
# 构建结果输出到 dist 目录。
本次构建成功,实际使用的是 Vite 8.3.5,处理了约 1672 个模块。
构建过程中曾出现关于 vite.config.ts 中 __dirname 的警告,但没有导致构建失败。
5.1 检查构建结果
ls -lah /opt/mindmap-editor-v2/dist
# 作用:查看构建输出目录。
# -l:显示详细信息。
# -a:显示隐藏文件。
# -h:以易读单位显示文件大小。
构建后的核心结构为:
dist/
├── index.html
└── assets/
├── JavaScript 构建文件
└── CSS 构建文件
部署时需要的是 dist 里面的内容,而不是整个 React 源码目录。
这一点非常关键。因为宝塔管理的 Nginx 网站是静态站点,它需要直接访问 index.html 和相应的静态资源。
六、第五阶段:部署到宝塔网站目录
我们选择的实际网站目录是:
/www/wwwroot/mindmap-editor
6.1 创建网站目录
复现时可以执行:
mkdir -p /www/wwwroot/mindmap-editor
# 作用:创建 Nginx 网站根目录。
# -p:目录已存在时不报错。
6.2 复制构建结果
本次实际使用的部署方式:
cp -a /opt/mindmap-editor-v2/dist/. /www/wwwroot/mindmap-editor/
# 作用:将 dist 中的全部构建文件复制到网站根目录。
# -a:尽可能保留文件属性并递归复制目录。
# dist/.:表示复制 dist 目录中的内容,而不是复制 dist 目录本身。
这里的 dist/. 值得特别注意。
正确结果:
/www/wwwroot/mindmap-editor/
├── index.html
└── assets/
错误结果:
/www/wwwroot/mindmap-editor/
└── dist/
├── index.html
└── assets/
如果网站根目录配置为 /www/wwwroot/mindmap-editor,但 index.html 却在下一级 dist 中,就容易导致访问首页时出现问题。
6.3 设置文件属主
本次执行:
chown -R www:www /www/wwwroot/mindmap-editor
# 作用:将网站目录及其内部文件的属主和属组设为 www。
# -R:递归处理全部子目录和文件。
# www:www:用户为 www,用户组为 www。
这样做是为了配合当前宝塔环境中网站文件的权限管理。
注意,www:www 是本次服务器使用的账户配置,并非所有 Linux 系统都必须使用这一账户。
6.4 检查网站文件
ls -lah /www/wwwroot/mindmap-editor
# 作用:检查 index.html 和 assets 是否存在。
# 同时确认文件属主、属组及访问权限。
七、第六阶段:在宝塔面板创建网站
这部分是在宝塔图形界面中完成的。
7.1 新建网站
进入:
宝塔面板 → 网站 → 添加站点
配置如下:
| 配置项 | 填写内容 |
|---|---|
| 域名 | mm.local |
| 网站根目录 | /www/wwwroot/mindmap-editor |
| 网站类型 | 静态网站 |
| Web 服务 | Nginx |
| SSL | 初始阶段不启用 |
保存后,宝塔生成对应的 Nginx 网站配置。
7.2 检查网站是否运行
当时宝塔网站列表中,mm.local 已经显示为运行状态。
同时,原有的 wp.local 网站也存在。
本次部署没有必要修改 wp.local 的网站根目录或证书配置。
7.3 验证 Nginx 能否正确识别 mm.local
在 Ubuntu 服务器中执行:
curl -I -H 'Host: mm.local' http://127.0.0.1/
# 作用:向本机 Nginx 发送 HTTP 请求,并指定 Host 为 mm.local。
# -I:只请求响应头。
# -H:添加 HTTP 请求头。
# Host: mm.local:让 Nginx 匹配 mm.local 对应的虚拟主机。
# 127.0.0.1:请求服务器本机。
实际返回:
HTTP/1.1 200 OK
这说明 Nginx 能够通过 mm.local 的 Host 请求访问网站。
接着执行:
curl -s -H 'Host: mm.local' http://127.0.0.1/ | head -20
# 作用:读取 mm.local 首页 HTML 内容的前 20 行。
# -s:静默模式,减少 curl 进度信息。
# -H:指定请求的 Host。
# head -20:只显示前 20 行。
我们看到 HTML 中包含页面标题:
多层同心圆思维路径图编辑器 - Concentric Mind Path Editor
并且包含前端构建资源的引用。
这证明网站已经能够通过 Nginx 正确返回构建后的 HTML 文件。
八、第七阶段:在 Windows 中访问 mm.local
宝塔创建网站并不意味着 Windows 自动知道 mm.local 对应哪台服务器。
因此需要解决本地域名解析。
8.1 Windows Hosts 文件
Windows Hosts 文件位于:
C:\Windows\System32\drivers\etc\hosts
可以通过管理员 PowerShell 打开:
notepad C:\Windows\System32\drivers\etc\hosts
# 作用:使用记事本打开 Windows Hosts 文件。
# 注意:需要以管理员权限运行 PowerShell 才能保存修改。
Hosts 中需要存在类似记录:
服务器实际IP mm.local
例如,假设服务器地址是 192.168.1.47,可以写:
192.168.1.47 mm.local
# 作用:让 Windows 将 mm.local 解析到指定服务器 IP。
# 这里的地址仅为示例,实际必须填写部署网站的服务器地址。
如果服务器不在局域网,而是通过公网 IP 访问,则需要使用实际可达的公网 IP。
本次我们最终已经能够从 Windows Chrome 打开 http://mm.local,说明客户端到网站的域名解析和 HTTP 访问链路已经打通。
8.2 检查域名解析
补充检查命令:
ping mm.local
# 作用:查看 Windows 将 mm.local 解析到了哪个 IP。
# 注意:服务器禁用 ICMP 时,ping 可能不通,但网站仍然可以访问。
更适合检查 HTTP 端口的命令:
Test-NetConnection mm.local -Port 80
# 作用:测试 Windows 到 mm.local 的 TCP 80 端口是否可连接。
# TcpTestSucceeded 为 True 表示 TCP 连接成功。
8.3 首次浏览器访问
打开:
http://mm.local
我们当时已经在 Chrome 中看到完整的同心圆编辑器界面,包括多层圆环、角度调整等功能。
至此,应用部署和 HTTP 访问已经成功。
但 Chrome 地址栏仍然显示“不安全”,因此我们进入下一阶段:配置本地 HTTPS。
九、第八阶段:检查 Windows 上的 mkcert
最开始,我们尝试直接执行:
mkcert -version
# 作用:检查 mkcert 是否可直接从系统 PATH 中调用。
# 本次结果:无法识别命令。
mkcert -CAROOT
# 作用:尝试查看 mkcert 的根 CA 目录。
# 本次结果:同样无法识别命令。
当时还检查了两个包管理器:
scoop --version
# 作用:检查 Scoop 是否可用。
# 结果:无法识别。
choco --version
# 作用:检查 Chocolatey 是否可用。
# 结果:无法识别。
随后,你发现原来调试 wp.local 时就已经下载了 mkcert。
目录是:
C:\mkcert
其中包含:
mkcert.exewp.local.pemwp.local-key.pem192.168.1.47.pem192.168.1.47-key.pem
所以我们不再下载或安装新程序,而是直接使用现有的 mkcert。
9.1 验证 mkcert
& "C:\mkcert\mkcert.exe" -version
# 作用:直接调用 C:\mkcert 中的程序并显示版本。
# &:PowerShell 调用运算符。
# 实际输出:v1.4.4。
9.2 查看根 CA 目录
& "C:\mkcert\mkcert.exe" -CAROOT
# 作用:查看 mkcert 根证书颁发机构的存储位置。
# 实际输出:C:\Users\Administrator\AppData\Local\mkcert。
十、第九阶段:生成 mm.local 的本地 SSL 证书
10.1 创建独立证书目录
New-Item -ItemType Directory -Force C:\mkcert\mm-local
# 作用:创建 mm.local 专用的证书存储目录。
# -ItemType Directory:创建文件夹。
# -Force:允许目录已存在。
实际创建成功:
C:\mkcert\mm-local
10.2 签发证书
& "C:\mkcert\mkcert.exe" -cert-file "C:\mkcert\mm-local\mm.local.pem" -key-file "C:\mkcert\mm-local\mm.local-key.pem" mm.local
# 作用:为 mm.local 生成本地 HTTPS 证书及其私钥。
# -cert-file:指定证书保存路径。
# -key-file:指定私钥保存路径。
# mm.local:证书要覆盖的域名。
实际输出:
Created a new certificate valid for the following names
- "mm.local"
The certificate is at
"C:\mkcert\mm-local\mm.local.pem"
and the key at
"C:\mkcert\mm-local\mm.local-key.pem"
It will expire on 22 January 2029
说明证书签发成功。
10.3 检查证书文件
Get-ChildItem C:\mkcert\mm-local
# 作用:查看目录中的文件。
# 预期看到 mm.local.pem 和 mm.local-key.pem。
10.4 安装根 CA(必要时)
& "C:\mkcert\mkcert.exe" -install
# 作用:将 mkcert 的本地根 CA 安装到受支持的信任存储中。
# 只有本机尚未信任该 CA 时才需要执行。
由于你之前已经用 mkcert 调试过 wp.local,可能早就完成了本机 CA 信任设置。
这里需要强调:生成证书与安装根 CA 是两个不同操作。 生成证书成功,不必然说明浏览器已经信任它。
十一、第十阶段:在宝塔中启用 HTTPS
进入:
宝塔 → 网站 → mm.local → 设置 → SSL
选择「其他证书」或相应的手动证书配置功能。
11.1 填写证书
打开 Windows 文件:
C:\mkcert\mm-local\mm.local.pem
复制文件全部内容,粘贴到宝塔的 SSL 证书输入框。
11.2 填写私钥
打开:
C:\mkcert\mm-local\mm.local-key.pem
复制文件全部内容,粘贴到宝塔的私钥输入框。
然后保存或部署证书。
需要注意:
- 证书与私钥必须匹配。
- 不要将
rootCA-key.pem上传到宝塔。 - 不要覆盖
wp.local的证书。 - 不要将私钥放进网站公开访问的静态目录。
11.3 验证 HTTPS
在 Chrome 中打开:
https://mm.local
你已经确认配置完成。
如果需要额外检查 443 端口,可以在 Windows PowerShell 中执行:
Test-NetConnection mm.local -Port 443
# 作用:测试 mm.local 的 HTTPS TCP 443 端口连通性。
# TcpTestSucceeded 为 True:说明 TCP 连接成功。
# 注意:这条命令不检查证书是否受信任。
如果浏览器出现证书不受信任的错误,需要检查 Windows 是否信任签发该证书的 mkcert 根 CA。
十二、以后修改代码,如何重新发布?
项目已经部署成功,后续更新时通常不需要重复创建宝塔网站、修改 Hosts 或重新申请证书。
只需要更新源码、重新构建、同步静态文件。
cd /opt/mindmap-editor-v2
# 作用:进入现有源码目录。
npm install
# 作用:在依赖配置发生变化时重新安装或更新依赖。
# 如果只是修改前端代码,且依赖没有变化,这一步通常可以省略。
npm run build
# 作用:重新生成最新的 dist 生产构建文件。
推荐使用 rsync 更新网站目录:
rsync -av --delete /opt/mindmap-editor-v2/dist/ /www/wwwroot/mindmap-editor/
# 作用:将最新构建结果同步到网站根目录。
# -a:递归同步并尽可能保留文件属性。
# -v:显示同步详情。
# --delete:删除目标目录中源目录已不存在的文件。
# 注意:仅在网站根目录完全由 dist 构建结果管理时使用 --delete。
然后调整文件属主:
chown -R www:www /www/wwwroot/mindmap-editor
# 作用:确保同步后的文件属主符合当前宝塔环境的配置。
如果只更新前端静态文件,通常不需要重启 Nginx。刷新浏览器即可;如果仍显示旧版本,可尝试强制刷新缓存。
十三、本次遇到的问题及解决方案
| 问题 | 原因或判断 | 最终处理 |
|---|---|---|
| npm 安装失败 | Vite 与 esbuild 版本约束冲突 | 调整 esbuild 版本后重新安装 |
| Vite 构建时出现警告 | vite.config.ts 中的 __dirname 提示 |
构建成功,未将警告误判为失败 |
| 宝塔网站需要显示前端应用 | Nginx 应提供构建后的静态文件 | 将 dist 内容复制到网站根目录 |
| 需要确认 Nginx 是否正常 | 浏览器访问前先检查服务器响应 | curl 验证 HTTP 200 和 HTML 内容 |
Windows 需要访问 mm.local |
本地域名需要正确解析 | 配置客户端域名解析并成功访问 |
| 浏览器显示 HTTP 不安全 | 尚未配置 HTTPS | 使用 mkcert 生成本地证书 |
mkcert 命令无法识别 |
程序不在 PATH 中 | 使用完整路径调用已有的 mkcert.exe |
| Scoop、Chocolatey 不存在 | 当前 Windows 未安装这些包管理器 | 直接使用原有 mkcert |
| HTTPS 证书需要部署 | 生成证书不等于 Nginx 自动使用证书 | 在宝塔 SSL 页面手动配置 |
十四、最终目录结构
Ubuntu 服务器
/opt/
└── mindmap-editor-v2/
├── package.json
├── vite.config.ts
├── src/
├── node_modules/
└── dist/
├── index.html
└── assets/
/www/wwwroot/
└── mindmap-editor/
├── index.html
└── assets/
Windows 电脑
C:\
├── mkcert\
│ ├── mkcert.exe
│ ├── wp.local.pem
│ ├── wp.local-key.pem
│ └── mm-local\
│ ├── mm.local.pem
│ └── mm.local-key.pem
│
├── Users\Administrator\AppData\Local\mkcert\
│ ├── rootCA.pem
│ └── rootCA-key.pem
│
└── Windows\System32\drivers\etc\
└── hosts
上面的树形结构用于说明各文件的用途和位置,部分中间文件已省略。
十五、这次部署最值得保留的经验
本次项目成功的关键,是把部署过程分成了四个相互独立的环节:
- 源码构建:解决 npm 依赖问题,确保 Vite 能生成
dist。 - 服务器发布:把
dist文件复制到宝塔网站目录,让 Nginx 正确提供页面。 - 本地域名解析:让 Windows 能够通过
mm.local找到服务器。 - HTTPS 配置:通过 mkcert 签发证书,并让宝塔 Nginx 使用它。
以后遇到网站打不开,不应该一开始就反复修改 Nginx,而应该按照这四个环节逐一检查。
最终结果:多层同心圆思维路径图编辑器已从 ZIP 源码成功部署到 Ubuntu 服务器,并通过宝塔管理的 Nginx,以 https://mm.local 提供本地 HTTPS 访问。
说明:以上保留了能够从本次操作记录中确认的实际路径、版本、故障及命令。最初 ZIP 上传和解压阶段无法逐字核实的命令,已明确标为复现命令,避免把推测写成实际执行记录。

浙公网安备 33010602011771号