资源压缩需分阶段协同执行:代码压缩、资源剔除、文件级压缩须按序进行;依赖前置条件(如Android需shrinkResources与minifyEnabled共启);按类型匹配最优策略(WebP/SVGO/Terser等);显式保留动态引用内容;并量化验证压缩效果。

构建工具配置是资源压缩最直接、最可控的入口。关键不在于堆砌插件,而在于理解每个环节的压缩逻辑和协同关系——代码压缩、资源剔除、文件级压缩,三者必须分阶段、有顺序地执行。
明确压缩阶段与依赖关系
资源压缩不是“一键开关”,它依赖前置条件才能生效:
- Android中,shrinkResources true 必须配合 minifyEnabled true,否则资源压缩器无法识别哪些资源真正未被引用
- 前端构建中,Terser或esbuild压缩JS前,需先完成Tree-shaking(移除未引用模块),否则压缩只是“把冗余代码压得更小”
- Jekyll使用jekyll-minifier时,CSS和HTML压缩需在Sass编译完成、Liquid模板渲染完毕后进行,否则可能压缩未生成的中间产物
按资源类型匹配最优压缩策略
不同资源适用不同工具和参数,硬套统一方案反而适得其反:
- 图片:优先转WebP(Android Studio Image Asset Studio / Squoosh / gulp-imagemin),启用渐进式加载+元数据剥离;SVG用svgo做结构精简
- JS/CSS/HTML:Vite默认用esbuild压缩,适合开发构建;生产环境若需更高压缩率,可切换为Terser并开启compress.drop_console(删console)和compress.passes(多轮压缩)
- 多语言资源:ThingsBoard通过esbuild插件自动扫描./src/assets/locale/下所有.json文件,仅打包实际声明的语言列表(SUPPORTED_LANGS),避免全量嵌入
保留机制必须显式声明
自动化压缩会误删动态引用内容,必须主动干预:
- Android中,在
res/raw/keep.xml里用tools:keep标记运行时通过getIdentifier()加载的资源名 - 混淆时,对反射调用的类、JSON序列化实体、WebView JS接口类,用
-keep class com.xxx.** { *; }保留 - 前端构建中,动态
import()的路由模块需在vite.config.ts的build.rollupOptions.output.manualChunks中显式归组,防止被拆分到不可预测的chunk里
验证与持续监控不能跳过
压缩效果必须量化,而非凭感觉判断:
- 每次构建后用APK Analyzer(Android)或source-map-explorer(前端)查看体积构成,重点关注占比超10%的模块
- 设置CI流水线检查:例如要求图片压缩后体积下降≥40%,否则阻断发布
- 保留一份未压缩的构建产物用于比对,尤其关注字体文件、图标雪碧图、第三方SDK资源是否异常丢失

















