news 2026/10/18 15:12:22

《英语单词软件EngFlow》第 27 章 · 打包发布:从 dev 到安装程序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《英语单词软件EngFlow》第 27 章 · 打包发布:从 dev 到安装程序

本章你将学会:

  1. 分清三种产物:dev(开发时)、dist(构建产物)、bundle(安装包)
  2. 看懂npm run build的两步:先vue-tsc查错,再vite build装箱
  3. 逐行读懂src-tauri/tauri.conf.json——软件出生证明上的每一栏
  4. 亲手打出安装程序,装到另一台电脑(或另一个用户账户)上验证
  5. 学会备份学习记录:复制一个 json 文件,就能把大脑搬走

需要的前置章节:第 1 章(Tauri 盒子)、第 5 章(Vite)、第 6 章(跑起来)、第 13 章(数据存哪)
对应项目文件:package.json、src-tauri/tauri.conf.json、src-tauri/Cargo.toml、dist/

27.1 从一个场景开始

软件做完那天,小雅说:“我想让我表哥也用上,他在另一个城市,电脑里没有 Node、没有 VS Code,只有浏览器都装不利索。”

你发现问题了:现在 EngFlow 只在你这台电脑、这个开发环境里活着——离开npm run tauri dev这条命令,它就不存在。可是软件的本领恰恰是离开作者也能活:拷进任何一台 Windows 电脑,双击图标就能用。

从"我电脑上跑着的代码"到"别人电脑上双击的程序",中间隔着一步,叫打包发布(build & bundle)。这一步有三道关卡,每道都有自己的产物,新手最容易搞混:

源码(菜谱) ──npm run build──▶ dist(标准化的成品菜) ──npm run tauri build──▶ 安装包(带饭盒的菜,端走就能吃)

本章把三道关卡全走一遍,顺便处理发布路上两件最容易出的事故:改错 identifier 数据"失踪",和dev 正常 build 白屏。

先做一个小预言,走完本章你来对答案:打包成功后,你会得到两个都能"双击安装"的文件(.msi和.exe),很多人以为它们是"同一个东西的两种皮肤"——不完全对,它们内部其实是两套不同的安装机制;而你装完之后,全世界会同时存在三份 EngFlow:安装包(送人的外卖)、Program Files 里的程序(饭店)、%APPDATA%里的数据(你打包带走的剩菜)。三份里,只有第三份是你的。这个"三份论"会在 27.4 和 27.6 反复救你的命。

【配图说明:三段流水线。第一段画源码文件夹进"vite"烤炉出 dist 盒;第二段画 dist 进"Tauri"饭盒出 msi/exe;第三段画一个 U 盘把 exe 递给别人】

27.2 原理:dist 是什么,bundle 又是什么

第一关:npm run build——检查 + 装箱

打开package.json,scripts 里那一行你可能早就眼熟(第 5 章见过一面):

"build":"vue-tsc --noEmit && vite build"

它是两个命令用&&串起来的:前一个成功了,后一个才执行。像机场安检:vue-tsc是安检员,vite build是登机口。

  • vue-tsc --noEmit:TypeScript 检查器(第 12 章的老朋友)。它把全部.ts/.vue里的类型重新审一遍——有没有把string塞进number、有没有访问不存在的字段——只报告,不产出文件(--noEmit的意思就是"别输出,查完拉倒")。为什么发布前非要过这道安检?因为 dev 模式下 Vite 是"用到才翻译",有些从没被点到的页面,类型错误会一路潜伏;而运行时的小毛病可能悄悄写坏数据。发布版要给所有人用,必须全量体检一次。
  • vite build:把散在src/里的几十个文件,编译、压缩、合并成dist/里少数几个"上线专用"文件。

跑完之后我们在项目里实测的输出(真实数字):

