flutter_flutter 模板图片资产管理指南:基于 flutter_template_images 的双仓库工作流
跨平台前端移动开发OpenHarmony【免费下载链接】flutter_flutter本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。项目地址https://gitcode.com/CPF-Flutter/flutter_flutter点击查看免费下载本文面向 flutter_flutterFlutter 的 OpenHarmony 适配版本的贡献者与二次开发者系统讲解flutter工具模板中图片资源的维护机制为什么图片不能直接提交进主仓库、flutter_template_imagesPub 包在其中扮演的角色、以及新增/更新模板图片时需要在flutter/packages与flutter/flutter两个仓库分别执行的完整操作步骤。读完本文你将掌握.img.tmpl占位符与template_manifest.json清单的配合方式并能独立完成一次模板图片的发布与回滚。为什么模板图片不直接入库flutter工具在生成新项目flutter create时会向目标工程写入大量模板文件其中包含各平台的图标、启动图等二进制资源如 iOS 的AppIcon、macOS 的应用图标、Windows 的app_icon.ico、Web 的 maskable icon 等。这些图片资源并没有直接存放在 flutter_flutter 主仓库中而是统一维护在flutter_template_images这个 Pub 包内。这一设计有两个直接原因Presubmit 检查禁止二进制文件入库。主仓库的静态检查verifyNoBinaries见 dev/bots/analyze.dart会逐个读取 Git 跟踪文件并以 UTF-8 解码凡无法解码为合法 UTF-8 的内容都被判定为二进制而报错。该检查的错误提示中明确写着All files in this repository must be UTF-8. In particular, images and other binaries must not be checked into this repository并直接引用本指南作为解决方案。仓库体积与升级成本。二进制文件会显著增大仓库体积且每次更新都会产生巨大的 diff。flutter_flutter 仓库会随版本被广大开发者同步执行flutter upgrade时需要对整个 Git 历史做增量同步体积膨胀会直接拖慢所有人的升级体验。而从 Pub 拉取一个包只需下载对应版本内容不涉及 Git 历史的全量同步明显更轻量。从本仓库的实际结构也能印证这一点以 packages/flutter_tools/templates/app/ios.tmpl/Runner/Assets.xcassets/AppIcon.appiconset 为例目录下只有Contents.json是真实文件而Icon-App-20x201x.png.img.tmpl、Icon-App-1024x10241x.png.img.tmpl等所有图标都只是零字节占位符真正的内容在flutter_template_images包中。双仓库工作流总览新增或更新模板图片需要同时提交两个补丁patch分别落在两个仓库flutter/packages 仓库修改flutter_template_images包把真实图片文件放入其templates目录并发布新版本到 Pub。flutter/flutter 仓库即本仓库把依赖版本提升到新发布的版本同步添加占位符与清单条目让flutter工具在生成项目时能正确解析到新图片。flutter_template_images包内的templates目录布局与 flutter_flutter 仓库中flutter_tools包下的 templates 目录完全一致先向flutter_template_images提交真实图片再回滚进主仓库保证两处路径一一对应。回滚时flutter_tools包中的占位文件只是同名零字节文件文件名含.img.tmpl后缀真实二进制仍留在 Pub 包里。第一步向 flutter_template_images 添加资源1. 分叉 flutter/packages 仓库在 GitHub 上 fork flutter/packages 仓库若未配置 GitHub 亦可参考该仓库的本地镜像流程在本地检出后进入packages/flutter_template_images目录操作。2. 按目标路径放置图片将图片放到templates目录下与 flutter_flutter 主仓库对应的相对路径。命名规则有三点要求文件名必须与flutter工具生成项目后的最终文件名完全一致因为模板渲染时不会做任何改名不要包含.img.tmpl后缀——该后缀只出现在主仓库的占位符中真实图片文件用的是最终名例如主仓库占位符是app_icon.ico.img.tmpl包内真实文件就叫app_icon.ico目录层级要与flutter_tools/templates严格对齐例如 iOS 图标要放在templates/app/ios.tmpl/Runner/Assets.xcassets/AppIcon.appiconset/下。3. 升级 pubspec.yaml 版本号编辑该包的pubspec.yaml版本号为major.minor.patch三段式规则是新增图片资源递增 minor 版本如5.0.0→5.1.0仅更新已有图片递增 patch 版本如5.0.0→5.0.1。这个规则与本仓库中flutter_template_images的 pin 位置相互印证主仓库pubspec.yaml中声明flutter_template_images: 5.0.0见 packages/flutter_tools/pubspec.yaml同时手工 pin 集中在kManuallyPinnedDependencies表中注释写明Must always exactly match flutter_tools template见 packages/flutter_tools/lib/src/update_packages_pins.dart。4. 更新 CHANGELOG.md在包的CHANGELOG.md顶部为本次版本新增一个标题条目并添加一行描述变更内容。格式遵循 docs/ecosystem/contributing/README.md#changelog-style 的规范该目录页同时说明了 packages 仓库采用持续发布模型、绝大多数发布型变更都必须更新版本号与 CHANGELOG 的纪律。5. 提交并发送 Pull Request提交改动建议仅包含图片、版本号、CHANGELOG 三类文件推送后发送 PR。合入后post-submit 作业会自动把新版本发布到 Pub无需手动执行发布命令。你可以在flutter_template_images包页面Pub 上的Versions标签页确认新版本是否已成功发布——只有发布成功后主仓库才能依赖到它。第二步将变更回滚进 flutter_flutter 主仓库新版本在 Pub 发布后开始在 flutter_flutter 仓库中回滚。1. 分叉 flutter/flutter 仓库并更新依赖 pinfork flutter_flutter 仓库后需要修改依赖版本声明。原指南指向update_packages.dart而在当前仓库中手工固定pin的依赖统一集中在 packages/flutter_tools/lib/src/update_packages_pins.dart 的kManuallyPinnedDependencies表中把flutter_template_images的条目从旧版本改为新版本。同时 packages/flutter_tools/pubspec.yaml 中的依赖声明也会随之更新。需要特别强调的是该表中的 pin必须是精确版本而非版本范围源码注释明确指出 ranges 会使 CI 随机失败并可能让用户无法升级 Flutter因此这里必须写入与包版本完全一致的精确版本号。2. 运行依赖更新命令在仓库根目录执行flutter update-packages --force-upgrade该命令会基于kManuallyPinnedDependencies重新解析并锁定额外依赖。从 packages/flutter_tools/lib/src/commands/update_packages.dart 的源码可以看到--force-upgrade是UpdatePackagesCommand的核心旗标之一文件头部的注释还说明Pub 包的例行升级由flutter-pub-roller-bot通过flutter update-packages --force-upgrade自动完成人工执行时同样走这条命令。3. 添加零字节占位文件对于你在flutter_template_images中新增的每一个图片文件都在flutter_tools包的 templates 目录的对应位置放一个零字节文件文件名加上.img.tmpl后缀。例如新增 iOS 启动图就在templates/app/ios.tmpl/Runner/Assets.xcassets/LaunchImage.imageset/下创建LaunchImage.png.img.tmpl。零字节占位的好处是不携带任何二进制内容能通过 UTF-8 检查模板引擎看到.img.tmpl后缀时也不会对其做 mustache 渲染而是从图片包中复制真实文件覆盖它。4. 更新 template_manifest.json编辑 packages/flutter_tools/templates/template_manifest.json在files数组中为每个新增文件添加一条记录路径必须包含.img.tmpl后缀。该清单文件的_comment字段说明了对应关系Files ending in .img.tmpl correspond to files checked in to the flutter_template_images package ... located at the same path, excluding the .img.tmpl suffix.清单的作用在 packages/flutter_tools/lib/src/commands/create_base.dart 中体现_computeTemplateManifest()读取该 JSON把所有files条目解析为绝对路径 URI 集合随后 packages/flutter_tools/lib/src/template.dart 在遍历模板目录时会跳过清单中不存在的文件从而清理掉flutter_tools目录里的过期文件。这保证了清单驱动模板的一致性。5. 测试运行并提交 PR提交改动后先在本仓库内实际执行一次模板生成做冒烟测试确认新图片能被flutter工具正确产出到生成的项目中。验证无误后再发送 PR。若 PR 中缺少占位符或清单条目CI 会拦截集成测试 packages/flutter_tools/test/integration.shard/template_manifest_test.dart 会递归扫描templates目录中的所有文件并与template_manifest.json声明的清单求差集任何存在但未声明的文件都会导致manifest and template directory should be in-sync断言失败。模板引擎如何消费图片资源理解.img.tmpl的语义对排查问题很有帮助。模板渲染的核心实现在 packages/flutter_tools/lib/src/template.dart其类注释定义了整套后缀约定后缀含义.tmpl需要 mustache 渲染后写出.copy.tmpl无需渲染直接按原样复制.img.tmpl从flutter_template_images包复制对应图片.test.tmpl仅当启用--implementation-tests时才包含在渲染流程Template.render见 template.dart中凡源文件以.img.tmpl结尾引擎会遍历imageSourceDirectories找到去掉.img.tmpl后缀后的相对路径对应的真实图片文件直接copySync到目标位置若找不到则抛出Image File not found的 ToolExit。目标文件路径在写出前会把.tmpl、.copy.tmpl、.img.tmpl、.test.tmpl后缀全部剥掉见 template.dart所以最终工程里出现的是干净的真实文件名。图片目录的定位逻辑在TemplatePathProvider.imageDirectory见 template.dart它读取flutter_tools/.dart_tool/package_config.json按包名flutter_template_images找到packageUriRoot取其父目录下的templates目录作为图片根目录。换言之图片解析完全依赖 Dart 包配置——这也解释了为什么主仓库必须先升级依赖并重新执行update-packages否则新图片根本无法被解析。同样的思路也出现在 iOS 打包逻辑中IOSApp注释写明Template assets images are in flutter_template_images package见 packages/flutter_tools/lib/src/ios/application_package.dart。本仓库的适配现状与验证线索作为 OpenHarmony 适配版本flutter_flutter 保留了整套图片资产管理机制同时扩展了 OpenHarmony 模板。可以从以下几处快速验证当前状态依赖 pinflutter_template_images: 5.0.0同时出现在 pubspec.yaml 与 update_packages_pins.dart 中且注释强制要求与模板严格同步。占位符分布find可列出 packages/flutter_tools/templates 下全部.img.tmpl占位符覆盖 iOSIcon-App-*、LaunchImage*、macOSapp_icon_*、Windowsapp_icon.ico.img.tmpl、WebIcon-maskable-*.png.img.tmpl等平台。清单文件template_manifest.json 中templates/app/ohos.tmpl/...、templates/module/ohos/...、templates/plugin/ohos.tmpl/...等 OpenHarmony 模板条目已被纳入files数组与适配版模板共存。渲染过滤在 template.dart 的renderPath中ohos与android、ios、web、linux、macos、windows并列只有创建 OpenHarmony 工程--platformsohos场景时ohos.tmpl目录下的内容才会被展开说明 OpenHarmony 模板已深度融入同一套模板管线。从源码结构还可以看到OpenHarmony 模板目录如templates/app/ohos.tmpl/AppScope/resources/base/media/app_icon.png、entry/src/main/resources/base/media/icon.png当前以真实 PNG 文件直接放在templates目录下并由清单直接列出未采用.img.tmpl占位方式与 iOS/macOS 等平台的占位符策略有所不同——这是适配版当前的实际情况后续若要统一管理 OH 图标资源可参照本文工作流迁移到flutter_template_images。小结模板图片资产的维护是一条清晰的包内放真图、仓库放占位的双仓库流水线在flutter_template_imagesflutter/packages按最终文件名放置真实图片按新增 minor / 更新 patch规则升级版本更新 CHANGELOG合入 PR 后由 post-submit 自动发布到 Pub在 flutter_flutter 主仓库更新精确版本 pin集中在kManuallyPinnedDependencies执行flutter update-packages --force-upgrade为每张图片添加同名零字节.img.tmpl占位符并在 template_manifest.json 中登记清单条目依赖template_manifest_test.dart与verifyNoBinaries等 CI 检查兜底确保清单与目录同步、仓库不混入二进制。掌握这套流程后无论是为 flutter_flutter 的 OpenHarmony 模板补充图标还是为既有平台模板替换应用图标都能以最小的仓库体积代价、最快地让flutter create生成出带新资源的工程。赞分享跨平台前端移动开发OpenHarmony【免费下载链接】flutter_flutter本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。项目地址https://gitcode.com/CPF-Flutter/flutter_flutter点击查看免费下载相关推荐Espanso资源管理终极指南高效处理图片、模板与资产的完整攻略Espanso资源管理终极指南高效处理图片、模板与资产的完整攻略 Espanso作为一款跨平台文本扩展工具不仅能帮你快速输入常用文本还能高效管理各类资源。桌面应用CLIFlutter 模板镜像资源管理指南flutter_template_images、.img.tmpl 占位符与模板清单机制Flutter 模板镜像资源管理指南flutter_template_images、.img.tmpl 占位符与模板清单机制 flutter create 生跨平台移动开发前端UI组件桌面应用Novu 仓库并行实现工作流基于 Git worktree 的垂直切片Vertical Slice多 Agent 协作指南Novu 仓库并行实现工作流基于 Git worktree 的垂直切片Vertical Slice多 Agent 协作指南 本文讲解 Novu 开源仓库内后端消息路由前端通信AI Agent上一篇Wireshark自动化测试终极指南环境变量配置与CI集成完整教程下一篇Metalsmith环境变量配置开发/生产环境无缝切换方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Java大厂面试实录:从Spring Boot自动装配到RAG链路设计全复盘

