mp-weixin-back 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mp-weixin-back",
3
3
  "type": "module",
4
- "version": "0.0.16",
4
+ "version": "0.0.18",
5
5
  "description": "Vite plugin to intercept back navigation (gesture back & navbar back) in WeChat miniprogram (mp-weixin) built with uni-app + Vue 3. 监听微信小程序的手势返回和页面默认导航栏的返回",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -38,6 +38,11 @@
38
38
  "types": "./client.d.ts"
39
39
  }
40
40
  },
41
+ "files": [
42
+ "dist",
43
+ "client.d.ts",
44
+ "README.md"
45
+ ],
41
46
  "author": "DBAAZzz",
42
47
  "license": "ISC",
43
48
  "repository": {
@@ -45,7 +50,6 @@
45
50
  "url": "git+https://github.com/DBAAZzz/mp-weixin-back.git"
46
51
  },
47
52
  "dependencies": {
48
- "@babel/generator": "^7.26.2",
49
53
  "@babel/parser": "^7.26.2",
50
54
  "@babel/traverse": "^7.25.9",
51
55
  "ast-kit": "^1.3.1",
@@ -61,22 +65,29 @@
61
65
  "*": "prettier --write"
62
66
  },
63
67
  "devDependencies": {
68
+ "@babel/types": "^7.26.0",
64
69
  "@changesets/cli": "^2.29.8",
65
- "@types/babel__generator": "^7.6.8",
70
+ "@types/babel__traverse": "^7.20.6",
66
71
  "@types/node": "^22.9.3",
67
72
  "@vitejs/plugin-vue": "^5.2.0",
73
+ "@vue/compiler-sfc": "^3.5.13",
68
74
  "@vue/test-utils": "^2.4.6",
69
75
  "happy-dom": "^15.11.6",
70
76
  "typescript": "^5.7.2",
71
77
  "unbuild": "^2.0.0",
78
+ "vite": "^5.4.11",
72
79
  "vitest": "^2.1.5",
73
80
  "vue": "^3.5.13"
74
81
  },
75
82
  "scripts": {
76
83
  "build": "unbuild",
77
84
  "test": "vitest",
85
+ "test:run": "vitest run",
86
+ "typecheck": "tsc --noEmit",
87
+ "check-publish": "node scripts/check-publish.mjs && pnpm publish --dry-run --no-git-checks",
78
88
  "changeset": "changeset",
79
89
  "version": "changeset version",
80
- "release": "pnpm build && changeset publish"
90
+ "release": "pnpm run version && pnpm typecheck && pnpm test:run && pnpm build && pnpm check-publish && pnpm publish --access public --no-git-checks",
91
+ "release:dry": "pnpm build && pnpm check-publish"
81
92
  }
82
93
  }
package/readme.md CHANGED
@@ -54,12 +54,19 @@ export default defineConfig({
54
54
  debug: false, // 调试模式,默认为 false
55
55
  onPageBack: ({ page }) => {
56
56
  console.log('返回事件触发,当前页面:', page)
57
- }, // 全局钩子,任意页面触发时执行
57
+ }, // 全局钩子,任意页面触发时执行。⚠️ 该函数会被序列化注入页面,必须自包含(不能引用 vite.config.ts 中的变量或 import 的模块)
58
+ pageContainer: {
59
+ zIndex: 1, // 注入的 page-container 的 z-index,默认 1
60
+ overlay: false, // 是否显示遮罩,默认 false
61
+ duration: false, // 动画时长(ms),默认 false 关闭
62
+ },
58
63
  }),
59
64
  ],
60
65
  })
