
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本篇导读Carbon Trigger 是 Web-Dev-For-Beginners 课程中的实战项目它基于 tmrow 的 CO2 Signal API将区域电力碳排放数据实时呈现在浏览器扩展图标上。读完本文你将掌握完整的扩展开发流程Webpack 打包构建、Edge/Chrome 扩展加载、API 密钥与区域代码配置、localStorage 持久化以及基于碳强度映射图标颜色的核心算法实现。本文以 翻译版完成代码文档 为骨架结合仓库内的 完整源码 逐行剖析保证每一步都可复现、可运行。Carbon Trigger 扩展在浏览器工具栏中以彩色圆点实时反映区域电力碳排放强度项目背景与核心思路Carbon Trigger 是一款微型网站式浏览器扩展它的任务是回答一个简单却重要的问题我所在区域的电力碳排放现在有多高扩展在安装后会定期/按需查询 CO2 Signal API获取指定区域的碳强度carbon intensity单位 gCO₂/kWh和化石燃料发电占比fossil fuel percentage并通过浏览器扩展栏中一个彩色圆点直观地提示用户当前是否适合执行高耗电活动例如洗衣服、烘干衣物等。该圆点视觉方案受 Energy Lollipop 扩展针对加州排放启发在仓库的 模块导读 中有明确说明。整个浏览器扩展模块共三课与本完成代码对应课程主题对应文件第 1 课浏览器工作原理与扩展安装1-about-browsers/README.md第 2 课表单、localStorage 与 API 集成2-forms-browsers-local-storage/README.md第 3 课后台任务、动态图标与性能3-background-tasks-and-performance/README.md快速开始安装、构建与加载关联文档给出了三步上手流程以下结合 package.json 给出完整说明。1. 环境要求与依赖安装前置条件系统已安装 npmNode.js 包管理器。仓库的 package.json 声明了运行环境门槛engines: { npm: 9.0.0, node: 18.0.0 }将 solution 目录 的代码下载到本地文件夹后安装依赖npm install该命令会安装两类包见 package.json开发依赖devDependencieswebpack ^5.105.4、webpack-cli ^5.1.4用于模块打包运行依赖dependenciesaxios ^1.15.0用于发起 CO2 Signal API 请求。2. Webpack 构建npm run buildbuild脚本映射到webpack命令将 src/index.js 打包为dist目录下的浏览器可加载文件。除此之外 package.json 还提供了开发调试脚本scripts: { watch: webpack --watch, build: webpack }npm run watch监听源码变更并自动重新打包适合开发期反复调试npm run build一次性构建用于加载和分发。3. 在 Edge及 Chromium 内核浏览器中加载扩展开发期通过加载解压缩的扩展方式安装点击浏览器右上角**三个点菜单**进入扩展面板打开**开发人员模式**开关选择加载解压缩的扩展Load Unpacked在弹出的文件选择器中打开dist文件夹扩展即被加载。在 Edge 的扩展管理页面通过加载解压缩的扩展导入 dist 目录提示由于新版 Edge 基于 Chromium 内核扩展 API 与 Chrome 兼容因此源码中使用的chrome.runtime.*系列 API 在 Edge 中同样有效这一点在 3-background-tasks-and-performance/README.md 中有明确说明。Firefox 亦可用于该扩展的开发测试。4. 获取两个必要配置扩展真正工作前需要用户提供两项输入配置项获取方式示例CO2 Signal API Key在 co2signal.com 页面输入邮箱免费申请形如xxxxx-xxxxx的令牌区域代码Region Code依据 Electricity Map 地图对照区域代码表查询波士顿地区使用US-NEISO区域代码与 Electricity Map 上的电网分区一一对应中国大陆地区可在地图上查询对应的电网分区编码。填写完成后扩展栏中的彩色圆点会随区域碳排放强度实时变色。源码级剖析扩展是如何工作的关联文档描述了输入 API Key 和区域后圆点变色的最终效果其背后的完整实现位于 solution/src/index.js。下面按数据流顺序逐段拆解。DOM 引用捕获扩展启动时首先通过document.querySelector()捕获所有需要操作的界面元素分为表单字段与结果展示两组// form fields const form document.querySelector(.form-data); const region document.querySelector(.region-name); const apiKey document.querySelector(.api-key); // results 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);这些 CSS 类名与 第 1 课文档 中定义的 HTML 结构一一对应.region-name和.api-key是配置表单的输入框.carbon-usage、.fossil-fuel、.my-region是结果区域的数据展示位.loading与.errors负责加载中和报错状态.clear-btn是更改区域按钮。表单提交与用户配置持久化扩展在页面底部完成事件绑定并立即初始化form.addEventListener(submit, (e) handleSubmit(e)); clearBtn.addEventListener(click, (e) reset(e)); //start app init();handleSubmit首先调用e.preventDefault()阻止浏览器默认的表单刷新行为随后把输入值交给setUpUserconst handleSubmit async (e) { e.preventDefault(); setUpUser(apiKey.value, region.value); }; const setUpUser async (apiKey, region) { localStorage.setItem(apiKey, apiKey); localStorage.setItem(region, region); loading.style.display block; errors.textContent ; clearBtn.style.display block; //make initial call displayCarbonUsage(apiKey, region); };关键设计点localStorage 持久化API Key 与区域代码以键值对形式写入浏览器本地存储下次打开扩展时无需重新输入UI 状态切换保存后立即显示加载指示器、清空历史错误、展示清除按钮立即发起首次请求保存配置后马上调用displayCarbonUsage拉取数据。初始化与重置记忆用户身份init()是扩展的状态分派中心负责判断老用户还是新用户const init async () { const storedApiKey localStorage.getItem(apiKey); const storedRegion localStorage.getItem(region); //set icon to be generic green 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; } };reset()则让用户更换区域const reset async (e) { e.preventDefault(); //clear local storage for region only localStorage.removeItem(region); init(); };注意这里只清除region而保留apiKey——API Key 无需重复输入设计细节上保持了较好的用户体验。浏览器扩展的 localStorage 与普通网页隔离可通过 DevTools 的 Application 面板查看详见 第 2 课文档。API 调用CO2 Signal 数据获取displayCarbonUsage是整个扩展的数据引擎使用 axios 向 CO2 Signal API 发起 GET 请求const 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; // ✅ Validate required data before using 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.; } };请求细节拆解要素值说明端点https://api.co2signal.com/v1/latestCO2 Signal 的实时数据接口认证Headerauth-token: apiKey通过请求头携带 API Key而非 URL 参数查询参数countryCode: region传入区域代码如US-NEISO返回数据data.carbonIntensity碳强度gCO₂/kWh用于圆点配色返回数据data.fossilFuelPercentage化石燃料发电占比%展示给用户健壮性处理可对照 第 2 课文档 的 fetch 版本理解演进可选链 数据校验response?.data?.data避免空引用崩溃carbonIntensity或fossilFuelPercentage缺失时主动抛出异常try/catch 兜底网络错误或数据不可用时隐藏 loading 与结果区在.errors中展示友好提示 Sorry, data unavailable for the selected region.UI 联动数据就绪后隐藏表单、填入区域名、碳强度克/千瓦时与化石燃料占比保留两位小数再显示结果容器。颜色计算算法数据 → 圆点颜色这是本扩展最有特色的部分将数值碳强度映射为五种视觉颜色。注意源码头部的calculateColor是隐式全局函数未用const声明这是为了兼容后续课程逐步添加代码的教学节奏其算法逻辑与 第 3 课文档 完全一致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 } }); };算法执行流程定义色阶co2Scale [0, 150, 600, 750, 800]表示碳强度阈值gCO₂/kWhcolors数组与之对应——绿色清洁、黄色中等、橙色偏高、深棕很高寻找最近阈值通过对数组按与输入值的绝对差排序取第一项得到最近的档位定位色标索引用findIndex找出第一个大于最近阈值的元素下标映射到对应颜色通知后台更新图标通过chrome.runtime.sendMessage({ action: updateIcon, ... })将颜色发给扩展后台脚本后台再调用chrome.action.setIcon用 OffscreenCanvas 绘制圆形图标此部分详见 3-background-tasks-and-performance/README.md 的drawIcon实现。注意co2Scale.sort()会原地修改数组。虽然示例代码中排序后立即使用不影响本次结果但生产代码应使用[...co2Scale].sort()拷贝排序避免污染原始色阶数组。数据流全景从表单到图标综合以上实现Carbon Trigger 的完整调用链为用户输入 API Key 区域代码 │ 提交表单 (submit 事件) ▼ handleSubmit() ──► setUpUser() │ ├─ localStorage.setItem(apiKey/region) 持久化 │ └─ displayCarbonUsage() 首次拉取 ▼ displayCarbonUsage() ──► axios GET api.co2signal.com/v1/latest │ ├─ header: auth-token │ └─ params: countryCode ▼ 响应数据校验 ──► calculateColor(carbonIntensity) │ └─ chrome.runtime.sendMessage({action:updateIcon}) ▼ 后台脚本 chrome.action.setIcon ──► 工具栏彩色圆点更新扩展启动时init()会先读取 localStorage若存在历史配置直接进入数据展示路径否则展示配置表单。这个记忆-恢复闭环正是第 2 课 LocalStorage 与第 3 课后台消息机制的实战融合。常见问题排查现象原因处理方式提示 data unavailable for the selected regionAPI Key 无效、区域代码格式错误或网络异常核对auth-token与countryCode取值检查控制台console.warn输出扩展图标不出现/不变色后台脚本未监听updateIcon消息确认dist中后台脚本包含chrome.runtime.onMessage监听与drawIcon函数修改源码后无变化未重新构建运行npm run build并在扩展管理页点击重新加载表单反复出现localStorage 被清除重新输入 API Key 与区域代码或检查浏览器是否清理了扩展存储深入阅读完整实现源码solution/src/index.js依赖与构建脚本solution/package.json第 1 课浏览器基础与扩展安装1-about-browsers/README.md第 2 课表单、localStorage 与 API2-forms-browsers-local-storage/README.md第 3 课后台任务、动态图标与性能剖析3-background-tasks-and-performance/README.md入门脚手架代码对照学习start/README.md【免费下载链接】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),仅供参考