- 概述
- 前置条件
- 第一步:SDK 配置
- 第二步:安装和配置 sentry-cli
- 第三步:生成 Source Map
- 第四步:上传 Source Map
- 第五步:CI/CD 自动化
- 第六步:验证 Source Map 是否生效
- 平台特殊说明
- 安全注意事项
- 常见问题排查
- 完整配置示例
在小程序中,错误堆栈的路径通常是各平台的虚拟路径(如微信的 appservice/pages/index.js、支付宝的 https://appx/pages/index.js),这导致上传到 Sentry 的 Source Map 无法被正确匹配和解析。
SDK 的解决方案: sentry-miniapp 内置了 RewriteFrames 集成,在上报错误时自动将各平台虚拟路径归一化为统一的 app:/// 前缀。例如:
微信: appservice/pages/index.js → app:///pages/index.js
支付宝: https://appx/pages/index.js → app:///pages/index.js
字节跳动: tt://pages/index.js → app:///pages/index.js
百度: swan://pages/index.js → app:///pages/index.js
因此,你在上传 Source Map 时只需统一使用 --url-prefix "app:///" 即可,无需关心各平台差异。
端到端流程:
构建工具生成 .js + .map 文件
↓
sentry-cli 上传 .map 到 Sentry(url-prefix: app:///)
↓
小程序运行时发生错误
↓
SDK 捕获错误,RewriteFrames 归一化堆栈路径为 app:///
↓
Sentry 收到事件,匹配 app:/// 前缀找到对应 Source Map
↓
Sentry 面板展示原始源码位置
- Sentry 账号:SaaS 版(sentry.io)或自托管版均可
- Sentry 项目:已创建对应的项目
- Auth Token:在 Sentry 设置中创建,需具备
project:releases和org:read权限- SaaS 版:
https://sentry.io/settings/auth-tokens/ - 自托管版:
https://<your-sentry>/settings/auth-tokens/
- SaaS 版:
release 是 Source Map 生效的关键——SDK 初始化时设置的 release 值必须与 sentry-cli 上传时使用的 release 名称完全一致。
import * as Sentry from 'sentry-miniapp';
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
release: 'my-miniapp@1.0.0', // 必须与上传时的 release 名称一致
environment: 'production',
// enableSourceMap: true, // 默认已开启,无需显式设置
});| 方式 | 示例 | 适用场景 |
|---|---|---|
| 语义化版本 | my-miniapp@1.2.3 |
有明确版本号的项目 |
| Git Commit SHA | my-miniapp@a1b2c3d |
持续部署场景 |
| 构建编号 | my-miniapp@build-456 |
CI/CD 自动构建 |
推荐在构建时通过环境变量注入,避免手动维护版本号:
Webpack(Taro):
// config/index.js
const config = {
defineConstants: {
SENTRY_RELEASE: JSON.stringify(process.env.SENTRY_RELEASE || 'dev'),
},
};Vite:
// vite.config.js
export default defineConfig({
define: {
__SENTRY_RELEASE__: JSON.stringify(process.env.SENTRY_RELEASE || 'dev'),
},
});然后在代码中使用:
Sentry.init({
dsn: '...',
release: SENTRY_RELEASE, // 或 __SENTRY_RELEASE__
});SDK 默认开启路径归一化(enableSourceMap: true),通常无需修改。如果你因特殊原因需要禁用:
Sentry.init({
enableSourceMap: false, // 禁用路径归一化
});# 推荐:作为开发依赖安装
npm install @sentry/cli --save-dev
# 或全局安装
npm install -g @sentry/cli方式一:.sentryclirc 文件(推荐本地开发)
在项目根目录创建 .sentryclirc:
[auth]
token=your-auth-token-here
[defaults]
org=your-org-slug
project=your-project-slug重要: 将
.sentryclirc添加到.gitignore,防止 Token 泄露。
方式二:环境变量(推荐 CI/CD)
export SENTRY_AUTH_TOKEN=your-auth-token-here
export SENTRY_ORG=your-org-slug
export SENTRY_PROJECT=your-project-slug根据你使用的构建工具,配置 Source Map 生成。
// config/index.js(Taro 配置)
const config = {
mini: {
webpackChain(chain) {
// 使用 hidden-source-map,避免在产物中暴露 .map 文件引用
chain.devtool('hidden-source-map');
},
},
};// vite.config.js
export default defineConfig({
build: {
sourcemap: 'hidden', // 生成 .map 文件但不在 .js 中添加 sourceMappingURL 注释
},
});Vue CLI 模式:
// vue.config.js
module.exports = {
productionSourceMap: true,
configureWebpack: {
devtool: 'hidden-source-map',
},
};Vite 模式(uni-app 3.x+):
// vite.config.js
export default defineConfig({
build: {
sourcemap: 'hidden',
},
});提示: 推荐使用
hidden-source-map(Webpack)或sourcemap: 'hidden'(Vite),这样生成.map文件用于上传,但不会在产物 JS 文件中添加//# sourceMappingURL注释,避免在生产环境暴露源码映射。
# 定义 release 名称(与 SDK 中的 release 一致)
VERSION="my-miniapp@1.0.0"
# 1. 创建 release
npx sentry-cli releases new "$VERSION"
# 2. 上传 Source Map
npx sentry-cli releases files "$VERSION" upload-sourcemaps ./dist \
--url-prefix "app:///" \
--ext js --ext map
# 3. 完成 release
npx sentry-cli releases finalize "$VERSION"参数说明:
| 参数 | 说明 |
|---|---|
--url-prefix "app:///" |
与 SDK 的 RewriteFrames 归一化前缀对应,必须设置 |
--ext js --ext map |
只上传 .js 和 .map 文件 |
./dist |
构建产物目录,根据实际情况调整 |
npm install @sentry/webpack-plugin --save-dev// config/index.js(Taro)
const { sentryWebpackPlugin } = require('@sentry/webpack-plugin');
const config = {
mini: {
webpackChain(chain) {
chain.devtool('hidden-source-map');
chain.plugin('sentry').use(sentryWebpackPlugin, [{
authToken: process.env.SENTRY_AUTH_TOKEN,
org: 'your-org',
project: 'your-project',
release: { name: process.env.SENTRY_RELEASE },
urlPrefix: 'app:///',
sourcemaps: { filesToDeleteAfterUpload: ['**/*.map'] },
}]);
},
},
};npm install @sentry/vite-plugin --save-dev// vite.config.js
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default defineConfig({
build: {
sourcemap: true,
},
plugins: [
sentryVitePlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: 'your-org',
project: 'your-project',
release: { name: process.env.SENTRY_RELEASE },
urlPrefix: 'app:///',
sourcemaps: { filesToDeleteAfterUpload: ['**/*.map'] },
}),
],
});提示: 使用构建插件时,Source Map 会在构建完成后自动上传,并可通过
filesToDeleteAfterUpload自动清理.map文件,避免发布到生产环境。
name: Build & Upload SourceMaps
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: 安装依赖
run: npm install
- name: 构建(生成 Source Map)
run: npm run build
env:
SENTRY_RELEASE: ${{ github.ref_name }}
- name: 上传 Source Map 到 Sentry
run: |
npx sentry-cli releases new "$SENTRY_RELEASE"
npx sentry-cli releases files "$SENTRY_RELEASE" upload-sourcemaps ./dist \
--url-prefix "app:///" \
--ext js --ext map
npx sentry-cli releases finalize "$SENTRY_RELEASE"
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: your-org
SENTRY_PROJECT: your-project
SENTRY_RELEASE: ${{ github.ref_name }}
- name: 清理 Source Map 文件
run: find ./dist -name "*.map" -delete
# 后续部署步骤...#!/bin/bash
# upload-sourcemaps.sh
set -e
VERSION=${SENTRY_RELEASE:-$(node -p "require('./package.json').version")}
echo "上传 Source Map,release: $VERSION"
npx sentry-cli releases new "$VERSION"
npx sentry-cli releases files "$VERSION" upload-sourcemaps ./dist \
--url-prefix "app:///" \
--ext js --ext map
npx sentry-cli releases finalize "$VERSION"
echo "上传完成,清理 .map 文件..."
find ./dist -name "*.map" -delete
echo "完成"npx sentry-cli releases files "my-miniapp@1.0.0" list输出应包含类似条目:
Name Size
app:///pages/index.js 12.5 KB
app:///pages/index.js.map 45.2 KB
在小程序代码中故意抛出一个错误:
// pages/index.js
Page({
onLoad() {
throw new Error('Source Map 测试错误');
},
});- 登录 Sentry,进入对应项目
- 找到刚触发的错误事件
- 查看堆栈信息——如果显示的是原始源码而非压缩代码,说明 Source Map 配置成功
- 如果仍显示压缩代码,点击堆栈帧右侧的 "Source Map Debug" 按钮,Sentry 会告诉你匹配失败的原因
必须关闭微信开发者工具自带的编译选项:
- ES6 转 ES5 → 关闭
- 代码压缩 → 关闭
- 样式补全 → 关闭(可选)
这些工作应交给 Webpack/Vite 等构建工具处理,否则会导致行列号错位,Source Map 无法正确匹配。
路径归一化: SDK 自动剥离 appservice/、app-service/、WAService/ 前缀。
路径归一化: SDK 自动剥离 https://appx/ 等 HTTP 协议前缀。
路径归一化: SDK 自动剥离 tt:// 协议前缀。
路径归一化: SDK 自动剥离 swan:// 协议前缀。
SDK 会自动剥离所有 协议:// 格式的前缀,因此 QQ、钉钉、快手等平台的虚拟路径也能被正确处理。
- 不要将
.map文件发布到生产环境——Source Map 包含原始源码,泄露可能带来安全风险。上传到 Sentry 后应立即删除本地.map文件。 - 不要将 Auth Token 提交到代码仓库——使用环境变量或将
.sentryclirc添加到.gitignore。 - 使用
hidden-source-map——避免在产物中生成sourceMappingURL注释,防止浏览器或调试工具直接加载.map文件。
检查项:
release名称是否一致?SDK 中的release必须与sentry-cli releases new的 release 名称完全匹配--url-prefix是否为app:///?- 是否禁用了微信开发者工具的 "ES6 转 ES5" 和 "代码压缩"?
- 在 Sentry 事件详情中,点击 "Source Map Debug" 查看具体匹配失败原因
排查方法:
- 在 Sentry 事件的原始 JSON 中查看实际的
filename字段(应以app:///开头) - 用
sentry-cli releases files <release> list查看已上传文件的名称 - 确认两者路径完全一致
解决方案:
- 增加超时时间:在
.sentryclirc中添加[http]的timeout配置 - 拆分上传:按目录分批上传
- 检查是否有不必要的大文件被包含
检查项:
- Auth Token 是否有效且具备
project:releases权限 SENTRY_ORG和SENTRY_PROJECT是否正确- 网络是否能访问 Sentry 服务器(自托管需检查内网连通性)
以下是一个 Taro + Webpack 项目的完整 Source Map 配置示例:
1. SDK 初始化(app.js):
import * as Sentry from 'sentry-miniapp';
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
release: SENTRY_RELEASE, // 构建时注入
environment: 'production',
// enableSourceMap 默认为 true
});2. Taro 构建配置(config/index.js):
const config = {
defineConstants: {
SENTRY_RELEASE: JSON.stringify(process.env.SENTRY_RELEASE || `my-miniapp@${require('./package.json').version}`),
},
mini: {
webpackChain(chain) {
chain.devtool('hidden-source-map');
},
},
};3. .sentryclirc(本地开发):
[auth]
token=sntrys_xxx
[defaults]
org=my-org
project=my-miniapp4. .gitignore:
.sentryclirc
5. 上传脚本(package.json):
{
"scripts": {
"upload:sourcemaps": "sentry-cli releases new $npm_package_version && sentry-cli releases files $npm_package_version upload-sourcemaps ./dist --url-prefix 'app:///' --ext js --ext map && sentry-cli releases finalize $npm_package_version"
}
}6. 构建并上传:
SENTRY_RELEASE="my-miniapp@1.0.0" npm run build
SENTRY_RELEASE="my-miniapp@1.0.0" npm run upload:sourcemaps