Scratch 3.0二次开发:品牌Logo全面替换与多品牌配置实战
很多做Scratch 3.0二次开发的人第一步想改的就是品牌Logo。毕竟外壳是别人的至少得把门面换成自己的。但这篇文章是系列第三章我不打算只教你“把logo.png换掉”这么简单。真实场景里换Logo会牵扯到浏览器页签、加载页、菜单栏、作品缩略图、甚至帮助菜单、关于对话框、版权外链。这一章我会从“视觉触点”这个角度看整件事先讲清楚Logo在Scratch 3.0里到底存在于哪些位置再给出从静态资源到组件注入的两套替换方案最后是构建部署时最容易翻车的地方和排查经验。适合自己维护二开版本、或者要给客户做白标交付的开发者。1. 品牌Logo看似简单实际是一套“视觉触点”工程1.1 一张Logo背后藏着的六个可见位置我接过的几个教育类项目甲方提需求时总是说“帮我把左上角那个猫换掉”。等真正做完他们又会问“为什么浏览器标签上还是旧的”“为什么作品保存后的封面图还是官方那套”这就是典型的只换了“大Logo”没换“小触点”。在Scratch 3.0这种以GUI为核心的开源项目里品牌Logo至少出现在六个位置触点位置常见形式由什么控制加载页/启动画面大Logo居中或转圈动画前端图片资源或组件菜单栏左上角主Logo 项目名称Vue/React组件内引用浏览器页签图标favicon小图标index.html中link标签浏览器标题栏“Scratch 3.0”文字index.html中的title项目封面缩略图作品保存后的默认封面运行时截图或上传图片关于/设置弹窗版本号旁的小Logo弹窗组件这里面的坑点在于前三个是纯静态资源层面替换起来很快但第四、第五个往往涉及运行时逻辑可能需要改组件代码第六个又牵扯到链路跳转和协议合规。所以我建议任何团队做品牌定制前先按这张表逐一核对自己代码库里对应的位置搞出一份“品牌资产清单”。这个清单在后续官方升级合代码时尤其重要很多人升级完发现Logo被覆盖就是因为没记录这些触点。1.2 为什么Scratch 3.0的Logo替换不是“换张图”Scratch 3.0的前端主仓库是scratch-guiUI层用React实现底层还有scratch-vm、scratch-blocks、scratch-render等模块。虽然打包后最终产出一堆静态文件但源码层面Logo往往不是一张裸图而是作为一个图片资源被React组件引用、再经过Webpack处理。这带来两个直接影响第一你直接改打包产物体里的图片可能临时生效但下次重新build又会被源文件的图覆盖。因为浏览器运行时打开的是build目录真正控制构建产物的是源码目录里的静态资源。第二不同版本对Logo文件的引用方式不一样。老版本可能是static/assets/logo.png直接引用新版本可能改成带hash的文件名或者直接以Base64方式内联进JS。所以最稳妥的办法不是凭记忆猜路径而是先定位再修改。有个通俗类比Logo像是贴在车身上的品牌车标但车标支架组件引用、螺丝构建配置、甚至仪表盘上的车标favicon是分开的。只撕掉外面的大标里面该露馅还是会露馅。你真正要做的是把整条“品牌视觉链路”理清楚再动手。2. 开工前准备环境、资源定位与素材规范2.1 搭建干净的二次开发环境如果你是从零开始做二开建议用一套干净的源码环境而不是直接在官方打包产物上改。我通常的流程是git clone scratch-gui仓库地址 cd scratch-gui yarn install yarn buildNode版本建议锁定在16或18这两个LTS版本之间Scratch 3.0的依赖链偏老太新的Node可能会出现Webpack兼容问题。如果你只是临时想看一下改造效果yarn start启动开发模式就够了如果要交付部署包再用yarn build生成生产版本。这里要插一句个人经验强烈建议初始化时就把整个项目纳入自己的Git仓库。这样每次官方升级版本你都有diff可查也方便回滚。很多人直接在下载包里开改改到最后连自己改过哪些文件都说不清楚这个坏习惯在“Logo被新版本覆盖”时尤其致命。2.2 快速定位Logo相关资源在源码中的位置不同版本、不同分支下Logo资源路径会有差异与其照搬网络旧教程不如直接在源码里搜。我常用的命令是find . -iname *logo* -not -path ./node_modules/* find . -iname *favicon* -not -path ./node_modules/* find . -iname *icon* -not -path ./node_modules/*正常会看到类似这样的结构src/components/logo/logo.jsx src/containers/menu-bar.jsx static/assets/logo.svg static/favicon.ico public/index.html其中components/logo/logo.jsx是菜单栏里那个Logo组件的实现static/assets/logo.svg是实际的图片源文件public/index.html控制页面标题和页签图标。找到这几个关键点后你要替换的范围就很明确了。所以我一直反对一上来就找“logo.png在哪个文件夹”这种思路。正确做法是先根据文件结构理解引用链再判断是做资源替换、组件替换还是配置注入。理解链路比记住路径重要得多。2.3 品牌素材需要一套而不是一张很多人只准备了一张Logo图结果一会儿用在宽屏菜单栏一会儿缩到16×16页签图标一会儿又放到深色背景上看不清、变形、白边全都冒出来。我建议准备一套素材至少包括主Logo横版带文字或独立图标用于菜单栏方版图标用于favicon和加载页深色背景下的反白版SVG优先导出时保留export属性清晰的路径文件保留透明通道不要带白色底板SVG格式是最推荐的因为Scratch 3.0的界面里Logo会有多种展示尺寸SVG的矢量特性让它放大缩小都不发虚。如果你只有PNG至少也要准备256×256以上的高清版。画面上还要注意留白特别是favicon这种小尺寸场景内容太满会糊成一团。这套素材整理好之后才进入真正的替换环节。3. 核心实操从静态资源到React组件的Logo替换3.1 第一步静态资源同名覆盖法这个方法风险最小也是我优先推荐给初学者的方案。思路很直接找到源图把同名文件替换掉让构建时引用的一直是你自己的Logo。操作流程大致是先备份原来的Logo文件放到项目外的backup/目录。把你自己准备的Logo文件重命名为原文件相同的名字比如logo.svg覆盖到原来的路径下。重新启动开发模式或重新构建刷新页面观察菜单栏和加载页。如果还有残留全局再搜一次logo.png、logo2x.png这类文件可能是因为同一张图有多个尺寸版本。举个例子如果在static/assets/下有logo.svg你用自己的brand-logo.svg替换时直接重命名复制过去即可。构建时Webpack会把这文件当成原来的Logo打包。这一步为什么风险小因为你完全不碰React组件逻辑只是替换静态资源。后续升级官方代码时除非官方改名或改目录结构否则你的资源覆盖还能继续生效。缺点是不够灵活比如你想让不同用户看到不同Logo或者运行时动态切换品牌单纯改文件做不到这时候需要下面说的组件方案。3.2 第二步浏览器页签图标与页面标题这是经常被忽略的一步。不少项目改完菜单栏就以为大功告成结果浏览器标签页上还挂着一个官方favicon专业感立刻拉低。在Scratch 3.0的目录里页面模板通常是public/index.html或src/index.html里面会有这样的代码titleScratch 3.0/title link relicon typeimage/png href/favicon.png你要做的是把title改成自己品牌名比如“某某少儿编程平台”然后把favicon文件也换成自己品牌的方版图标。需要注意favicon的格式和文化16×16要清晰可辨纯色背景加单色图标通常比花花绿绿的设计效果好。改完之后重新build再打开浏览器看页签。有时候浏览器会缓存favicon你会以为自己没改成功。解决办法后面第4.3节会讲。3.3 第三步进阶方案——通过组件注入动态Logo静态资源覆盖法适合单品牌、单部署。但如果是做SaaS平台或“给多个机构定制版本”你就得让Logo变成一个变量而不是一张写死的图片。这时候要动React组件层。Scratch 3.0的菜单栏Logo组件大致长这样// components/logo/logo.jsx import logoIcon from ./logo.svg; const Logo ({ className }) ( div className{className} img src{logoIcon} altlogo / /div );想让它变成可配置的最直接的做法是把图片引用改成propsconst Logo ({ className, icon }) ( div className{className} img src{icon || logoIcon} altlogo / /div );然后在更上层的容器组件里从配置模块读取当前品牌对应的Logo地址再传进来。这样你就把Logo从“静态资源”变成了“运行时配置项”。这一步的关键不是怎么写组件而是“配置从哪来”。我习惯建一个brand.config.js文件里面统一放export default { brandName: 某某学堂, logo: /brands/edu-a/logo.svg, favicon: /brands/edu-a/favicon.ico, primaryColor: #2E7D32, };其他模块统一引用这个配置。后期换品牌、加品牌只改配置不改组件。说句实在话这一步做完你才真正拥有了“品牌定制”的能力而不仅仅是“换图”的手艺。3.4 第三步的补充让配色和字体同步品牌化只换LogoUI依然是Scratch默认的蓝橙配色和官方字体其实会有明显的拼凑感。尤其是菜单栏区域Logo周围如果还是别人的品牌色用户一眼就觉得很“山寨”。Scratch 3.0的UI颜色主要集中在主题文件和CSS变量里。你可以通过全局覆盖的方式把主色、辅色、菜单栏背景色改成自己品牌的指定色。比如在入口文件里引一个brand.css.menu-bar { background-color: #f7f7f7; border-bottom: 1px solid #e0e0e0; }不过这属于临时手段。更体系化的做法是把品牌色写入主题配置比如定义一组theme对象里面包含主色、成功色、危险色、文字色。这样积木区、按钮、菜单栏都会跟着变不会出现“Logo变了但按钮还是橙色”的尴尬。我的经验是配色不是越浓越好。Scratch 3.0的界面元素密度很高如果品牌色太艳用户会觉得拥挤和刺眼。建议保留官方的浅色底、中性色只把主操作按钮、Logo区域、高亮边框做品牌化处理。很多二开产品最终效果不高级就是因为什么都想改成自己的颜色结果视觉噪音翻倍。4. 构建、部署与验证别让Logo在最后一公里翻车4.1 本地构建验证清单替换完Logo别急着交付。先在本地完整走一遍构建别只用开发模式看效果就一直觉得行了。我的验证清单大致是yarn build能正常通过没有资源引用报错。打开build/index.html菜单栏Logo正确显示。浏览器页签favicon正确显示标题文字变成品牌名。强制刷新页面加载过程没有明显404请求。用无痕窗口再开一遍排除缓存干扰。随机进入项目编辑页保存一次看看缩略图是否正常。其中第3步和第5步尤其值得注意。favicon缓存是常见“假性失败”而开发模式下一切正常、build后资源404多半是publicPath路径没配好或者静态资源没被copy插件复制进去。4.2 部署阶段最容易漏掉的四个地方部署到服务器后很多问题在本地是发现不了的。我列几个高频坑位静态资源相对路径如果你的平台部署在子路径下比如http://host/edu但资源引用带了绝对根路径/static/...就会出现404。这时候需要调整Webpack的publicPath。favicon请求超时或404这个文件虽然小但一旦404浏览器会在控制台里持续报错虽然不一定影响界面但会拖慢网络日志的排查效率。页签标题被框架覆盖有些二次开发版本在IDE里嵌套了一套自己的壳外部壳已经把index.html的title覆盖成别的名字你改了Scratch的title自然看不到变化。帮助菜单和版本更新链接很多二开端到生产后底部还带着“关于Scratch”“访问社区”之类的跳转链接。这些不是Logo但比Logo更容易暴露“这是别人家产品”的马脚。我记得有个客户上线后才发现点帮助菜单直接跳到官方社区观感非常分裂。其中第四点最容易被“非技术需求”触发。品牌交付时一定要逐个排查菜单栏里所有带外链的入口要么替换成自己的帮助中心地址要么直接隐藏。4.3 缓存和路径替换后不生效的高频原因这一节单独拿出来讲是因为“改了文件没反应”几乎是所有二开新手都会遇到的问题。原因通常有两个浏览器缓存和构建缓存。浏览器缓存的典型表现是刷新页面后Logo还是旧的但用无痕窗口打开就是新的。解决方式是不用慌等缓存过期就行了或者手动给资源URL加版本参数link relicon typeimage/png href/favicon.png?v20250101只要改动文件的版本号浏览器就会当新资源重新拉取。更专业的办法是构建时给静态资源生成文件hashWebpack本身对带[contenthash]命名的资源会自动处理但favicon这种直接在HTML里写死的文件不会自动带hash需要你手动改。构建缓存的典型表现是源码里改了文件名但build出来的文件还是老内容。这种时候多半是启动了持久化缓存。最粗暴的解法是删除node_modules/.cache之类的目录再重新build或者检查Webpack配置里是否开启了cache: true。5. 常见问题排查速查表与避坑实录5.1 一张表解决大多数替换问题下面这张表是我在实际项目里整理出来的基本涵盖了替换Logo时90%的问题。你可以直接截图存下来遇到问题对照排查。症状可能原因解决方向菜单栏Logo变了页签图标没变只改了主体文件没改favicon重新替换favicon并强制刷新改完源码build后还是旧Logo构建缓存或文件名hash未更新清构建缓存或给资源URL加参数页面标题始终显示Scratch 3.0title被外层框架覆盖检查部署壳模板改外层title作品缩略图仍是官方风格缩略图是运行时截图不是静态图修改默认缩略图逻辑或在保存时生成自定义封面Safari下Logo显示模糊使用了位图而非矢量图尽量换SVG或准备2x高清版本控制台报favicon 404favicon路径不对或文件未复制检查copy插件与publicPath帮助菜单跳转官方页面外链配置未清理替换为自建帮助中心或隐藏入口这表里我想重点讲一下“作品缩略图”。很多二开产品忘记处理这个点导致用户建了一个新项目在作品列表里看到的封面缩略图还是官方默认样式这种割裂感对品牌形象非常致命。缩略图的生成通常有两种路径一种是用浏览器截取舞台区的截图另一种是项目内嵌的图片元数据。如果你不做干预默认封面就会一直沿用官方设计。要彻底解决就得在创建项目时初始化一个自定义的封面或者在后台上传默认封面图。5.2 关于对话框、版权信息这些容易忽略的细节品牌Logo做到最后最抠细节的地方往往在“关于”弹窗。用户点击菜单栏的“关于”弹出来的对话框里写着官方版权信息、版本号、甚至官方Logo。这种地方不处理前面的替换功夫就白费一半。处理方式建议分两步第一步把关于弹窗里的Logo图片和文字说明替换成自己的品牌信息第二步保留原有开源协议声明。注意Scratch 3.0是开源项目你可以改界面、改Logo但协议要求的版权声明不能随意删除。合规做法是在某个角落保留原文声明再放上自己产品的版权信息这样既合法又体面。还有一个很容易漏的地方是打包后的应用名称。如果你的产品还要做成离线桌面应用或移动端壳那么系统层面的应用名、启动图标也需要跟着改。这不在scratch-gui源码范围内但交付时一定会被问到。6. 更进一步用配置实现多品牌一键切换6.1 把品牌元素抽成独立配置如果你的团队同时给多个机构交付不同品牌的Scratch版本复制整份代码再一套套改Logo会让你崩溃。正确的路子是把品牌相关元素抽到一个配置模块里。我建议的配置结构是这样// brand.config.js const brands { eduA: { name: 某某学堂, logo: /brands/edu-a/logo.svg, favicon: /brands/edu-a/favicon.ico, primary: #2E7D32, helpUrl: https://help.example-a.com, }, eduB: { name: 某某编程, logo: /brands/edu-b/logo.svg, favicon: /brands/edu-b/favicon.ico, primary: #1565C0, helpUrl: https://help.example-b.com, }, }; export default brands[process.env.REACT_APP_BRAND] || brands.eduA;这样所有组件从配置里读取品牌信息而不是在代码里写死Logo路径。替换品牌、新增品牌都变成改配置而不用碰页面代码。这个思路的精髓是把“改代码”变成“改配置”。第一次配置可能要多花一点时间但后续维护的边际成本极低。尤其是团队里有非前端背景的交付人员时他们只需要改配置文件里的Logo和颜色不用动任何React代码。6.2 按品牌构建一条命令出不同皮肤抽好配置之后剩下的就是构建时注入。Scratch 3.0基于React开发环境改造而来支持通过环境变量在构建时区分品牌。配合Webpack的DefinePlugin配置可以这样处理new webpack.DefinePlugin({ process.env.REACT_APP_BRAND: JSON.stringify(process.env.REACT_APP_BRAND || default), }),然后在打包命令里指定品牌REACT_APP_BRANDeduA yarn build REACT_APP_BRANDeduB yarn build出来的两个build目录分别自带不同Logo、不同标题、不同配色。这一步做完你从“单个Logo替换”升级成了“一套品牌工程体系”。有了这套体系后续再想换皮肤、换字体、换主题色都能顺着配置往下走。你不需要每接一个客户都重新研究一遍Scratch源码这也是我认为“品牌定制”真正该有的状态。7. 几次二开项目下来我的几点体会文章最后说点我自己踩坑的经验。第一次做Scratch品牌定制时我也觉得这活太简单了不就是换图吗。结果那周至少有三分之二的时间花在了收尾上比如favicon不变、浏览器标题不对、关于弹窗被忽略还有那该死的帮助菜单外链。从那以后我给自己定了一个规矩凡是做品牌定制必须按第1.1节那张触点表逐项验收一项都不能少。第二个体会是能覆盖资源就优先覆盖资源不要一上来就改组件。改组件虽然看起来更“高级”但它会把你的代码和官方代码缠在一起每隔几个版本就冲突一次。资源覆盖法虽然朴素但升级痛苦最小。真的需要动态品牌时再考虑组件注入和配置化。第三点是交付时别只给一个build目录。把品牌配置、素材命名规范、替换说明、以及对应的代码diff一起给出去。因为对方后续大概率会找你改颜色、改文字你把配置和流程理顺后续沟通成本才能压下来。这个习惯救了我很多次。Logo这件事说到底是二开产品里最显眼的一层皮。皮换好了用户会觉得整个产品都是你的皮没换干净用户一眼就看出你是个套壳。希望这一章的内容能帮你把品牌定制这条路走顺。