merge: tuanwei-uniapp 切换到命令行构建(uni-app CLI 工程)
- 集成分支 feat/cli-migration 整体并入 master;此后 HBuilderX 不再是本仓库的构建方式 - 7 张票全部 resolved(.scratch/uniapp-cli/);产物 app.json / 分包 / tabBar / appid 与迁移前逐项一致,业务代码零改动 - 产物:pnpm build:mp-weixin → dist/build/mp-weixin,用微信开发者工具导入该目录 - 回滚:git revert -m 1 <本合并提交>;口径与取舍见 docs/adr/0009-uniapp-built-by-cli-not-hbuilderx.md - 未做:微信开发者工具人工冒烟(清单见 .scratch/uniapp-cli/issues/03-artifact-parity-and-smoke-checklist.md)
@@ -1,4 +1,5 @@
|
||||
node_modules/
|
||||
dist/
|
||||
unpackage/
|
||||
.hbuilderx/
|
||||
.DS_Store
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# tuanwei-uniapp
|
||||
|
||||
团员管理系统移动端(uni-app + Vue 3)。**本仓库是标准 uni-app Vite CLI 工程:命令行即可构建,不需要 HBuilderX。**
|
||||
|
||||
## 环境要求
|
||||
|
||||
| 依赖 | 实测版本 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Node.js | v22.23.3 | 构建用 |
|
||||
| pnpm | v12.11.2 | **唯一包管理器**,不要用 npm / yarn |
|
||||
| 微信开发者工具 | — | 只用来预览产物,不参与构建 |
|
||||
|
||||
npm 源使用官方 `registry.npmjs.org`。
|
||||
|
||||
## 快速开始
|
||||
|
||||
三条命令都在**仓库根目录**执行:
|
||||
|
||||
```bash
|
||||
# 1. 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 2. 日常开发:watch 构建,不退出;产物持续写入 dist/dev/mp-weixin
|
||||
pnpm dev:mp-weixin
|
||||
|
||||
# 3. 发布构建:一次性产出静态快照到 dist/build/mp-weixin
|
||||
pnpm build:mp-weixin
|
||||
```
|
||||
|
||||
`package.json` 里只有四条 scripts:`dev:h5` / `build:h5` / `dev:mp-weixin` / `build:mp-weixin`。
|
||||
**`mp-weixin` 是本仓库唯一承诺的平台**;h5 两条只是顺带保留,不作保证。
|
||||
|
||||
## 产物路径与微信开发者工具的导入目录
|
||||
|
||||
| 命令 | 产物目录 | 什么时候用 |
|
||||
| --- | --- | --- |
|
||||
| `pnpm dev:mp-weixin` | `dist/dev/mp-weixin` | 日常开发:改源码自动重编译 |
|
||||
| `pnpm build:mp-weixin` | `dist/build/mp-weixin` | 发布 / 上传前:一次性静态构建 |
|
||||
|
||||
产物路径由 uni CLI 固定为 `dist/<dev|build>/<平台>`,`dist/` 已在 `.gitignore` 中,不会进版本库。
|
||||
|
||||
**微信开发者工具 → 「导入项目」→ 目录选 `dist/dev/mp-weixin`(开发)或 `dist/build/mp-weixin`(发布构建)。**
|
||||
|
||||
- 要导入的是**产物目录本身**,也就是 `app.json`、`project.config.json` 所在的那一层;
|
||||
不要再往外选到仓库根目录,也不要再往里选一层。
|
||||
- **appid 不用手填**:`project.config.json` 由编译器生成,appid 取自 `src/manifest.json` 的
|
||||
`mp-weixin.appid`(`wxf7ee9cd5801bf7a6`),项目名取自 `manifest.json` 的 `name`。
|
||||
- 开发时先起 `pnpm dev:mp-weixin`(它进入 watch、不退出),再导入 `dist/dev/mp-weixin`。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
.
|
||||
├── index.html # H5 入口(仅 h5 构建使用)
|
||||
├── package.json
|
||||
├── pnpm-lock.yaml
|
||||
├── pnpm-workspace.yaml # pnpm 12 的 allowBuilds 白名单,见「常见问题」
|
||||
├── shims-uni.d.ts
|
||||
├── vite.config.js
|
||||
├── src/ # uni-app 源码根(官方 src/ 布局)
|
||||
│ ├── App.vue main.js manifest.json pages.json uni.scss
|
||||
│ ├── pages/ packageMine/ components/ utils/ static/ uni_modules/
|
||||
│ └── uni.promisify.adaptor.js
|
||||
└── dist/ # 构建产物(git 忽略)
|
||||
```
|
||||
|
||||
`@/` 别名指向 `src/`。**不要把源码挪回仓库根目录**:`vite.config.js` 的 `root` / `build.outDir`
|
||||
是 uni-app 官方明确不支持的,`UNI_INPUT_DIR` 是文档不背书的源码后门 —— 官方 `src/` 布局是唯一受支持的形状。
|
||||
|
||||
## 为什么不再需要 HBuilderX
|
||||
|
||||
改造前这是 HBuilderX 可视化工程:构建只能在 IDE 里点菜单完成,命令行里没有等价入口,
|
||||
**无法在 CI、脚本或别人机器上复现构建结果**。现在整个构建流程就是 `pnpm install` + `pnpm build:mp-weixin`,
|
||||
退出码 0、产物在 `dist/build/mp-weixin`,任何人在命令行都能复现。
|
||||
|
||||
改造的背景、布局 / 版本 / 包管理器的取舍、以及「绝不用 `@dcloudio` 的 `latest` tag」这条硬约束,
|
||||
记录在工作区仓库(本仓库之外)的 `docs/adr/0009-uniapp-built-by-cli-not-hbuilderx.md`。
|
||||
|
||||
`.gitignore` 里保留的 `.hbuilderx/` 与 `unpackage/` 只是为了不让旧的 IDE 配置与旧产物被误提交,
|
||||
**它们不是构建路径**,与现在的构建无关。
|
||||
|
||||
## 版本口径(硬约束)
|
||||
|
||||
- 五个编译器包(`@dcloudio/uni-app` / `uni-components` / `uni-h5` / `uni-mp-weixin` / `vite-plugin-uni`)
|
||||
**必须同一版本**,按精确版本号 pin。具体值以 `package.json` 为准。
|
||||
- `@dcloudio/types` **不受上面这条约束**:它是 IDE 用的类型定义,单独窄化到 `3.4.31`
|
||||
(`@dcloudio/uni-app` 的 strict peer,不影响构建)。
|
||||
- **绝不用 `@dcloudio` 包的 `latest` tag。** `latest` 指向 **Vue 2** 线
|
||||
(实测 `npm view @dcloudio/uni-app dist-tags` → `latest: 2.0.2-5020620260917001`),
|
||||
与 Vue 3 线同日期后缀、极易看错;Vue 3 线在精确版本号上(`vue3` tag 只给 alpha)。
|
||||
- `vite` 钉**精确 `5.2.8`**:`@dcloudio/vite-plugin-uni` 的 peer 要求精确版本,不要写 `^`。
|
||||
- 升级编译器走官方 `npx @dcloudio/uvm`(一次改全套),不要手改单个 `@dcloudio/*` 版本。
|
||||
|
||||
## 常见问题
|
||||
|
||||
**`pnpm install` 报 `ERR_PNPM_IGNORED_BUILDS`、退出码非 0**
|
||||
|
||||
pnpm 12 下依赖的构建脚本默认不执行,且 `strictDepBuilds` 默认为 `true`,
|
||||
会把「被跳过的依赖构建脚本」判成安装失败。本项目已在 `pnpm-workspace.yaml` 里用 `allowBuilds`
|
||||
显式复核(`esbuild` / `@parcel/watcher` / `core-js` / `core-js-pure`),之后
|
||||
`pnpm install --frozen-lockfile` 退出码 0(`node_modules/.modules.yaml` 里记着 `allowBuilds`、`pendingBuilds` 为空)。
|
||||
|
||||
这里只写实测到的事实(pnpm v12.11.2):生效的键是 `pnpm-workspace.yaml` 的 `allowBuilds`;
|
||||
把 `onlyBuiltDependencies` 写进 `package.json` 的 `pnpm` 字段,pnpm 12 会明确打印
|
||||
`The "pnpm" field in package.json is no longer read by pnpm`(并列出被忽略的键名),**无效**;
|
||||
写在 `pnpm-workspace.yaml` 里同样不生效(既不告警、也不执行那批构建脚本)。
|
||||
这个键究竟从哪个版本起失效,本仓库没有逐版本复现,不下版本学结论。
|
||||
|
||||
**构建输出一堆 sass `@import` / `legacy-js-api` 弃用告警**
|
||||
|
||||
这是既有 scss 写法与新版 dart-sass 的差异,告警不影响退出码,也不影响产物。
|
||||
|
||||
**H5**
|
||||
|
||||
`pnpm dev:h5` / `pnpm build:h5` 仍在 `package.json` 里,但不在承诺范围内。
|
||||
@@ -15,6 +15,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"name" : "tuanwei",
|
||||
"appid" : "__UNI__F254BAB",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wxf7ee9cd5801bf7a6",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "tuanwei-uniapp",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev:h5": "uni",
|
||||
"build:h5": "uni build",
|
||||
"dev:mp-weixin": "uni -p mp-weixin",
|
||||
"build:mp-weixin": "uni build -p mp-weixin"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "3.0.0-5020620260917001",
|
||||
"@dcloudio/uni-components": "3.0.0-5020620260917001",
|
||||
"@dcloudio/uni-h5": "3.0.0-5020620260917001",
|
||||
"@dcloudio/uni-mp-weixin": "3.0.0-5020620260917001",
|
||||
"vue": "3.4.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "3.4.31",
|
||||
"@dcloudio/vite-plugin-uni": "3.0.0-5020620260917001",
|
||||
"@vue/runtime-core": "3.4.21",
|
||||
"rollup": "4.14.3",
|
||||
"sass": "^1.77.8",
|
||||
"vite": "5.2.8"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# pnpm 12 起,依赖的构建脚本默认「不予执行」,且 strictDepBuilds 默认为 true,
|
||||
# 会把安装判成非零退出(ERR_PNPM_IGNORED_BUILDS)。这里显式复核这 4 个包。
|
||||
# 说明(均为 uni-app 官方依赖树的传递依赖):
|
||||
# esbuild —— vite 的打包器,postinstall 校验平台二进制
|
||||
# @parcel/watcher—— 原生文件监听(dev watch 用)
|
||||
# core-js / core-js-pure —— 仅打印赞助信息,无构建产物
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
'@parcel/watcher': true
|
||||
core-js: true
|
||||
core-js-pure: true
|
||||
@@ -0,0 +1,10 @@
|
||||
/// <reference types='@dcloudio/types' />
|
||||
import 'vue'
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
type Hooks = App.AppInstance & Page.PageInstance;
|
||||
|
||||
interface ComponentCustomOptions extends Hooks {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name" : "tuanwei",
|
||||
"appid" : "__UNI__F254BAB",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
"mp-weixin" : {
|
||||
"appid" : "wxf7ee9cd5801bf7a6",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |