838 lines
18 KiB
Markdown
838 lines
18 KiB
Markdown
# Kbone 常见问题排查指南
|
||
|
||
## 从 Next 项目迁移到小程序
|
||
|
||
**先读**:本技能 `SKILL.md` 中的「Next 项目 → 小程序 最优转化方式」章节。
|
||
|
||
**要点**:
|
||
- 以 **newpp** 为 Kbone 构建源,**miniprogram** 为壳,构建后合并产物。
|
||
- 必须做 **适配层**:`env`、`request`、`storage`、`router`;功能开关与 Next 一致,用同一 API(如 `/api/db/config` 的 `features.matchEnabled`)。
|
||
- **UI**:在 newpp 内复制并适配 Next 的页面/组件,或通过 webpack alias 引用根目录共享组件(无 Next 专属 API)。
|
||
- **配置**:`miniprogram.config.js` 每页单独 router、**不配原生 tabBar**;`webpack.mp.config.js` 中 `isOptimize = process.env.NODE_ENV === 'production'`,中小型项目建议 `splitChunks: false`。
|
||
- **底部菜单**:Web 端多为自定义底部菜单组件(主页面统一引入、有显隐逻辑),**不要**转为小程序原生 tabBar;保留「主页面引入统一菜单组件」,显隐与跳转与 Web 一致,跳转用 `wx.reLaunch`。
|
||
- **样式**:Grid 改 Flex,补 `boxSizing`/`lineHeight`;不支持特性用兼容写法或替代。
|
||
|
||
遇到具体报错时,在下方「配置问题」「编译问题」「运行时问题」「样式问题」中按类型排查。
|
||
|
||
---
|
||
|
||
## 配置问题
|
||
|
||
### 1. redirect 用了不存在的页面名
|
||
|
||
**现象**:配置了 `redirect.notFound: 'home'`、`redirect.accessDenied: 'home'`,但 router 里没有名为 `home` 的页面。
|
||
|
||
**后果**:404 或无权时,Kbone 可能无法正确跳转到首页。
|
||
|
||
**解决**:redirect 必须使用 **router 里存在的 key**。首页通常是 `index`,不要写 `home`。
|
||
|
||
```javascript
|
||
// ❌ 错误
|
||
redirect: { notFound: 'home', accessDenied: 'home' }
|
||
|
||
// ✅ 正确
|
||
redirect: { notFound: 'index', accessDenied: 'index' }
|
||
```
|
||
|
||
---
|
||
|
||
## 编译问题
|
||
|
||
### 0. Node 17+ OpenSSL 错误(ERR_OSSL_EVP_UNSUPPORTED)
|
||
|
||
**错误信息**:
|
||
```
|
||
Error: error:0308010C:digital envelope routines::unsupported
|
||
code: 'ERR_OSSL_EVP_UNSUPPORTED'
|
||
```
|
||
|
||
**原因**:Node.js 17+ 使用 OpenSSL 3.0,旧版 webpack(如 4.x)依赖的 MD4 等算法被移出默认提供,导致构建时报错。
|
||
|
||
**解决方案**:
|
||
|
||
**方案 1:在 newpp 的 package.json 脚本中加 NODE_OPTIONS**(推荐)
|
||
```json
|
||
"scripts": {
|
||
"web": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack-dev-server ...",
|
||
"mp": "rimraf dist/mp/common && cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack ...",
|
||
"build:mp": "rimraf dist/mp/common && cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack ..."
|
||
}
|
||
```
|
||
|
||
**方案 2:当前终端临时设置后再运行**
|
||
- Windows PowerShell:`$env:NODE_OPTIONS="--openssl-legacy-provider"; cd newpp; npm run web`
|
||
- Windows CMD:`set NODE_OPTIONS=--openssl-legacy-provider && cd newpp && npm run web`
|
||
- Linux/macOS:`NODE_OPTIONS=--openssl-legacy-provider npm run web`
|
||
|
||
**方案 3**:使用 Node.js 16.x(LTS)运行 newpp 构建,避免 OpenSSL 3.0。
|
||
|
||
---
|
||
|
||
### 1. chunk 文件缺失错误
|
||
|
||
**错误信息**:
|
||
```
|
||
Error: ENOENT: no such file or directory, open 'E:/path/to/default~chapters~index~my.js'
|
||
```
|
||
|
||
**原因**:
|
||
- Webpack 代码分割(splitChunks)生成了动态命名的 chunk 文件
|
||
- 小程序环境下,动态 chunk 路径可能不稳定
|
||
|
||
**解决方案**:
|
||
|
||
**方案 1:完全禁用代码分割**(推荐中小型项目)
|
||
```javascript
|
||
// webpack.mp.config.js
|
||
optimization: {
|
||
runtimeChunk: false,
|
||
splitChunks: false, // 完全禁用
|
||
}
|
||
```
|
||
|
||
**方案 2:固定 chunk 命名**(大型项目)
|
||
```javascript
|
||
optimization: {
|
||
runtimeChunk: false,
|
||
splitChunks: {
|
||
chunks: 'all',
|
||
name: true, // 使用固定命名
|
||
cacheGroups: {
|
||
vendors: {
|
||
name: 'vendors',
|
||
test: /[\\/]node_modules[\\/]/,
|
||
priority: 10,
|
||
},
|
||
default: {
|
||
name: 'common',
|
||
minChunks: 2,
|
||
priority: 5,
|
||
},
|
||
},
|
||
},
|
||
}
|
||
```
|
||
|
||
**选择建议**:
|
||
- 项目 <20 页面:方案 1(稳定性优先)
|
||
- 项目 >50 页面:方案 2(体积优化优先)
|
||
|
||
---
|
||
|
||
### 2. Babel 编译错误
|
||
|
||
**错误信息**:
|
||
```
|
||
SyntaxError: Unexpected token ...
|
||
```
|
||
或具体到某列:`Unexpected token (45:64)`(多为可选链位置)
|
||
|
||
**原因**:
|
||
- Babel 配置不正确
|
||
- 使用了 Babel 6(stage-3)不支持的语法:**可选链 `?.`、空值合并 `??`**(属 ES2020)
|
||
- 其他小程序不支持的 ES6+ 语法
|
||
|
||
**解决方案**:
|
||
|
||
**若为可选链 / 空值合并**(最常见):
|
||
```javascript
|
||
// ❌ Babel 6 会报错
|
||
res.content?.length
|
||
x ?? 'default'
|
||
|
||
// ✅ 兼容写法
|
||
(res.content && res.content.length) || 0
|
||
x != null ? x : 'default'
|
||
```
|
||
|
||
**Babel 配置**(.babelrc 或 babel.config.js):
|
||
```javascript
|
||
{
|
||
"presets": [
|
||
["env", {
|
||
"targets": {
|
||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||
}
|
||
}],
|
||
"react",
|
||
"stage-3"
|
||
],
|
||
"plugins": [
|
||
"transform-runtime"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 依赖包报错
|
||
|
||
**错误信息**:
|
||
```
|
||
Module not found: Can't resolve 'xxx'
|
||
```
|
||
|
||
**排查步骤**:
|
||
|
||
1. **检查依赖是否安装**
|
||
```bash
|
||
npm list [package-name]
|
||
```
|
||
|
||
2. **重新安装依赖**
|
||
```bash
|
||
rm -rf node_modules package-lock.json
|
||
npm install
|
||
```
|
||
|
||
3. **检查 webpack resolve 配置**
|
||
```javascript
|
||
resolve: {
|
||
extensions: ['*', '.js', '.jsx', '.json'],
|
||
alias: {
|
||
'@': path.resolve(__dirname, 'src'),
|
||
},
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 运行时问题
|
||
|
||
### 0. TypeError: eval is not a function
|
||
|
||
**错误信息**:
|
||
```
|
||
TypeError: eval is not a function
|
||
at Object../src/index.jsx (index.js?...)
|
||
```
|
||
|
||
**原因**:`npm run mp` 使用 development 模式时,webpack 默认 `devtool: 'eval'`,会注入使用 `eval()` 的代码;小程序环境**不支持** `eval`,因此报错。
|
||
|
||
**解决方案**:在 **webpack.mp.config.js** 中显式关闭 devtool:
|
||
|
||
```javascript
|
||
module.exports = {
|
||
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
||
devtool: false, // 小程序环境不支持 eval,必须关闭
|
||
entry: { ... },
|
||
// ...
|
||
}
|
||
```
|
||
|
||
重新执行 `npm run mp` 或 `npm run build:mp` 后,再在微信开发者工具中预览即可。
|
||
|
||
---
|
||
|
||
### 1. URLSearchParams 未定义
|
||
|
||
**错误信息**:
|
||
```
|
||
ReferenceError: URLSearchParams is not defined
|
||
```
|
||
|
||
**原因**:小程序环境不支持 `URLSearchParams`
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// 自定义实现
|
||
function buildQueryString(params) {
|
||
const parts = []
|
||
for (const [key, value] of Object.entries(params)) {
|
||
if (value !== undefined && value !== null) {
|
||
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
||
}
|
||
}
|
||
return parts.join('&')
|
||
}
|
||
|
||
// 使用示例
|
||
const queryString = buildQueryString({
|
||
page: 1,
|
||
limit: 10,
|
||
keyword: '搜索'
|
||
})
|
||
// 结果: "page=1&limit=10&keyword=%E6%90%9C%E7%B4%A2"
|
||
```
|
||
|
||
---
|
||
|
||
### 2. localStorage 未定义
|
||
|
||
**错误信息**:
|
||
```
|
||
ReferenceError: localStorage is not defined
|
||
```
|
||
|
||
**原因**:小程序环境使用 `wx.storage` 而不是 `localStorage`
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// adapters/storage.js
|
||
function isMiniProgram() {
|
||
return typeof wx !== 'undefined' && wx.getSystemInfoSync
|
||
}
|
||
|
||
export const storage = {
|
||
get(key) {
|
||
if (isMiniProgram()) {
|
||
return wx.getStorageSync(key)
|
||
} else {
|
||
const value = localStorage.getItem(key)
|
||
try {
|
||
return JSON.parse(value)
|
||
} catch {
|
||
return value
|
||
}
|
||
}
|
||
},
|
||
|
||
set(key, value) {
|
||
if (isMiniProgram()) {
|
||
wx.setStorageSync(key, value)
|
||
} else {
|
||
localStorage.setItem(key, JSON.stringify(value))
|
||
}
|
||
},
|
||
|
||
remove(key) {
|
||
if (isMiniProgram()) {
|
||
wx.removeStorageSync(key)
|
||
} else {
|
||
localStorage.removeItem(key)
|
||
}
|
||
},
|
||
|
||
clear() {
|
||
if (isMiniProgram()) {
|
||
wx.clearStorageSync()
|
||
} else {
|
||
localStorage.clear()
|
||
}
|
||
},
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. window 对象未定义
|
||
|
||
**错误信息**:
|
||
```
|
||
ReferenceError: window is not defined
|
||
```
|
||
|
||
**原因**:小程序环境没有 `window` 对象
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// 环境判断
|
||
function isMiniProgram() {
|
||
return typeof wx !== 'undefined' && wx.getSystemInfoSync
|
||
}
|
||
|
||
// 使用示例
|
||
if (!isMiniProgram()) {
|
||
window.addEventListener('resize', handleResize)
|
||
}
|
||
|
||
// 或使用可选链
|
||
window?.addEventListener?.('resize', handleResize)
|
||
```
|
||
|
||
---
|
||
|
||
### 4. document 对象未定义
|
||
|
||
**错误信息**:
|
||
```
|
||
ReferenceError: document is not defined
|
||
```
|
||
|
||
**原因**:小程序环境没有 `document` 对象
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// ❌ 不要直接使用 document
|
||
const title = document.title
|
||
|
||
// ✅ 使用 React 特性
|
||
import { useEffect } from 'react'
|
||
|
||
function MyComponent() {
|
||
useEffect(() => {
|
||
if (!isMiniProgram()) {
|
||
document.title = 'My Page'
|
||
} else {
|
||
// 小程序使用 wx.setNavigationBarTitle
|
||
wx.setNavigationBarTitle({
|
||
title: 'My Page'
|
||
})
|
||
}
|
||
}, [])
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 样式问题
|
||
|
||
### 1. CSS Grid 不生效
|
||
|
||
**问题描述**:使用 CSS Grid 布局在小程序中显示错乱
|
||
|
||
**原因**:小程序对 CSS Grid 支持不完整
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// ❌ 避免使用 Grid
|
||
const badStyles = {
|
||
container: {
|
||
display: 'grid',
|
||
gridTemplateColumns: 'repeat(4, 1fr)',
|
||
gap: '10px',
|
||
}
|
||
}
|
||
|
||
// ✅ 使用 Flexbox
|
||
const goodStyles = {
|
||
container: {
|
||
display: 'flex',
|
||
flexDirection: 'row',
|
||
flexWrap: 'wrap',
|
||
boxSizing: 'border-box',
|
||
},
|
||
item: {
|
||
flex: '0 0 25%', // 相当于 4 列
|
||
boxSizing: 'border-box',
|
||
padding: '5px',
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 盒模型计算错误
|
||
|
||
**问题描述**:元素尺寸计算不正确,padding/border 撑大元素
|
||
|
||
**原因**:未设置 `box-sizing: border-box`
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// ✅ 所有容器都添加 boxSizing
|
||
const styles = {
|
||
container: {
|
||
width: '100%',
|
||
padding: '10px',
|
||
boxSizing: 'border-box', // 重要!
|
||
},
|
||
item: {
|
||
width: '50%',
|
||
border: '1px solid #ccc',
|
||
boxSizing: 'border-box', // 重要!
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 文字垂直居中问题
|
||
|
||
**问题描述**:文字没有垂直居中
|
||
|
||
**原因**:未设置 `line-height`
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
const styles = {
|
||
button: {
|
||
height: '44px',
|
||
lineHeight: '44px', // 与 height 相同
|
||
textAlign: 'center',
|
||
},
|
||
text: {
|
||
lineHeight: '1.5', // 或使用相对值
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4. 标题/头部被胶囊或电池栏遮挡
|
||
|
||
**问题描述**:自定义导航栏时,标题、返回按钮被右上角胶囊或顶部状态栏遮挡。
|
||
|
||
**原因**:未预留顶部安全区高度和右侧胶囊留白。
|
||
|
||
**解决方案**:
|
||
|
||
1. **顶部安全区**:在 `app.js` 的 `onLaunch` 中计算并写入 `globalData`:
|
||
- `statusBarHeight = wx.getSystemInfoSync().statusBarHeight || 44`
|
||
- `navBarHeight`:用 `wx.getMenuButtonBoundingClientRect()` 计算 `menuButton.bottom + menuButton.top - statusBarHeight`,无菜单时用 `statusBarHeight + 44`
|
||
- `capsulePaddingRight = systemInfo.windowWidth - menuButton.left + 10`
|
||
2. **页面占位**:顶部占位条高度设为 `{{ navBarHeight }}px`,内容区 `padding-top: {{ statusBarHeight }}px`;页面 `onLoad`/`onShow` 从 `getApp().globalData` 取上述值写入 `data`。
|
||
3. **标题右侧留白**:头部容器加类 `.safe-header-right { padding-right: 200rpx; box-sizing: border-box; }`,或内联 `padding-right: {{ capsulePaddingRight }}px`,避免标题与胶囊重叠。
|
||
|
||
详见本目录 `reference.md` 第 7 节「安全区与标题/胶囊避让」。
|
||
|
||
---
|
||
|
||
### 5. Flexbox 间距问题
|
||
|
||
**问题描述**:Flexbox 子元素间距不均匀
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// 方案 1:使用 gap(注意兼容性)
|
||
const styles = {
|
||
container: {
|
||
display: 'flex',
|
||
gap: '10px', // 可能不支持
|
||
}
|
||
}
|
||
|
||
// 方案 2:使用 margin(推荐)
|
||
const styles = {
|
||
container: {
|
||
display: 'flex',
|
||
margin: '-5px', // 负边距抵消子元素边距
|
||
},
|
||
item: {
|
||
margin: '5px',
|
||
}
|
||
}
|
||
|
||
// 方案 3:使用伪元素
|
||
// CSS: .item:not(:last-child) { margin-right: 10px; }
|
||
```
|
||
|
||
---
|
||
|
||
## 路由问题
|
||
|
||
### 1. 页面跳转无效
|
||
|
||
**问题描述**:点击导航无反应
|
||
|
||
**排查步骤**:
|
||
|
||
1. **检查 router 配置**
|
||
```javascript
|
||
// miniprogram.config.js
|
||
router: {
|
||
index: ['/', '/index.html'],
|
||
my: ['/my', '/my.html'], // 确保配置了目标页面
|
||
}
|
||
```
|
||
|
||
2. **检查路由适配器**
|
||
```javascript
|
||
// adapters/router.js
|
||
export function navigateTo(path) {
|
||
if (isMiniProgram()) {
|
||
wx.navigateTo({
|
||
url: toMpPath(path),
|
||
fail: (err) => console.error('导航失败:', err)
|
||
})
|
||
} else {
|
||
window.location.href = path
|
||
}
|
||
}
|
||
```
|
||
|
||
3. **检查页面是否存在**
|
||
```bash
|
||
# 确保入口文件存在
|
||
ls src/my.jsx
|
||
```
|
||
|
||
---
|
||
|
||
### 2. switchTab 报错
|
||
|
||
**错误信息**:
|
||
```
|
||
navigateTo:fail can not navigateTo a tabbar page
|
||
```
|
||
|
||
**原因**:使用 `wx.navigateTo` 跳转 tabBar 页面
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// ❌ 错误
|
||
wx.navigateTo({ url: '/pages/index/index' })
|
||
|
||
// ✅ 正确
|
||
wx.switchTab({ url: '/pages/index/index' })
|
||
|
||
// 或使用 wx.reLaunch(不依赖 tabBar 配置)
|
||
wx.reLaunch({ url: '/pages/index/index' })
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 动态路由参数丢失
|
||
|
||
**问题描述**:`/read/:id` 中的 `id` 获取不到
|
||
|
||
**解决方案**:
|
||
|
||
```javascript
|
||
// 小程序环境
|
||
if (isMiniProgram()) {
|
||
// 从页面 options 获取
|
||
const pages = getCurrentPages()
|
||
const currentPage = pages[pages.length - 1]
|
||
const { id } = currentPage.options
|
||
}
|
||
|
||
// Web 环境
|
||
else {
|
||
// 从 URL 解析
|
||
const pathParts = window.location.pathname.split('/')
|
||
const id = pathParts[pathParts.length - 1]
|
||
|
||
// 或使用 React Router
|
||
import { useParams } from 'react-router-dom'
|
||
const { id } = useParams()
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 网络问题
|
||
|
||
### 1. API 请求失败
|
||
|
||
**错误信息**:
|
||
```
|
||
request:fail url not in domain list
|
||
```
|
||
|
||
**原因**:小程序要求配置服务器域名白名单
|
||
|
||
**解决方案**:
|
||
|
||
1. **小程序管理后台配置**
|
||
- 登录小程序管理后台
|
||
- 开发 > 开发设置 > 服务器域名
|
||
- 添加你的 API 域名
|
||
|
||
2. **开发阶段临时方案**
|
||
- 微信开发者工具 > 右上角详情
|
||
- 勾选"不校验合法域名"
|
||
|
||
3. **使用代理**
|
||
```javascript
|
||
// miniprogram.config.js
|
||
module.exports = {
|
||
origin: 'https://soul.quwanzhi.com', // 本项目线上域名,见开发文档 8、部署
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 跨域问题
|
||
|
||
**错误信息**:
|
||
```
|
||
Access to fetch at 'xxx' has been blocked by CORS policy
|
||
```
|
||
|
||
**原因**:Web 端开发时遇到跨域限制
|
||
|
||
**解决方案**:
|
||
|
||
**方案 1:配置 webpack devServer 代理**
|
||
```javascript
|
||
// webpack.dev.config.js
|
||
devServer: {
|
||
proxy: {
|
||
'/api': {
|
||
target: 'https://your-api.com',
|
||
changeOrigin: true,
|
||
pathRewrite: { '^/api': '' },
|
||
},
|
||
},
|
||
}
|
||
```
|
||
|
||
**方案 2:后端配置 CORS**
|
||
```javascript
|
||
// Express 示例
|
||
app.use(cors({
|
||
origin: ['http://localhost:8080', 'https://soul.quwanzhi.com'],
|
||
credentials: true,
|
||
}))
|
||
```
|
||
|
||
---
|
||
|
||
## 性能问题
|
||
|
||
### 1. 首屏加载慢
|
||
|
||
**排查步骤**:
|
||
|
||
1. **检查包体积**
|
||
```bash
|
||
# 查看构建产物大小
|
||
ls -lh dist/mp/common/
|
||
```
|
||
|
||
2. **启用代码压缩**
|
||
```javascript
|
||
// webpack.mp.config.js
|
||
const isOptimize = process.env.NODE_ENV === 'production'
|
||
|
||
optimization: {
|
||
minimizer: isOptimize ? [
|
||
new TerserPlugin(),
|
||
new OptimizeCSSAssetsPlugin(),
|
||
] : [],
|
||
}
|
||
```
|
||
|
||
3. **使用代码分割**(大型项目)
|
||
```javascript
|
||
optimization: {
|
||
splitChunks: {
|
||
chunks: 'all',
|
||
cacheGroups: {
|
||
vendors: {
|
||
test: /[\\/]node_modules[\\/]/,
|
||
priority: 10,
|
||
},
|
||
},
|
||
},
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 页面卡顿
|
||
|
||
**常见原因**:
|
||
|
||
1. **渲染列表过长**
|
||
```javascript
|
||
// ✅ 使用虚拟列表
|
||
import VirtualList from 'react-virtual-list'
|
||
|
||
<VirtualList
|
||
items={items}
|
||
itemHeight={50}
|
||
renderItem={(item) => <Item {...item} />}
|
||
/>
|
||
```
|
||
|
||
2. **频繁重渲染**
|
||
```javascript
|
||
// ✅ 使用 React.memo
|
||
const MyComponent = React.memo(({ data }) => {
|
||
return <div>{data}</div>
|
||
})
|
||
|
||
// ✅ 使用 useMemo
|
||
const expensiveValue = useMemo(() => {
|
||
return computeExpensiveValue(data)
|
||
}, [data])
|
||
```
|
||
|
||
---
|
||
|
||
## 调试技巧
|
||
|
||
### 1. 查看小程序日志
|
||
|
||
**微信开发者工具**:
|
||
- 控制台 > Console:查看 console.log
|
||
- 控制台 > Network:查看网络请求
|
||
- 控制台 > Storage:查看本地存储
|
||
|
||
---
|
||
|
||
### 2. 条件断点
|
||
|
||
```javascript
|
||
// 只在小程序环境下打印
|
||
if (isMiniProgram()) {
|
||
console.log('小程序环境:', data)
|
||
}
|
||
|
||
// 只在 Web 环境下打印
|
||
if (!isMiniProgram()) {
|
||
console.log('Web 环境:', data)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 真机调试
|
||
|
||
1. **开启调试模式**
|
||
- 微信开发者工具 > 预览
|
||
- 扫码在真机上打开
|
||
- 点击右上角 > 打开调试
|
||
|
||
2. **查看 vConsole**
|
||
- 小程序右下角会出现绿色悬浮按钮
|
||
- 点击查看日志、网络、存储等信息
|
||
|
||
---
|
||
|
||
## 检查清单
|
||
|
||
遇到问题时,按此清单逐项排查:
|
||
|
||
### 编译检查
|
||
- [ ] 所有依赖已安装(`npm install`)
|
||
- [ ] entry 配置正确
|
||
- [ ] output 配置未修改必需字段
|
||
- [ ] splitChunks 配置合理
|
||
|
||
### 兼容性检查
|
||
- [ ] 没有使用 URLSearchParams
|
||
- [ ] 没有使用 localStorage(改用适配器)
|
||
- [ ] 没有直接使用 window/document
|
||
- [ ] CSS 没有使用 Grid(改用 Flexbox)
|
||
|
||
### 配置检查
|
||
- [ ] router 每个页面单独配置
|
||
- [ ] pages 配置了所有页面
|
||
- [ ] 适配器正确处理平台差异
|
||
|
||
### 运行检查
|
||
- [ ] Web 端能正常运行
|
||
- [ ] 小程序能正常编译
|
||
- [ ] 微信开发者工具无错误
|
||
- [ ] 真机预览正常
|
||
|
||
---
|
||
|
||
## 获取帮助
|
||
|
||
### 官方资源
|
||
- [Kbone 官方文档](https://wechat-miniprogram.github.io/kbone/docs/)
|
||
- [Kbone GitHub Issues](https://github.com/wechat-miniprogram/kbone/issues)
|
||
- [小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/)
|
||
|
||
### 社区资源
|
||
- [Kbone 讨论区](https://github.com/wechat-miniprogram/kbone/discussions)
|
||
- [小程序开发者社区](https://developers.weixin.qq.com/community/)
|
||
|
||
### 调试工具
|
||
- 微信开发者工具:[下载地址](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)
|
||
- React DevTools:浏览器扩展
|
||
- vConsole:真机调试工具(小程序内置)
|