61
66
  ```
62
67
 
68
+ > 插件会自动探测 `src/pages.json`(CLI 项目)或根目录 `pages.json`(HBuilderX 项目);多端构建时仅在 `UNI_PLATFORM=mp-weixin` 下生效,其他平台自动降级为 no-op。
69
+
63
70
  ## 🚀 快速开始
64
71
 
65
72
  ### 基本使用
@@ -133,6 +140,8 @@ onPageBack(
133
140
  | `frequency` | `number` | `1` | 阻止次数 |
134
141
  | `initialValue` | `boolean` | `true` | 是否立即启用监听(设为 `false` 时需手动调用 `activeMpBack()`) |
135
142
 
143
+ > ⚠️ 这些配置在**构建期静态读取**,必须直接写布尔/数字字面量(如 `{ frequency: 3 }`),不能传变量或表达式。需要运行时动态控制时请使用 `activeMpBack()` / `inactiveMpBack()`。
144
+
136
145
  ### 辅助方法
137
146
 
138
147
  #### `activeMpBack()`
@@ -167,33 +176,55 @@ onPageBack(
167
176
  | ---------------- | ------------------------------------------- | ------- | -------------------------- |
168
177
  | `preventDefault` | `boolean` | `false` | 全局阻止默认返回行为 |
169
178
  | `frequency` | `number` | `1` | 全局阻止次数 |
179
+ | `initialValue` | `boolean` | `true` | 全局是否立即启用监听 |
170
180
  | `debug` | `boolean` | `false` | 开发模式下开启调试日志 |
171
- | `onPageBack` | `(params: { page: string }) => void` | — | 全局回调,任意页面触发执行 |
172
-
173
- ## 🎯 选项式 API 支持(未完善)
181
+ | `onPageBack` | `(params: { page: string \| null }) => void` | — | 全局回调,任意页面触发执行。必须自包含(会被序列化注入页面,闭包变量运行时不可用,检测到时构建期会警告) |
182
+ | `pageContainer` | `{ zIndex?, overlay?, duration? }` | 见上文 | 注入的 page-container 组件属性 |
174
183
 
175
- 组件内直接声明
184
+ ## 🎯 选项式 API 支持
176
185
 
177
- 在 Vue 组件的选项对象中直接定义 onPageBack 方法:
186
+ 在 Vue 组件的选项对象中直接定义 `onPageBack`,支持三种写法:
178
187
 
179
188
  ```html
180
- <template>
181
- <div class="container">
182
- <div>当前页面内容</div>
183
- </div>
184
- </template>
185
-
186
189
  <script>
187
190
  export default {
188
- // 读取 vite 中的配置
191
+ // 写法一:方法简写(使用 vite 中的全局配置)
189
192
  onPageBack() {
190
193
  console.log('检测到返回操作')
191
- // 业务逻辑处理
192
194
  },
193
195
  }
194
196
  </script>