vite v8.3.1 building client environment for production... ✓ 54 modules transformed. rendering chunks... computing gzip size... dist/index.html 0.49 kB │ gzip: 0.35 kB dist/assets/index-B5L7jvuz.css 41.59 kB │ gzip: 8.54 kB dist/assets/dist-js-BAnW1I5v.js 3.36 kB │ gzip: 1.24 kB dist/assets/index-ob2WvhM4.js 142.37 kB │ gzip: 55.58 kB ✓ built in 711ms

三个看点:

  1. 每个文件跟着两列大小:前一个是文件实际大小,后一个gzip是"网络打包后"的大小——浏览器传输前会先压一遍。主程序 js 142.37 kB,压完只剩 55.58 kB,压缩比接近 3:1。
  2. 0.71 秒、54 个模块:我们的全部 Vue 源码被炼成一个 142 kB 的 js——第 7 章那些组件在产物里已经没有了"文件边界",全成了函数。
  3. dist/里还有一个 1.95 MB 的gre-bank.json——注意它没出现在上表里,因为它不走打包,是public/目录原样复制过来的静态资源。还记得第 19 章的懒加载吗?词库故意不进主包:软件一打开只下 55 kB,等用户真去背 GRE 词时才取那个 1.95 MB。构建输出再次印证了设计——这是读构建日志的乐趣。

顺便建立一把"大小感觉尺":55.58 kB 是什么概念?一张手机照片大约 2000 kB——EngFlow 的整个主程序,比一张照片还小四十倍。CSS 那 8.54 kB 是第 2 章三件套里"衣服"的全部家当。而 41.59 kB 的 css 压到 8.54 kB,压缩比接近 5:1——样式表里全是重复的颜色名和属性名,gzip 最爱这种"重复话"。以后看到构建日志,先问两个问题:大的东西该不该大?小的东西为什么小?能回答这两问,你就在"读"构建,而不是"跑"构建。

vue-tsc 万一拦下错误怎么办?别慌,它的报错格式第 5 章见过世面:文件路径、行号、期望类型 vs 实际类型,三行定罪。九成报错长得像"你把 string 塞给了 number"——第 12 章练习题里的老熟人。修它,重新 build;不修好,dist 不会更新,Tauri 也不会替你打包一份"没通过安检的菜"。

第二关:npm run tauri build——套上 Rust 饭盒

dist/是一套"网页文件",双击dist/index.html也就能开个网页,没有桌面图标、没有窗口标题栏设置、卸载也不干净。差的就是那层盒子。

npm run tauri build干的事:把tauri.conf.json里配置的窗口、图标、产品名交给 Rust 编译器,编译出一个真正的 Windows 程序,再把dist/整个塞进 exe 肚子里——最终产物是安装程序,双击安装后:开始菜单有图标、卸载面板有名字、数据有专属目录。

所以三层关系,一句话钉死:

dev 是厨师边炒边尝,dist 是炒好的菜,bundle 是装盒贴标的外卖。送人,永远送盒子。

再把 dev 和 build 的差别摆成一排,以后见到"dev 行 build 不行"的事故,这一排字就是诊断手册:

npm run dev(试吃)npm run build(出餐)
谁在跑代码Vite 开发服务器(localhost:1420)现场翻译提前全部编译好的静态文件
改一行代码立刻热更新必须重新 build
TypeScript 类型错可能照跑不误先被 vue-tsc 拦下
import 路径大小写Windows 下宽容严格,错了就找不到
绝对路径引用本机碰巧能通到别人电脑上必断
体积不关心(本机)关心(所以有 gzip 数字)

一句话读表:dev 的环境处处偏向你,build 的世界只尊重规则。这就是 27.6 节白屏事故的总根源。

27.3 回到 EngFlow:逐项精读 tauri.conf.json

软件的"出生证明"就一页纸:src-tauri/tauri.conf.json。全文 39 行,我们分三块逐栏读。

块一:身份证区

