ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Carbon Trigger 浏览器扩展完整代码解析:基于 CO2 Signal API 构建电力碳排放监控扩展

2026/9/10 12:51:54 拓冰建站 浏览量
Carbon Trigger 浏览器扩展完整代码解析:基于 CO2 Signal API 构建电力碳排放监控扩展 Carbon Trigger 浏览器扩展完整代码解析基于 CO2 Signal API 构建电力碳排放监控扩展【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners本指南以 Web-Dev-For-Beginners 开源课程中 5-browser-extension/solution 的完整代码为核心系统讲解如何基于 tmrow 的 CO2 Signal API 构建一款浏览器扩展它能够在浏览器扩展栏中实时显示你所在区域的电力碳排放强度并通过彩色圆点图标给出直观反馈帮助你决定何时进行洗衣机烘干等高耗电活动。读完本文你将掌握扩展的构建与安装流程npm webpack Edge Load Unpacked、API 密钥与区域代码的配置方法以及完整源码中颜色映射算法、localStorage 持久化与后台脚本消息通信的底层实现。项目背景为什么需要一个碳触发扩展Carbon Trigger 的核心思想来自微软绿色云倡导团队最初是一个网站项目。该扩展调用 CO2 Signal API 追踪指定区域的电力使用情况把当前区域电网有多脏这一抽象数据转化为浏览器扩展栏中一枚直观的彩色圆点。用户可以随时ad hoc唤起扩展根据实时数据判断当下是否适合执行耗电活动——例如在区域电力负载高峰期推迟使用烘干机就是一种典型的低碳决策。这一圆点系统的视觉概念借鉴了针对加州排放设计的 Energy Lollipop 扩展其绿色代表清洁电力、暖色代表高碳排放的配色逻辑在实现中被完整保留见下文calculateColor分析。环境准备与构建流程前置条件本机需安装 npm将仓库中的5-browser-extension/solution目录完整代码复制到本地文件夹。课程还提供了 starter 初始代码其中src/index.js仅保留编号注释占位供学习者自行补全查看 starter 源码骨架。安装依赖并构建npm install npm run buildnpm install会安装项目声明的依赖。查看 solution/package.json 可以看到技术栈webpack ^5.105与webpack-cli ^5.1打包工具将src/index.js连同依赖axios打包输出到dist目录axios ^1.15用于向 CO2 Signal API 发起 HTTP 请求的 HTTP 客户端engines 字段要求npm 9.0.0、node 18.0.0构建前请确认版本满足要求scripts 配置build执行webpack完成一次构建watch执行webpack --watch监听源码变化自动重新打包适合开发调试期使用。在 Edge 中安装扩展点击浏览器右上角三点菜单进入扩展Extensions面板开启开发人员模式Developer mode选择加载解压缩的扩展Load Unpacked在弹出的目录选择框中打开刚才npm run build生成的dist目录扩展加载成功后会在扩展栏显示图标。提示Edge 的新版本基于 Chromium 内核因此可直接复用 Chrome 的扩展 APIchrome.*这也是源码中使用chrome.runtime、chrome.action等接口的原因。配置 API 密钥与区域代码要正常使用扩展需要两项关键输入API 密钥前往 CO2 Signal 官网在页面输入框中填写邮箱即可通过邮件获取 API key区域代码对应 Electricity Map 的电网分区编码可查询区域代码列表。例如波士顿所在的美国东北部 ISO 区域代码为US-NEISO。将密钥与区域代码填入扩展界面后扩展栏中的彩色圆点会随之更新实时反映你所在区域的能耗强度。源码级解析完整代码如何工作完整代码入口 src/index.js 是整个扩展的前端逻辑核心以下按模块拆解。1. DOM 引用与结果区声明const form document.querySelector(.form-data); const region document.querySelector(.region-name); const apiKey document.querySelector(.api-key); const errors document.querySelector(.errors); const loading document.querySelector(.loading); const results document.querySelector(.result-container); const usage document.querySelector(.carbon-usage); const fossilfuel document.querySelector(.fossil-fuel); const myregion document.querySelector(.my-region); const clearBtn document.querySelector(.clear-btn);代码先通过querySelector一次性抓取表单字段区域名、API 密钥与结果展示区碳强度、化石燃料占比、错误提示、加载状态等的 DOM 节点为后续读写做准备。2. 颜色计算函数 calculateColor数据到视觉的映射calculateColor async (value) { let co2Scale [0, 150, 600, 750, 800]; let colors [#2AA364, #F5EB4D, #9E4229, #381D02, #381D02]; let closestNum co2Scale.sort((a, b) { return Math.abs(a - value) - Math.abs(b - value); })[0]; let num (element) element closestNum; let scaleIndex co2Scale.findIndex(num); let closestColor colors[scaleIndex]; chrome.runtime.sendMessage({ action: updateIcon, value: { color: closestColor } }); };其工作流程为定义 CO2 强度刻度数组单位克/千瓦时[0, 150, 600, 750, 800]定义对应的颜色数组#2AA364绿色清洁、#F5EB4D黄色中等、#9E4229橙色偏高、#381D02深棕很高通过对刻度数组排序找出与当前 CO2 值最接近的刻度点closestNum排序比较函数按绝对值距离排序取[0]即最近者用findIndex定位第一个大于该刻度的元素下标据此取色通过chrome.runtime.sendMessage向后台脚本发送updateIcon消息携带目标颜色。这里映射逻辑的边界语义CO2 值落在0–150显示绿色150–600黄色600–750橙色750深棕750与800两档共用同一深棕属于设计上对极端值的收敛处理。3. 调用 APIdisplayCarbonUsageconst displayCarbonUsage async (apiKey, region) { try { await axios .get(https://api.co2signal.com/v1/latest, { params: { countryCode: region }, headers: { auth-token: apiKey }, }) .then((response) { const data response?.data?.data; if (data?.carbonIntensity null || data?.fossilFuelPercentage null) { throw new Error(Missing carbon intensity or fossil fuel data); } let CO2 Math.floor(data.carbonIntensity); calculateColor(CO2); loading.style.display none; form.style.display none; myregion.textContent region; usage.textContent Math.round(data.carbonIntensity) grams (grams C02 emitted per kilowatt hour); fossilfuel.textContent data.fossilFuelPercentage.toFixed(2) % (percentage of fossil fuels used to generate electricity); results.style.display block; }); } catch (error) { console.warn(Data fetch failed:, error.message); loading.style.display none; results.style.display none; errors.textContent Sorry, data unavailable for the selected region.; } };关键实现细节请求构造以countryCode作为查询参数传入区域代码通过auth-token请求头携带 API 密钥向https://api.co2signal.com/v1/latest拉取最新数据数据校验使用可选链response?.data?.data安全取值并显式校验carbonIntensity与fossilFuelPercentage是否为空缺失即抛出错误进入 catch 分支——这是对课程反复强调的异步数据校验的工程化落实UI 状态机请求成功后依次隐藏 loading 与表单、填充区域名、碳强度克/千瓦时与化石燃料占比百分比保留两位小数、显示结果容器失败时隐藏 loading 与结果区并在errors节点输出 Sorry, data unavailable for the selected region.同时console.warn记录错误原因便于开发者调试。4. 持久化与初始化setUpUser / init / resetconst setUpUser async (apiKey, region) { localStorage.setItem(apiKey, apiKey); localStorage.setItem(region, region); loading.style.display block; errors.textContent ; clearBtn.style.display block; displayCarbonUsage(apiKey, region); }; const init async () { const storedApiKey localStorage.getItem(apiKey); const storedRegion localStorage.getItem(region); chrome.runtime.sendMessage({ action: updateIcon, value: { color: green } }); if (storedApiKey null || storedRegion null) { form.style.display block; results.style.display none; loading.style.display none; clearBtn.style.display none; errors.textContent ; } else { results.style.display none; form.style.display none; displayCarbonUsage(storedApiKey, storedRegion); clearBtn.style.display block; } }; const reset async (e) { e.preventDefault(); localStorage.removeItem(region); init(); };setUpUser表单提交后把密钥与区域写入localStorage显示 loading 并立即发起首次 API 调用init应用启动时先读取本地存储若缺少密钥或区域则展示表单否则直接以已存参数拉取数据无论何种分支都会先通过sendMessage将默认图标设为绿色保证扩展一加载就有明确的工作正常视觉反馈对应第 3 课中设置默认图标颜色的实践reset清除本地存储中的region并重新执行init即清除配置、回到表单的入口由clearBtn触发。5. 事件绑定与启动form.addEventListener(submit, (e) handleSubmit(e)); clearBtn.addEventListener(click, (e) reset(e)); init();文件末尾将表单submit事件绑定到handleSubmit内部调用setUpUser(apiKey.value, region.value)将清除按钮click事件绑定到reset最后调用init()启动整个应用。这一先声明函数、再绑定监听、最后启动的组织方式也是 starter 骨架中//1 ~ //6编号注释对应的实现顺序。后台脚本图标动态更新原理第 3 课后台任务与性能 详细讲解了与前台sendMessage配套的后台监听逻辑完整实现了数据 → 颜色 → 图标的链路chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { if (msg.action updateIcon) { chrome.action.setIcon({ imageData: drawIcon(msg.value) }); } }); function drawIcon(value) { const canvas new OffscreenCanvas(200, 200); const context canvas.getContext(2d); context.beginPath(); context.fillStyle value.color; context.arc(100, 100, 50, 0, 2 * Math.PI); context.fill(); return context.getImageData(50, 50, 100, 100); }其技术要点消息传递前台脚本通过chrome.runtime.sendMessage({ action: updateIcon, ... })发送消息后台脚本通过chrome.runtime.onMessage.addListener订阅action字段充当消息路由标识动态绘制使用 Canvas API 的OffscreenCanvas在离屏绘制一个指定颜色的实心圆再经getImageData截取图像数据交给chrome.action.setIcon更新浏览器工具栏图标——离屏绘制不会阻塞 UI是扩展性能优化的典型做法该课程同时讲解了浏览器性能分析Edge DevTools 的 Performance 面板、Profiler 记录、Event Log 中超过 15ms 的事件检查等可用于对本扩展进行性能验证与调优例如确认 API 请求、颜色计算与图标绘制各环节的开销。完整工作流程总结用户首次打开扩展init()发现localStorage为空显示配置表单用户输入 API 密钥与区域代码并提交setUpUser持久化配置并触发displayCarbonUsageaxios 携带countryCode参数与auth-token请求头调用 CO2 Signal API校验通过后计算碳强度调用calculateColor映射出颜色经sendMessage通知后台脚本后台脚本用OffscreenCanvas绘制圆点图标并调用chrome.action.setIcon更新扩展栏图标之后每次打开扩展都会从localStorage读取配置并自动拉取最新数据点击清除按钮则回到配置表单。常见问题与调试建议构建失败确认 node 18、npm 9package.json engines 的硬性要求并确认npm install成功执行图标不变化检查是否已重新执行npm run build并在浏览器扩展页点击重新加载dist目录必须包含最新打包产物数据获取失败确认 API 密钥有效、区域代码格式正确如US-NEISO错误信息会显示在扩展界面的 errors 区域同时可在开发者工具控制台查看console.warn输出的具体原因性能验证参考 3-background-tasks-and-performance用 Performance 面板录制并分析扩展加载流程观察是否存在渲染阻塞或过长任务。以上便是 Carbon Trigger 扩展从构建、安装、配置到源码原理的完整解读。你可以直接使用5-browser-extension/solution目录中的成品代码也可以基于 starter 骨架 按课程编号提示自行实现一遍以加深对表单、异步 API 调用、localStorage 持久化与扩展消息通信的整体理解。【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考