uni-cdn-uploader
| Install | |
|---|---|
npm install uni-cdn-uploader |
|
| Latest Version: | 1.0.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Sep 18, 2026 |
| Links: | npm |
uni-cdn-uploader
将 uniapp + Vue3 + TypeScript 小程序的静态资源自动上传到 CDN(支持火山引擎 TOS、七牛云 Kodo、阿里云 OSS、腾讯云 COS),并在构建时自动替换路径,大幅减小小程序包体积。
工作原理
┌─────────────┐ ┌──────────────┐ ┌───────────────┐ ┌─────────────┐
│ uni-cdn │────▶│ 上传到 CDN │────▶│ 生成 cdn-map │────▶│ Vite 构建 │
│ upload │ │ (带缓存) │ │ .json │ │ 替换路径 │
└─────────────┘ └──────────────┘ └───────────────┘ └─────────────┘
- 上传阶段:扫描
src/static/下的图片资源,上传到 CDN(火山引擎 TOS / 七牛云 Kodo / 阿里云 OSS / 腾讯云 COS),生成本地路径 → CDN URL 的映射表 - 构建阶段:Vite 插件在打包时自动将
.wxml/.wxss/.js中的/static/xxx替换为 CDN URL - 清理阶段:构建完成后自动删除产物中已上传到 CDN 的 static 文件,只保留 tabBar 图标等必要文件
安装
npm install uni-cdn-uploader --save-dev
快速开始
1. 初始化配置
npx uni-cdn init # 火山引擎 TOS(默认)
npx uni-cdn init --provider qiniu # 七牛云 Kodo
npx uni-cdn init --provider aliyun # 阿里云 OSS
npx uni-cdn init --provider tencent # 腾讯云 COS
会在项目根目录生成 uni-cdn.config.ts(以下为 TOS 示例,七牛/阿里云/腾讯云示例见「配置项说明」):
import type { UniCdnConfig } from 'uni-cdn-uploader'
const config: UniCdnConfig = {
provider: 'tos',
cdn: {
accessKeyId: process.env.VITE_TOS_ACCESS_KEY!,
secretAccessKey: process.env.VITE_TOS_SECRET_KEY!,
region: process.env.VITE_TOS_REGION!,
bucket: process.env.VITE_TOS_BUCKET!,
baseUrl: process.env.VITE_TOS_BASE_URL!,
},
}
export default config
2. 配置环境变量
运行 npx uni-cdn init 会自动生成专门的配置文件 .env.uni-cdn(与项目的 .env.local 分离,已含每项的获取指引),你也可以手动创建。各变量的获取方式(火山引擎):
| 变量 | 获取方式 |
|---|---|
VITE_TOS_ACCESS_KEY |
火山引擎控制台 →「访问控制 IAM」→「API 访问密钥」→ 新建密钥得到 AK |
VITE_TOS_SECRET_KEY |
与 AK 同时生成的 SK |
VITE_TOS_REGION |
Bucket 所在地域,如 cn-beijing / cn-shanghai / cn-guangzhou |
VITE_TOS_BUCKET |
「对象存储 TOS」中创建的 Bucket 名称 |
VITE_TOS_BASE_URL |
为 Bucket 绑定的 CDN 域名(如 https://cdn.example.com),也可临时用 TOS 默认域名 https://{bucket}.tos-{region}.volces.com |
VITE_TOS_ACCESS_KEY=你的AccessKeyId
VITE_TOS_SECRET_KEY=你的SecretAccessKey
VITE_TOS_REGION=cn-beijing
VITE_TOS_BUCKET=你的bucket名
VITE_TOS_BASE_URL=https://cdn.example.com
七牛云用户改用以下变量(获取方式:七牛控制台 →「个人中心」→「密钥管理」):
| 变量 | 获取方式 |
|---|---|
VITE_QINIU_ACCESS_KEY |
七牛「个人中心」→「密钥管理」中的 AccessKey |
VITE_QINIU_SECRET_KEY |
与 AK 同时生成的 SecretKey |
VITE_QINIU_BUCKET |
「对象存储 Kodo」中创建的空间名称 |
VITE_QINIU_REGION |
空间创建时所在存储区域(z0 华东 / z1 华北 / z2 华南 / na0 北美 / as0 新加坡等,默认 z0) |
VITE_QINIU_BASE_URL |
为空间绑定的 CDN 域名(如 https://cdn.example.com) |
阿里云用户改用以下变量(获取方式:阿里云控制台 →「访问控制 RAM」→ AccessKey):
| 变量 | 获取方式 |
|---|---|
VITE_ALIYUN_ACCESS_KEY_ID |
RAM 用户 / 主账号的 AccessKeyId |
VITE_ALIYUN_ACCESS_KEY_SECRET |
与 AK 同时生成的 AccessKeySecret |
VITE_ALIYUN_REGION |
Bucket 所在地域,如 oss-cn-hangzhou / oss-cn-shanghai / oss-cn-beijing |
VITE_ALIYUN_BUCKET |
「对象存储 OSS」中创建的 Bucket 名称 |
VITE_ALIYUN_BASE_URL |
为 Bucket 绑定的 CDN 域名(如 https://cdn.example.com) |
腾讯云用户改用以下变量(获取方式:腾讯云控制台 →「访问管理」→「API 密钥管理」):
| 变量 | 获取方式 |
|---|---|
VITE_TENCENT_SECRET_ID |
「API 密钥管理」中的 SecretId |
VITE_TENCENT_SECRET_KEY |
与 SecretId 同时生成的 SecretKey |
VITE_TENCENT_REGION |
存储桶所属地域,如 ap-guangzhou / ap-shanghai / ap-beijing |
VITE_TENCENT_BUCKET |
存储桶名称({名称}-{APPID} 格式,如 static-img-1250000000) |
VITE_TENCENT_BASE_URL |
为存储桶绑定的 CDN 域名(如 https://cdn.example.com) |
⚠️
.env.uni-cdn包含密钥,请务必加入.gitignore。
3. 上传静态资源
npx uni-cdn upload
- 首次上传会扫描所有匹配的图片文件
- 再次上传会自动跳过内容未变化的文件(基于文件内容 hash 缓存,避免 CI / git checkout 后 mtime 变化导致误判)
提示:
.cdn-cache.json与cdn-map.json是运行时产物,建议加入项目.gitignore。
如需清除缓存、强制全量重新上传(例如想重新推送所有资源到 CDN),运行:
npx uni-cdn clean # 删除 .cdn-cache.json 与 cdn-map.json
清除后再次运行 npx uni-cdn upload 即可全量重传。
4. 在 vite.config.ts 中注册插件
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { cdnReplacePlugin } from 'uni-cdn-uploader'
export default defineConfig({
plugins: [
uni(),
cdnReplacePlugin({
// 微信小程序产物目录
outputDir: 'dist/build/mp-weixin',
// 支付宝小程序改成:
// outputDir: 'dist/build/mp-alipay',
// 保留 tabBar 图标不上传、不删除
keepDirs: ['icon/tabBar'],
}),
],
})
5. 正常构建小程序
npm run build:mp-weixin
构建完成后,你会看到:
- 所有
/static/xxx.png已被替换为 CDN URL dist/build/mp-weixin/static/中多余文件已自动清理
配置项说明
provider 支持 'tos'(火山引擎)、'qiniu'(七牛云)、'aliyun'(阿里云 OSS)与 'tencent'(腾讯云 COS),四者的 cdn 字段不同。
TOS(火山引擎)
cdn: {
accessKeyId: '...',
secretAccessKey: '...',
region: 'cn-beijing',
bucket: '...',
baseUrl: 'https://cdn.example.com',
}
| 配置项 | 类型 | 说明 |
|---|---|---|
cdn.accessKeyId |
string |
TOS AccessKeyId |
cdn.secretAccessKey |
string |
TOS SecretAccessKey |
cdn.region |
string |
地域,如 cn-beijing |
cdn.bucket |
string |
Bucket 名称 |
cdn.baseUrl |
string |
CDN 访问域名 |
七牛云 Kodo
cdn: {
accessKey: '...',
secretKey: '...',
bucket: '...',
region: 'z0', // 可选,默认 z0 华东
baseUrl: 'https://cdn.example.com',
}
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
cdn.accessKey |
string |
必填 | 七牛 AccessKey |
cdn.secretKey |
string |
必填 | 七牛 SecretKey |
cdn.bucket |
string |
必填 | 空间(Bucket)名称 |
cdn.region |
QiniuRegion |
'z0' |
存储区域,决定上传域名(见下表) |
cdn.baseUrl |
string |
必填 | CDN 访问域名 |
七牛存储区域代号(region):
| 代号 | 区域 |
|---|---|
z0 |
华东-浙江(默认) |
cn-east-2 |
华东-浙江2 |
z1 |
华北-河北 |
z2 |
华南-广东 |
na0 |
北美-洛杉矶 |
as0 |
亚太-新加坡(原东南亚) |
ap-southeast-2 |
亚太-河内 |
ap-southeast-3 |
亚太-胡志明 |
阿里云 OSS
cdn: {
accessKeyId: '...',
accessKeySecret: '...',
region: 'oss-cn-hangzhou',
bucket: '...',
baseUrl: 'https://cdn.example.com',
}
| 配置项 | 类型 | 说明 |
|---|---|---|
cdn.accessKeyId |
string |
阿里云 AccessKeyId |
cdn.accessKeySecret |
string |
阿里云 AccessKeySecret |
cdn.region |
string |
地域(endpoint 后缀),如 oss-cn-hangzhou / oss-cn-shanghai / oss-cn-beijing |
cdn.bucket |
string |
Bucket 名称 |
cdn.baseUrl |
string |
CDN 访问域名 |
腾讯云 COS
cdn: {
secretId: '...',
secretKey: '...',
region: 'ap-guangzhou',
bucket: 'static-img-1250000000', // {名称}-{APPID} 格式
baseUrl: 'https://cdn.example.com',
}
| 配置项 | 类型 | 说明 |
|---|---|---|
cdn.secretId |
string |
腾讯云 SecretId |
cdn.secretKey |
string |
腾讯云 SecretKey |
cdn.region |
string |
存储桶地域,如 ap-guangzhou / ap-shanghai / ap-beijing |
cdn.bucket |
string |
存储桶名称({名称}-{APPID} 格式) |
cdn.baseUrl |
string |
CDN 访问域名 |
通用配置
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
localDir |
string |
'src/static' |
本地静态资源目录 |
cdnPrefix |
string |
'static/' |
CDN 上的路径前缀 |
excludeDirs |
string[] |
['icon/tabBar'] |
排除上传的目录 |
extensions |
string[] |
['.png', '.jpg', '.jpeg', '.gif', '.webp'] |
上传的文件类型 |
keepDirs |
string[] |
['icon/tabBar'] |
构建后保留的 static 子目录 |
插件选项说明
除
fileExtensions外,mapFile/outputDir/keepDirs未在插件选项中指定时,会自动从uni-cdn.config.ts中读取(优先级:插件选项 > 配置文件 > 内置默认)。推荐只在配置文件中维护一份,插件选项仅用于个别覆盖。
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mapFile |
string |
'cdn-map.json' |
映射表文件路径 |
outputDir |
string |
'dist/build/mp-weixin' |
构建产物目录 |
keepDirs |
string[] |
['icon/tabBar'] |
保留不删除的目录 |
fileExtensions |
string[] |
['.wxml', '.wxss', '.js', '.xml', '.acss', '.axml'] |
需要替换路径的文件类型 |
autoUpload |
boolean |
false |
构建前自动上传静态资源(等价于先跑 uni-cdn upload),适用于 HBuilderX 发行等无法手动执行 upload 的场景 |
replaceInDev |
boolean |
false |
dev 运行模式也执行「上传 + 替换 + 清理」(默认仅发行模式生效),适用于 HBuilderX「运行到小程序模拟器」等 dev 场景 |
自动上传(autoUpload)与 dev 模式(replaceInDev)
默认插件只在「发行模式」(production)生效。手动跑 uni-cdn upload + 发行构建是基本用法;开启下面两个选项可实现全自动。
autoUpload:构建前自动上传
开启后,每次构建开始前会自动执行一次上传(等价于先跑 uni-cdn upload,有 hash 缓存,未变化的文件会秒过),无需再手动跑命令。命令行 npm run build:mp-weixin 与 HBuilderX「发行」都会触发:
cdnReplacePlugin({
outputDir: 'dist/build/mp-weixin', // 构建产物目录
keepDirs: ['icon/tabBar'], // 保留不上传的目录(如 tabBar 图标)
autoUpload: true, // 构建前自动上传静态资源到 CDN
})
replaceInDev:打 dev 包时也上传 + 替换
默认插件只在发行模式生效,dev(运行模式)不触发——这是刻意的:开发调试时图片应走本地以便即时预览。若需要打 dev 包时也自动上传并替换,额外开启 replaceInDev: true。
命令行的 npm run dev:mp-weixin、HBuilderX 的「运行到小程序模拟器」都属于 dev 模式,开启后两者都会自动上传 + 替换。
注意:HBuilderX 项目的「运行」与「发行」产物目录不同(unpackage/dist/dev/ 与 unpackage/dist/build/),需按构建模式切换 outputDir(mode 由构建器自动传入,无需手动判断):
export default (command, mode) => {
const isProd = mode === 'production' // 发行=production,运行=development,自动传入
return {
plugins: [
cdnReplacePlugin({
// 运行(dev)与发行(build)的产物目录不同,按模式自动切换
outputDir: isProd
? 'unpackage/dist/build/mp-weixin' // 发行产物目录
: 'unpackage/dist/dev/mp-weixin', // 运行(dev)产物目录
keepDirs: ['icon/tabBar'], // 保留不上传的目录(如 tabBar 图标)
autoUpload: true, // 构建前自动上传
replaceInDev: true, // dev 运行模式也上传+替换(打 dev 包也走 CDN)
}),
],
}
}
⚠️ 开启
replaceInDev后,dev 调试时图片将走 CDN 加载(网络图片),CDN 或网络不可用会影响本地调试。
常见问题
Q: 为什么 tabBar 图标不上传 CDN? A: 微信/支付宝小程序的 tabBar 图标要求放在本地,不支持 CDN 路径,所以默认排除。
Q: 上传后代码里的路径没被替换?
A: 确保:1) 已执行 uni-cdn upload 生成了 cdn-map.json;2) 是在 production 模式下构建;3) 路径写法和映射表中的 key 一致(以 /static/ 开头)。
Q: 如何支持支付宝小程序?
A: 将插件的 outputDir 改为 dist/build/mp-alipay,fileExtensions 已经默认包含 .xml 和 .acss。
Q: Windows PowerShell 提示「无法加载 npx.ps1,因为在此系统上禁止运行脚本」?
A: 这是 PowerShell 默认执行策略(Restricted)拦截了 npm 的 .ps1 启动脚本,与工具本身无关。以当前用户身份执行一次即可解决:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
或者改用 cmd / Git Bash 执行命令(命令用法完全相同)。
License
MIT
Related Packages
适用于 uni-app (Vue3) 的 unplugin-vue-components,按需自动导入组件
Version History
| Version | Released | License |
|---|---|---|
| 1.0.0 | MIT |