195
197
  ```
196
198
 
199
+ ```html
200
+ <script>
201
+ export default {
202
+ // 写法二:函数属性
203
+ onPageBack: function () {
204
+ console.log('检测到返回操作')
205
+ },
206
+ }
207
+ </script>
208
+ ```
209
+
210
+ ```html
211
+ <script>
212
+ export default {
213
+ // 写法三:对象写法,支持页面级配置(与 composition API 对齐)
214
+ onPageBack: {
215
+ preventDefault: true,
216
+ frequency: 3,
217
+ initialValue: true,
218
+ handler() {
219
+ console.log('检测到返回操作')
220
+ },
221
+ },
222
+ }
223
+ </script>
224
+ ```
225
+
226
+ 回调中的 `this` 指向组件实例,可直接访问 `data` / `methods`。
227
+
197
228
  ## 🛠 类型支持
198
229
 
199
230
  ### 类型声明配置
@@ -227,7 +258,8 @@ onPageBack(
227
258
 
228
259
  ### Q3: 不生效怎么排查?
229
260
 
230
- 1. 确认 `src/pages.json` 存在且格式正确
231
- 2. 确认是页面级 `.vue` 文件(非组件)
232
- 3. 开启 `debug: true` 查看插件日志
233
- 4. 确认 `@vue/compiler-sfc` 已安装:`pnpm add -D @vue/compiler-sfc`
261
+ 1. 确认 `src/pages.json` 或根目录 `pages.json` 存在且格式正确
262
+ 2. 确认是 `pages.json` 中注册的页面级 `.vue` 文件(组件中使用不会注入,dev 下运行时会有 console 警告)
263
+ 3. 多端项目确认构建平台为 `mp-weixin`(其他平台插件自动禁用)
264
+ 4. 开启 `debug: true` 查看插件日志
265
+ 5. 确认 `@vue/compiler-sfc` 已安装:`pnpm add -D @vue/compiler-sfc`
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "public",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
package/.editorconfig DELETED
@@ -1,25 +0,0 @@
1
-
2
- root = true
3
-
4
- [*]
5
- indent_style = space
6
- # 缩进大小=2
7
- indent_size = 2
8
-
9
- end_of_line = lf
10
- # 字符集=utf-8
11
- charset = utf-8
12
- # 删除行尾空格 = 是
13
- trim_trailing_whitespace = true
14
- # 插入最后一行=真
15
- insert_final_newline = true
16
-
17
- [*.md]
18
- # 删除行尾空格 = 否
19
- trim_trailing_whitespace = false
20
-
21
- [package.json]
22
- # 缩进样式=空格
23
- indent_style = space
24
- # 缩进大小=2
25
- indent_size = 2
@@ -1,38 +0,0 @@
1
- name: Publish to npm
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
-
8
- concurrency: ${{ github.workflow }}-${{ github.ref }}
9
-
10
- jobs:
11
- publish:
12
- runs-on: ubuntu-latest
13
- permissions:
14
- contents: write
15
- pull-requests: write
16
- steps:
17
- - uses: actions/checkout@v4
18
-
19
- - uses: pnpm/action-setup@v4
20
- with:
21
- version: latest
22
-
23
- - uses: actions/setup-node@v4
24
- with:
25
- node-version: 20
26
- registry-url: https://registry.npmjs.org
27
- cache: pnpm
28
-
29
- - name: Install dependencies
30
- run: pnpm install --no-frozen-lockfile
31
-
32
- - name: Create Release Pull Request or Publish
33
- uses: changesets/action@v1
34
- with:
35
- publish: pnpm release
36
- env:
37
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.prettierrc.cjs DELETED
@@ -1,8 +0,0 @@
1
- // .prettierrc.js 文件
2
- module.exports = {
3
- printWidth: 100,
4
- tabWidth: 2,
5
- useTabs: false,
6
- semi: false,
7
- singleQuote: true,
8
- };
package/build.config.ts DELETED
@@ -1,12 +0,0 @@
1
- import { defineBuildConfig } from 'unbuild'
2
-
3
- export default defineBuildConfig({
4
- entries: ['src/index'],
5
- declaration: true,
6
- clean: true,
7
- rollup: {
8
- emitCJS: true,
9
- },
10
- failOnWarn: false,
11
- externals: ['vite', 'vue', '@babel/generator'],
12
- })
package/llms.txt DELETED
@@ -1,154 +0,0 @@
1
- # mp-weixin-back
2
-
3
- > Vite plugin for intercepting back navigation (gesture back + navbar back button) in WeChat miniprogram (mp-weixin) built with uni-app + Vue 3.
4
-
5
- ## When to use
6
-
7
- Use this library when you need to:
8
- - Intercept or customize the swipe-back gesture in a WeChat miniprogram page
9
- - Intercept or customize the navbar back button behavior
10
- - Show a confirmation dialog before the user leaves a page
11
- - Prevent accidental back navigation (e.g., on a form page)
12
-
13
- ## Install
14
-
15
- ```bash
16
- npm install mp-weixin-back
17
- # or
18
- pnpm add mp-weixin-back
19
- ```
20
-
21
- ## Setup (vite.config.ts)
22
-
23
- Register the Vite plugin once, globally:
24
-
25
- ```ts
26
- import { defineConfig } from 'vite'
27
- import mpBackPlugin from 'mp-weixin-back'
28
-
29
- export default defineConfig({
30
- plugins: [
31
- mpBackPlugin({
32
- preventDefault: false, // true = block all back navigation by default
33
- frequency: 1, // how many times to intercept before allowing through
34
- debug: false, // enable debug logging in development
35
- onPageBack: ({ page }) => {
36
- console.log('back triggered on page:', page)
37
- },
38
- }),
39
- ],
40
- })
41
- ```
42
-
43
- ## Usage in Vue SFC (Composition API)
44
-
45
- Import from the virtual module `mp-weixin-back-helper`:
46
-
47
- ```ts
48
- // Basic usage — listen to back event
49
- import onPageBack from 'mp-weixin-back-helper'
50
-
51
- onPageBack(() => {
52
- console.log('back navigation detected')
53
- })
54
- ```
55
-
56
- ```ts
57
- // Advanced — prevent back and show dialog
58
- import onPageBack from 'mp-weixin-back-helper'
59
-
60
- onPageBack(
61
- () => {
62
- showConfirmDialog() // your logic here
63
- },
64
- {
65
- preventDefault: true, // block default back behavior
66
- frequency: 2, // intercept 2 times
67
- initialValue: true, // start listening immediately (default)
68
- }
69
- )
70
- ```
71
-
72
- ```ts
73
- // Manually toggle the listener
74
- import onPageBack, { activeMpBack, inactiveMpBack } from 'mp-weixin-back-helper'
75
-
76
- onPageBack(() => { /* ... */ }, { initialValue: false }) // start disabled
77
-
78
- activeMpBack() // enable listener (call inside <script setup>)
79
- inactiveMpBack() // disable listener (call inside <script setup>)
80
- ```
81
-
82
- ## TypeScript support
83
-
84
- Add to `tsconfig.json`:
85
-
86
- ```json
87
- {
88
- "compilerOptions": {
89
- "types": ["mp-weixin-back/client"]
90
- }
91
- }
92
- ```
93
-
94
- Or in `env.d.ts`:
95
-
96
- ```ts
97
- /// <reference types="mp-weixin-back/client" />
98
- ```
99
-
100
- ## API Reference
101
-
102
- ### Plugin options (`mpBackPlugin(options)`)
103
-
104
- | Option | Type | Default | Description |
105
- | --------------- | --------------------------------- | ------- | -------------------------------------------------------- |
106
- | `preventDefault`| `boolean` | `false` | Block default back behavior globally |
107
- | `frequency` | `number` | `1` | Number of times to intercept before allowing through |
108
- | `debug` | `boolean` | `false` | Log debug info in development mode |
109
- | `onPageBack` | `(params: { page: string }) => void` | — | Global callback fired on every back event |
110
-
111
- ### `onPageBack(callback, options?)`
112
-
113
- Listen to back events on the current page. Must be called in `<script setup>`.
114
-
115
- | Param | Type | Required | Description |
116
- | ---------- | --------------------- | -------- | ------------------------------- |
117
- | `callback` | `() => void` | Yes | Function called when back fires |
118
- | `options` | `OnPageBackOptions` | No | Per-page overrides |
119
-
120
- #### `OnPageBackOptions`
121
-
122
- | Option | Type | Default | Description |
123
- | --------------- | --------- | ------- | ------------------------------------------------------------ |
124
- | `preventDefault`| `boolean` | `false` | Block default back for this page |
125
- | `frequency` | `number` | `1` | Intercept count for this page |
126
- | `initialValue` | `boolean` | `true` | Start listening immediately; set `false` to enable manually |
127
-
128
- ### `activeMpBack()`
129
-
130
- Enable the back listener. Call inside `<script setup>` when `initialValue: false`.
131
-
132
- ### `inactiveMpBack()`
133
-
134
- Disable the back listener. Call inside `<script setup>`.
135
-
136
- ## How it works
137
-
138
- This is a **Vite transform plugin**. At build time it:
139
- 1. Reads `src/pages.json` to identify miniprogram pages
140
- 2. For each `.vue` page file, injects a `<page-container>` component into the template (the WeChat API used to intercept back gestures)
141
- 3. Wires up the `onPageBack` composable to control `show` state of `<page-container>`
142
-
143
- The virtual module `mp-weixin-back-helper` is resolved by the plugin and provides the runtime composable API.
144
-
145
- ## Constraints
146
-
147
- - Requires **uni-app** project with `src/pages.json`
148
- - Requires **Vue 3** + `<script setup>` (Composition API)
149
- - Works with **Vite 3–6**
150
- - Only applies to page-level `.vue` files, not components
151
-
152
- ## Repository
153
-
154
- https://github.com/DBAAZzz/mp-weixin-back
package/shims-vue.d.ts DELETED
@@ -1,6 +0,0 @@
1
- // shims-vue.d.ts
2
- declare module '*.vue' {
3
- import { DefineComponent } from 'vue'
4
- const component: DefineComponent<{}, {}, any>
5
- export default component
6
- }
package/src/context.ts DELETED
@@ -1,78 +0,0 @@
1
- import path from 'path'
2
- import fs from 'fs'
3
- import JSON5 from 'json5'
4
- import { red, white, green } from 'kolorist'
5
- import { ContextConfig, PagesJson } from '../types'
6
- import { transformVueFile } from '../utils'
7
-
8
- export class pageContext {
9
- private logPreText = '[mp-weixin-back] : '
10
- config: ContextConfig
11
- pages: string[] = []
12
- log = {
13
- info: (text: string) => {
14
- console.log(white(this.logPreText + text))
15
- },
16
- error: (text: string) => {
17
- console.log(red(this.logPreText + text))
18
- },
19
- debugLog: (text: string) => {
20
- if (this.config.mode === 'development' && this.config.debug) {
21
- console.log(green(this.logPreText + text))
22
- }
23
- },
24
- }
25
-
26
- constructor(config: ContextConfig) {
27
- this.config = config
28
- }
29
- getPagesJsonPath() {
30
- const pagesJsonPath = path.join(this.config.root, 'src/pages.json')
31
- return pagesJsonPath
32
- }
33
- // 获取页面配置详情
34
- async getPagesJsonInfo() {
35
- const hasPagesJson = fs.existsSync(this.getPagesJsonPath())
36
- if (!hasPagesJson) return
37
- try {
38
- const content = await fs.promises.readFile(this.getPagesJsonPath(), 'utf-8')
39
- const pagesContent = JSON5.parse(content) as PagesJson
40
- const { pages, subpackages } = pagesContent
41
- if (pages) {
42
- const mainPages = pages.reduce((acc: string[], current) => {
43
- acc.push(current.path)
44
- return acc
45
- }, [])
46
- this.pages.push(...mainPages)
47
- }
48
- if (subpackages) {
49
- for (let i = 0; i < subpackages.length; i++) {
50
- const element = subpackages[i]
51
- const root = element.root
52
- const subPages = element.pages.reduce((acc: string[], current) => {
53
- acc.push(`${root}/${current.path}`.replace('//', '/'))
54
- return acc
55
- }, [])
56
- this.pages.push(...subPages)
57
- }
58
- }
59
- } catch (error: unknown) {
60
- this.log.error(
61
- `Failed to read pages.json. Make sure src/pages.json exists and is valid JSON/JSON5.\n` +
62
- ` Path checked: ${this.getPagesJsonPath()}\n` +
63
- ` Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-配置`
64
- )
65
- this.log.debugLog(String(error))
66
- }
67
- }
68
- // 获取指定id的page
69
- getPageById(id: string) {
70
- const path = (id.split('src/')[1] || '').replace('.vue', '')
71
- // 页面级别
72
- return this.pages.find((i) => i === path) || null
73
- }
74
- async transform(code: string, id: string) {
75
- const result = await transformVueFile.call(this, code, id)
76
- return result
77
- }
78
- }
package/src/index.ts DELETED
@@ -1,79 +0,0 @@
1
- import { pageContext } from './context'
2
- import { virtualFileId } from '../utils/constant'
3
- import type { Plugin } from 'vite'
4
- import type { Config, UserOptions } from '../types'
5
-
6
- function MpBackPlugin(userOptions: UserOptions = {}): Plugin {
7
- let context: pageContext
8
-
9
- const defaultOptions: Config = {
10
- initialValue: true,
11
- preventDefault: false,
12
- frequency: 1,
13
- debug: false,
14
- }
15
- const options = { ...defaultOptions, ...userOptions }
16
-
17
- return {
18
- name: 'vite-plugin-mp-weixin-back',
19
- enforce: 'pre',
20
- configResolved(config) {
21
- context = new pageContext({ ...options, mode: config.mode, root: config.root })
22
- },
23
- buildStart() {
24
- context.getPagesJsonInfo()
25
- },
26
- resolveId(id) {
27
- if (id === virtualFileId) {
28
- return virtualFileId
29
- }
30
- },
31
- load(id) {
32
- if (id.includes('node_modules')) {
33
- return
34
- }
35
- // 导出一个对象
36
- if (id === virtualFileId) {
37
- return `
38
- import { ref } from 'vue'
39
- export default function onPageBack() {}
40
- export function activeMpBack(fn = null) {
41
- fn?.()
42
- }
43
- export function inactiveMpBack(fn = null) {
44
- fn?.()
45
- }
46
- export function useMpWeixinBack(initialValue = true) {
47
- const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(initialValue)
48
-
49
- const __MP_WEIXIN_ACTIVEBACK__ = () => {
50
- __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
51
- }
52
-
53
- const __MP_WEIXIN_INACTIVEBACK__ = () => {
54
- __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
55
- }
56
-
57
- return {
58
- __MP_BACK_SHOW_PAGE_CONTAINER__,
59
- __MP_WEIXIN_ACTIVEBACK__,
60
- __MP_WEIXIN_INACTIVEBACK__
61
- }
62
- }
63
- `
64
- }
65
- },
66
- async transform(code, id) {
67
- if (id.includes('node_modules') || !id.includes('.vue')) {
68
- return
69
- }
70
-
71
- return {
72
- code: await context.transform(code, id),
73
- map: null,
74
- }
75
- },
76
- } as Plugin
77
- }
78
-
79
- export default MpBackPlugin
@@ -1,17 +0,0 @@
1
- <template>
2
- <div>我是默认的界面</div>
3
- </template>
4
-
5
- <script>
6
- export default {
7
- data() {
8
- return {}
9
- },
10
- onPageBack() {
11
- console.log('触发了手势返回')
12
- return true
13
- },
14
- }
15
- </script>
16
-
17
- <style></style>
@@ -1,14 +0,0 @@
1
- <template>
2
- <div>我是默认的界面</div>
3
- </template>
4
-
5
- <script setup>
6
- import onPageBack from 'mp-weixin-back-helper'
7
-
8
- onPageBack(() => {
9
- console.log('触发了手势返回')
10
- return true
11
- })
12
- </script>
13
-
14
- <style></style>
@@ -1,29 +0,0 @@
1
- <template>
2
- <div>我是默认的界面</div>
3
- <button id="button" @click="disableMpBack"></button>
4
- <button id="button2" @click="activeMpBack"></button>
5
- </template>
6
-
7
- <script setup>
8
- import onPageBack, { activeMpBack as mpppacitve, inactiveMpBack } from 'mp-weixin-back-helper'
9
-
10
- onPageBack(
11
- () => {
12
- console.log('触发了手势返回')
13
- },
14
- {
15
- initialValue: false,
16
- }
17
- )
18
-
19
- const activeMpBack = () => {
20
- console.log('执行了activeMpBack')
21
- mpppacitve()
22
- }
23
-
24
- const disableMpBack = () => {
25
- inactiveMpBack()
26
- }
27
- </script>
28
-
29
- <style></style>