Java大厂面试实录:从Spring Boot自动装配到RAG链路设计全复盘

上个月面了一家做在线交易平台的头部互联网公司,一面开始没多久,面试官就对着简历问了一个让我措手不及的问题:“你说你的服务是从Spring Boot单体架构起步的,那项目启动之后,Spring容器里到底按什么顺序把这些Bean装配…

2026/10/15 6:46:49 阅读更多 →
超微 X12DAI-N6 主板装机避坑指南:从跳线到 BIOS 实战

超微 X12DAI-N6 主板装机避坑指南:从跳线到 BIOS 实战

简介:超微 X12DAI-N6 主板用户手册面向服务器运维、数据中心部署及高性能计算平台的硬件工程师与装机人员,用于解决主板规格查询、组件安装与故障排查等实际问题。手册围绕 Intel Xeon Scalable 处理器支持、多通道 DDR4 ECC 内存插槽、PCIe 扩展槽、SAT…

2026/10/15 6:45:49 阅读更多 →
基于Simulink的三机九节点风电调频仿真:下垂与虚拟惯性控制实现

基于Simulink的三机九节点风电调频仿真:下垂与虚拟惯性控制实现

做风电并网调频仿真的朋友,多半都经历过这个阶段:拿到一个风机模型,在下垂控制里改个系数,跑完看着频率曲线心里想着“这回总该成了”,结果被人问了一句“你的惯性响应呢”,当场愣住。我这次在Simulink里搭…