{"$schema":"https://schema.tauri.app/config/2","productName":"EngFlow","version":"0.1.0","identifier":"com.engflow.app",
  • productName:产品名。决定窗口标题、安装包文件名、控制面板"卸载列表"里显示什么。

  • version:版本号,含义见 27.5 小课堂。

  • identifier:identifier 是软件的身份证号,全世界它必须唯一,格式约定像倒写的网址(com.公司名.软件名)。这一栏是整张证明上唯一 dangerous 的格子,因为操作系统按它给软件分抽屉:EngFlow 的学习数据存在

    C:\Users\你\AppData\Roaming\com.engflow.app\engflow.json

    改了 identifier = 换一个新抽屉:软件从此去新抽屉存取,旧抽屉里的心血原封不动,但再也"看不见"。27.6 节的惊魂事故就在这一格。

顺便认一认"抽屉家族"——以后你在电脑里找各种软件的数据,都按这张地图找:

%APPDATA% (= C:\Users\你\AppData\Roaming) ← 漫游区:软件的主要数据。EngFlow 的家 %LOCALAPPDATA% (= ...\AppData\Local) ← 本地区:缓存、临时件(体积大、不跟着账户漫游)

Windows 给每个账户准备这两个平行区域,Tauri 的 plugin-store 默认把engflow.json放进了漫游区的 identifier 文件夹里。有的软件还会多开一层子文件夹(比如数据存储\),规矩都一样:identifier 在哪,数据就在哪。

另外那一行"$schema"也别忽略:它指向官方说明书,告诉编辑器"这个 json 该有哪些栏、什么类型"。有它在你改配置时 VS Code 会给你补全和红线提示——让机器帮你检查配置,永远比肉眼靠谱,这是全书反复出现的习惯(还记得 tsconfig 吗?同一招)。

块二:建造流程区

"build":{"beforeDevCommand":"npm run dev","devUrl":"http://localhost:1420","beforeBuildCommand":"npm run build","frontendDist":"../dist"},

四行两对,恰好对应第 1 章说的"盒子里住着一个浏览器":

  • 开发时(tauri dev):盒子先替你跑npm run dev,然后窗口去加载http://localhost:1420——对,端口 1420 的老熟人,原来登记在这里。
  • 发布时(tauri build):先自动跑npm run build(安检+装箱),再去../dist取成品塞进安装包。这就是为什么你从没手动跑过 build,tauri build 也能产出新界面——beforeBuildCommand替你跑。

块三:窗口与出厂包装区

"app":{"windows":[{"title":"EngFlow · 英语学习工作台","width":1200,"height":800,"minWidth":900,"minHeight":620,"resizable":true,"center":true}],"security":{"csp":null}},"bundle":{"active":true,"targets":"all","icon":["icons/32x32.png","icons/128x128.png","icons/128x128@2x.png","icons/icon.icns","icons/icon.ico"]}}
  • 窗口:打开时 1200×800;minWidth/minHeight是"缩得最小也不能更小"的底线——再小,卡片按钮就会挤成一团。center: true让窗口在屏幕正中出生,体面。
  • security.csp:网页安全策略,我们暂时设为null全放行。EngFlow 不联网、不加载远程脚本,风险面极小;等第 28 章真要接 AI 接口时,这一格值得重新审查——把它记进"已知待办",这正是第 26 章教的习惯:查过、暂不动、写下来。
  • bundle.targets: "all":给每种该平台能吃的格式都出一份——Windows 上是.msi和.exe两种安装包。
  • icon五连:32/128/128@2x png 管窗口和任务栏,.ico管 Windows,.icns管 Mac——一套源图,多尺寸输出,各平台各取所需。这就是前面反复叮嘱"图标别马虎"的原因:图标是软件的脸。

【配图说明:一张"出生证明"表单样式图,三块区域用彩笔圈出:身份证区(productName/version/identifier)、建造流程区(build 四行)、包装区(app/bundle),identifier 格子画一个红色警示三角】

27.4 动手时间:打包、安装、搬家,一条龙

第 1 步:dist 出炉(2 分钟)

PS D:\WorkSpace\CET6\learnEnglish>npmrun build

你会看到:先是vue-tsc默默跑十几秒(没有消息就是好消息,有错误它会逐条列出行号),然后 vite 打出 27.2 节那份大小表,最后✓ built in 660ms左右。用资源管理器打开dist\:index.html、assets 里三个带乱码后缀的文件、还有原样躺着的 gre-bank.json。

那个"乱码后缀"值得解释一句:index-ob2WvhM4.js中间那串ob2WvhM4是文件内容的指纹(第 18 章哈希的又一次出场!)。内容变一个字,指纹就换一撮字母;内容没变,指纹不变。为什么要这样?浏览器会缓存旧文件,如果文件名不变,用户可能永远拿不到新版;文件名一换,浏览器见没见过,必去服务器取新的。缓存和更新这对冤家,全靠文件名里的哈希握手言和。所以记住:dist/里的文件不要手动改,也不要给同学发你手改过的 dist——永远发"刚 build 出来的"。

顺带认识一位新朋友:第一次 build 时日志里可能闪过dist-js-BAnW1I5v.js这样一个几 kB 的小块——那是 Tauri 的插件代码被自动代码分割(code splitting)出去了:不常用的东西切成小包,用到才加载,主包因此瘦身。Vite 自己会做这个决定,你一行配置都不用写。

第 2 步:套盒(一次漫长的等待)

PS D:\WorkSpace\CET6\learnEnglish>npmrun tauri build

你会看到:屏幕开始滚动 Rust 的编译进度,几十行、几百行,持续好几分钟,第一次甚至要 20-40 分钟——它正在把 Tauri 用到的上百个 Rust 库(crate)从网上下载下来,一个字母一个字母地编译成机器码,而且用的是"release 全力度优化"模式。

这里要做一次耐心教育:Rust 的 release 编译慢,是这门语言的交易——它用编译期的漫长,换运行期的飞快和安全(第 1 章说过 Tauri 的盒子是 Rust 打的,这就是盒子的工费)。看到进度条爬得慢,别慌、别强制关机,去喝杯牛奶,或者拿这二十分钟把 27.5 的备份先做了。第一次之后增量编译会快很多,但每次改了 Rust 侧配置,它还是会认真地重新烤。

顺便参观一下工地:src-tauri\里除了 tauri.conf.json,还有Cargo.toml(Rust 世界的 package.json——依赖清单,管 Rust 盒子用哪些 crate)、icons\(源图,五条 icon 配置的真实出处)、capabilities\(权限清单:这个盒子允许网页侧调用哪些系统能力,第 13 章 plugin-store 的读写权限就登记在这里),以及编译时新建的target\——整个 target 都是 Rust 的"厨房废料加半成品",大到几个 GB 也随时可删,和 dist 一样永远不进版本管理(src-tauri\.gitignore里它就以/target/这一行在册)。

烤的过程中你会看到几百行Compiling xxx v1.2.3加一堆 warning——warning(黄色警告)不是 error(红色错误):warning 意思是"能跑,但我看着不对劲",Rust 编译器是全书我们遇到的最啰嗦也最负责的安检员,它连你写了个没用的变量都要提醒。红色的 error 出现时构建才会停,而且它报得比 vue-tsc 还细,照着小节建议改即可。

第 3 步:开盒验货

烤完后,去这里领产物(路径里的版本号随version变):

src-tauri\target\release\bundle\msi\EngFlow_0.1.0_x64_zh-CN.msi src-tauri\target\release\bundle\nsis\EngFlow_0.1.0_x64.exe

msi 和 exe 都是安装程序:msi 偏"单位统一装机"(学校机房管理员爱它,可以用命令一次装五十台),exe 双击安装更顺手,发给朋友用后者。它们连"进度条"都是两套代码画的——这就是 27.1 预言里"不是同一东西换皮肤"的意思。挑一台"干净电脑"验证——没有装过 Node、没有这个项目的任何源代码的那台(没有第二台?就在自己电脑上新建一个 Windows 本地用户,切换过去装)。"干净"这两个字值千金:你自己的开发机装着 Node、缓存着一切、路径里全是项目痕迹,它在场,测试就不算数。这跟第 1 章"快捷方式、exe、源码"三分是同一课——测试软件,要测的是它离开你之后的样子。

验收单四勾:

  1. 双击安装,开始菜单出现EngFlow图标;
  2. 打开窗口,标题"EngFlow · 英语学习工作台",初始大小 1200×800、拉到很小时在 900×620 卡住(conf 生效);
  3. 收藏一个panda,关掉再打开——还在(数据写进了这台机器的新抽屉);
  4. 控制面板能正规卸载,卸载后%APPDATA%\com.engflow.app还保留着数据(卸载删程序、不删学习记录,这是为用户负责,呼应第 1 章"符号、本体、原料"三分)。

四勾全过之后,再加三个"出厂三问":

  • 问体积:安装完 Program Files 里多大?(几十 MB——别忘了 exe 肚子里揣着整个 dist,1.95 MB 的词库也在其中。)
  • 问数据:新装的软件在%APPDATA%下建没建com.engflow.app?没建说明没写到文件,可能掉进了"白屏但其实没启动成功"的坑(27.6 事故二)。
  • 问图标:桌面和任务栏的图标清晰吗?发糊通常是 png 尺寸不全(conf 的 icon 五连少了一栏)。

三问都答得上来,这份 bundle 才算"出厂"。

【配图说明:一份"三份论"家谱图。顶端一个 exe 安装包画成外卖盒(标注"送人的,装完就功成身退"),箭头指向中间 Program Files 里的饭店(“程序本体,卸载就拿走”),再一个箭头指向第三份——%APPDATA% 里贴着封条的 engflow.json(“你的学习记录,唯一真正属于你的那份”);第三条箭头描最粗,旁边画一颗小星星】

第 4 步:备份你的学习记录——搬家带走大脑

现在做发布章最重要的实操。你的全部学习记录——卡片进度、连续打卡、收藏的词、最近 60 天历史——就是第 13 章挖到的那个文件:

%APPDATA%\com.engflow.app\engflow.json

(地址栏粘贴%APPDATA%回车就到。)备份只要一步:

PS>Copy-Item"$env:APPDATA\com.engflow.app\engflow.json""D:\我的备份\engflow-$(Get-Date-FormatyyyyMMdd).json"

把副本放进网盘或 U 盘,换电脑、重装系统之后,把文件复制回原位,启动 EngFlow——三个月的复习进度原地复活。原理第 13 章就学过:软件只是菜谱,数据才是你真正在"用"的东西;菜谱随便重装,数据必须备份。

恢复是一门手艺,练一遍才算会。现在就演练:复制一份 engflow.json 到桌面 → 删掉原文件 → 打开软件(它应该给你一份全新的空档)→ 把桌面的副本放回去 → 再打开——panda 和全部打卡记录回来了。全程一分钟。没演练过的备份等于没有备份:真到搬家那天,你会在"放回去之后会不会崩"面前发抖。也建议每月把带日期的副本存进网盘一份——它比照片小一万倍,却记录着你真金白银的时间。(也可以直接把这个 json 发给另一台已装好的电脑导入,自己实现"导入"界面是第 28 章的开放挑战之一。)

27.5 版本号小课堂

0.1.0——三段数字,学名叫语义化版本(SemVer),规矩是:

位置名字什么时候 +1例句
第 1 位0主版本(大改)产品脱胎换骨、老存档可能不兼容从背单词软件升级成学习平台 →1.0.0
第 2 位1次版本(新功能)加了新页面、新字段,老用户照常用上线语法模块 →0.2.0
第 3 位0补丁(修 bug)只修问题不加功能修好连点丢分 →0.1.1

我们停在0.1.0是有讲究的:第一位是 0,等于挂牌"试用期"——数据结构随时可能改,请用户别把兼容性当承诺。等第 28 章把 Phase 4 做完、字段稳定了,就该升1.0.0——那是软件的"成年礼"。记住口诀:大改动第一位,加菜动第二位,补漏动第三位;后两位归零规则(升 0.2.0 时第三位必须回到 0)顺手就懂了。

版本号改哪儿?两处要同时改,少一处就会出现"装的软件说自己是 0.1.0、安装包文件名写着 0.1.1"的怪事:

package.json "version": "0.1.0" ← js 世界这边 src-tauri\tauri.conf.json "version": "0.1.0" ← Rust 盒子那边

两处不一致时以tauri.conf.json为准——安装包名和"关于"页看的是它。所以养成习惯:升版本一口气改两处,第 26 章的"两把尺子"教训在版本号上完全适用。

顺便把三件东西的分工钉牢,这是本章的"出厂三问":

归谁管什么时候动它
productName: "EngFlow"给人看的名字(标题栏/卸载列表)市场说要改名,改
version: "0.1.0"发布节奏(大/中/小)每次发布,动对应位
identifier: "com.engflow.app"数据的门牌号永不。它不属于改名自由,它属于用户的数据

最后一行请读两遍:改名自由是程序的自由,门牌号是用户的数据——程序没有权力动用户的门牌号。这也是为什么老软件可以改产品名,却极少改 identifier:那等于宣布全体失忆。

27.6 小毛病大修理

事故一:改了 identifier 之后,"数据全没了"惊魂 48 小时

事故现场:发布前夜,同学看着com.engflow.app说"不像个网址,我改成com.engflow.desktop更工整"。两分钟后他打来电话,声音发抖:"我的词没了,panda 没了,报告全是零,EngFlow 把我当新用户了!软件是不是把数据删了?!”

真相:数据一个字节都没丢。第 27.3 节说过:identifier 决定抽屉。抽屉名一改,软件去com.engflow.desktop这个新抽屉找数据——当然是空的,于是给你一份默认档;三个月的心血好好地躺在旧抽屉com.engflow.app里睡大觉,只是没人去开。

新抽屉为什么是"空"的?还记得第 13 章loadData()的剧本吗——拿不到数据不是错误,是"还没有数据":软件会客客气气地发一份DEFAULT_DATA(空卡片、空历史、空收藏)继续运行。这个设计平时是优点(新用户零配置即用),惊魂夜成了吓人的帮凶:它演得太像"数据被删了"。所以排查这种"失踪案",第一条线索永远是去%APPDATA%看一眼:真丢了,是没有文件的;没丢,文件安安静静躺在某个旧名字的抽屉里。空软件是"空壳子",旧壳一开,满壳是宝。

找回方法(当时执行的完整步骤):

  1. 关掉软件;
  2. 打开%APPDATA%,能看到两个抽屉并排:com.engflow.app和com.engflow.desktop;
  3. 把旧抽屉里的engflow.json复制进新抽屉(或者一劳永逸:把 conf 里的 identifier 改回旧值);
  4. 启动——panda 回来了,连复习到期日都分毫不差。

立案规则:identifier 是出厂即终身的一栏——它是地址,不是装饰。以后任何重构、改名、换图标,都别碰它;真需要改名,产品名可改,identifier 必须保留,否则等于要求所有用户集体失忆。这一条我们写进了项目备忘,也请你写进自己的第一行"发布纪律"。

事故二:dev 一切正常,build 之后白屏

事故现场:另一类经典——打包完的 exe 打开是一个纯白窗口,dev 模式却好好的。

白屏说明网页根本没跑起来,两个最常见的原因:

  1. 路径大小写不一致:代码里写import Dashboard from './components/dashboard.vue',实际文件叫Dashboard.vue。Windows 文件系统粗线条,大小写不敏感,dev 照样跑;可vite build和 Linux 打包机是认真的人,找不到dashboard.vue就把模块丢了,运行时一碰面就白屏。教训一句话:dev 是宽待你的老师,build 是验收你的考官。
  2. 资源用了绝对路径:页面里写<img src="D:/WorkSpace/.../cover.png">或者fetch('http://localhost:1420/gre-bank.json')这类"只有我这台机器才认"的地址。dev 跑在你电脑上,碰巧灵;装到小雅表哥电脑上,D 盘根本没有那个文件夹,请求失败,首屏脚本一崩,全家白屏。正确姿势是相对路径加 public:fetch('gre-bank.json')(我们的bank.ts就是这么写的)。

排查步骤(四步定位法,按顺序,一步一刀):

第 1 步:npm run preview —— 不走 Tauri,本地 http 服务器直接开 dist 白屏?→ 问题在 dist(前端产物),继续第 2 步 正常?→ 问题在 Tauri 侧(conf 的 frontendDist 指错?dist 是旧的?) 第 2 步:浏览器 F12 → Console 看红字、Network 看 404 404 的文件名大小写不对 → 原因 1;404 的是外部绝对地址 → 原因 2 第 3 步:修源码 → 重新 npm run build → 再 preview 确认 第 4 步:最后才重新 tauri build(Rust 侧没改动时,它其实只重装箱)

第 1 步的npm run preview是本章最值得带走的一招,它就是"先尝一口再装盒":不启动桌面软件、不等漫长的 Rust,用浏览器直接看 dist 跑得对不对,几秒钟出结论。能把大问题切成两半的工具,永远比能解决大问题的工具更常用。

90% 的"dev 行 build 不行",都栽在大小写和绝对路径这两个路径问题上。剩下的 10% 里,最常见的是"dist 是旧的"——忘了重新 build 就 tauri build,盒子里装的还是昨天的菜(好在beforeBuildCommand这道自动流程让这类事故少了一大半,但手动折腾过 dist 的人都懂)。而第 1 步那招(把盒子拆开单独验菜)是通用思维:产物独立验,能一下子把"网页的锅"和"盒子的锅"分开——以后无论修什么软件,先找到那条"把大问题切成两半"的缝。

发布纪律最终浓缩成三句,请抄在你项目的 README 末尾:

① identifier 终身不改;② 版本号两处同改;③ 每次发布前做一次 27.4 的恢复演练。

27.7 本章你会解释

  1. dist 和 bundle 的区别是什么,谁是最终送人的那份?(dist 是编译装箱好的网页文件;bundle 是套上 Tauri 盒子的安装包,送人用 bundle)
  2. npm run build里&&前后分别是谁?谁失败了后面就不跑?(vue-tsc 安检 / vite build 装箱;安检不过就不装箱)
  3. identifier 是干什么的?为什么"永世不改"?(软件身份证号,决定数据目录;改了=换抽屉,旧数据看不见)
  4. 学习记录备份要拷哪个文件、放在哪?(%APPDATA%\com.engflow.app\engflow.json)
  5. 版本号0.1.0里那个0在向用户承诺什么?(试用期,数据结构还可能大改,别当 1.0 依赖)
  6. "dev 正常 build 白屏"两个常见原因是什么,第一步排查命令是什么?(大小写路径 / 绝对路径资源;npm run preview)

27.8 练习

  1. ★ 热身填空:合上书,把"三道关卡"默写出来——源码 ──( )──▶ dist ──( )──▶ 安装包;再默写数据文件的完整路径(从%开始写)。写不出就回 27.1 和 27.4,这两处是本章的地基。

  2. ★ 完整跑一遍npm run build,把构建输出的大小表抄下来,找出:哪个文件最大?它为什么没被 gzip 那几行列出?(gre-bank.json,静态资源原样复制不走打包)

  3. ★★ 把 27.4 第 3 步的"验收单四勾"做成一张纸质清单,请一位家人当"验收员",在打包版里逐项操作并签字。体验一下:用户拿到的永远是最终产品,你的环境帮不了他。

  4. ★★★ 思考题:如果两位用户各自改了engflow.json备份,现在要把两份合并成一份,会发生什么难处?(提示:第 25 章——两份都改过的"点名册",谁覆盖谁?这就是第 28 章"多设备同步"候选里"最大风险"一栏的答案预告。)


全书正文到这里就讲完了"怎么做出来"。但一个真正的工程师,最后要回答的问题是:接下来做什么。最后一章没有标准答案——那是留给你自己的毕业设计。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 15:11:14

3.java运算符

算术运算符 算术运算符是对数值型的变量进行运算的。 常用算术运算符所以 运算符在java中表示三中含义&#xff1a;正号、加、字符串连接。/ % 运算符 public class SuanshuYsf {public static void main(String[] args){//除法System.out.println(10 / 4); //从数学来看是2.5…

作者头像 李华
网站建设 2026/10/18 15:09:48

微信小程序源码二次开发实战:从Mock数据到请求封装

简介&#xff1a;这份源码合集收录了100个微信小程序项目的完整代码&#xff0c;面向初学小程序开发或希望快速参考实战案例的开发者。内容涵盖基础组件、页面生命周期、数据绑定、wx.request网络请求及本地存储等核心知识点&#xff0c;并涉及地图、支付、分享等常见高级功能&…

作者头像 李华
网站建设 2026/10/18 15:08:51

AI辅助论文写作全流程指南:从选题到答辩的10个平台方向

每年到这个时间段&#xff0c;办公室门口总会蹲着一批愁毕业论文的专科生。问的问题翻来覆去就那几个&#xff1a;题目定不下来怎么办、文献看不懂怎么办、写出来的东西像流水账怎么办、查重过不了怎么办。今年被追问得最多的是“AI工具到底怎么用”。说实话&#xff0c;AI辅助…

作者头像 李华
网站建设 2026/10/18 15:06:42

Delphi Berlin 下 Raize 6.1.1.12 DX10.1 安装与避坑指南

简介&#xff1a;Raize 6.1.1.12 DX10.1 Berlin 修正版面向使用 CBuilder 10.1 Berlin 的 Delphi/C 开发者&#xff0c;针对原版组件包中 pas 文件报错导致编译失败的问题做了修复&#xff0c;并已调整好配置文件&#xff0c;解压至 C:\Program Files\Raize\ 后执行 RC6\Source…

作者头像 李华
网站建设 2026/10/18 15:05:05

蛋白质建模 PyRosetta 安装指南:wheel、源码编译与避坑要点

简介&#xff1a;一份面向蛋白质结构预测与分子对接研究者的Pyrosetta安装指南代码包&#xff0c;聚焦在Python环境中顺利部署Rosetta官方Python接口。Pyrosetta本身是Rosetta的Python化封装&#xff0c;使用者无需深入掌握Rosetta底层实现&#xff0c;便可通过脚本完成蛋白质折…

作者头像 李华
网站建设 2026/10/18 15:04:43

KSQL Developer实测:打通Hive、Spark SQL与Impala的多引擎SQL开发体验

做大数据SQL开发的人&#xff0c;一定受够了在命令行或者几个客户端之间来回切换的苦。Hive、Impala、Spark SQL&#xff0c;每换一个引擎就要换一套工具&#xff0c;元数据看不了&#xff0c;格式化一塌糊涂&#xff0c;写个长一点的ETL脚本全靠眼睛硬扛。所以我这次集中测了下…

作者头像 李华