2026/10/15 6:45:49 阅读更多 →

最新新闻

模板渲染报错如何快速定位:从字段路径到错误码的三层消息治理实践

模板渲染报错如何快速定位:从字段路径到错误码的三层消息治理实践

做模板系统好几年,我发现自己最不想看但又不得不看的代码,不是模板解析器,不是渲染引擎,而是那一堆堆"报错分支"。尤其是消息模板、通知模板这类业务系统,上线前大家盯的是参数能不能渲染成功,没…

2026/10/15 7:31:57 阅读更多 →
多传感器信息融合前四章:从物理本质到工程决策的地基构建

多传感器信息融合前四章:从物理本质到工程决策的地基构建

1. 这本《多传感器信息融合及应用》到底在讲什么,为什么值得花时间啃前四章“多传感器信息融合及应用”——光看这个书名,很多人第一反应是:又一本理论厚重、公式密集的教材。但如果你正在做智能感知系统、无人平台导航、工业状态监测&#x…

2026/10/15 7:31:57 阅读更多 →
C++与物联网端侧开发:从裸机到工程化的架构实践

C++与物联网端侧开发:从裸机到工程化的架构实践

这两年和物联网端侧打交道比较多,从最开始用裸机C写采集程序,到后来把整个协议栈和任务管理迁移到C,我最大的感受是:C和物联网开发的组合,不是“用更高级的语言写单片机”这么简单,而是整个工程组织方式在变…

2026/10/15 7:31:57 阅读更多 →
布隆过滤器如何根治缓存穿透:原理、误判率与工程落地

布隆过滤器如何根治缓存穿透:原理、误判率与工程落地

先说一个我印象特别深的场景。某个深夜值班,监控屏上数据库的QPS曲线突然拉成一条直线,连接池排队数肉眼可见地涨,接口超时率从 0 直接跳到百分之十几。当时第一反应是流量突增,结果把网关日志翻了一遍,发现同一批根本…

2026/10/15 7:31:57 阅读更多 →
MNIST手写数字识别:全连接网络的底层原理与实操诊断

MNIST手写数字识别:全连接网络的底层原理与实操诊断

1. 这不是“抄代码”,而是一次深度学习的底层认知重建你打开《21个项目玩转深度学习》第三章,看到“手写数字识别”几个字,心里可能想:不就是调个keras.Sequential(),加几层Dense,跑个model.fit()吗&#x…

2026/10/15 7:31:57 阅读更多 →
在线问诊系统源码搭建:问诊单状态机、WebRTC与消息可靠性实践

在线问诊系统源码搭建:问诊单状态机、WebRTC与消息可靠性实践

去年接了个模拟项目,帮某医疗信息化团队从零搭一套在线问诊系统源码级的Demo。最初大家以为这活儿和做电商订单差不多,无非患者下单、医生接单、聊天室答疑。真正把需求和业务规则捋完才发现,视频/图文问诊平台搭建步骤里最难的从来不是音视频…

2026/10/15 7:30:57 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →