Chrome插件开发入门:自定义新标签页

10 阅读7分钟

Chrome 扩展开发完全指南:从零打造个性新标签页

本文不仅会系统讲解 Chrome 扩展的核心概念,还会通过一个完整的实战项目——自定义新标签页,带你一步步掌握扩展开发的完整流程。无论你是前端新手还是想拓展技术栈的开发者,都能从中受益。


一、Chrome 扩展基础

Chrome 扩展本质上是 HTML、CSS、JavaScript 文件的集合,可以增强浏览器功能、修改网页行为、提供自定义界面等。它由几个关键组件构成,下面我们逐一介绍。

1. 核心文件:manifest.json

每个扩展都必须有一个 manifest.json 文件,它就像应用的“身份证”,声明了扩展的名称、版本、权限以及各功能模块的入口。

最小示例

json

{
  "manifest_version": 2,
  "name": "我的第一个扩展",
  "version": "1.0",
  "description": "一个简单的Chrome扩展",
  "browser_action": {
    "default_popup": "popup.html"
  },
  "permissions": ["activeTab"]
}
  • manifest_version:当前必须为 2(或 3,但本文基于 V2)。
  • browser_action:定义工具栏图标及点击后弹出的页面(default_popup)。
  • permissions:声明需要访问的 Chrome API 或网站权限。

2. 扩展的主要组件

  • 背景脚本(Background Script) :运行在后台,处理事件、管理状态。在 V2 中可以是持久页面或事件页面。
  • 内容脚本(Content Script) :注入到网页中,可以读取/修改 DOM,但受同源策略限制。
  • 弹出页面(Popup) :点击工具栏图标时显示的小窗口,通常用于快速交互。
  • 选项页面(Options Page) :用户自定义扩展设置的页面。
  • 覆盖页面(Override Pages) :可以覆盖浏览器的默认页面,如新标签页、历史记录页等。

3. 调试与安装

  • 打开 chrome://extensions,开启“开发者模式”。
  • 点击“加载已解压的扩展程序”,选择你的项目文件夹即可安装。
  • 扩展的代码修改后,点击刷新按钮即可重新加载。

二、实战项目:chrome-theme —— 自定义新标签页

本项目是一个功能完整的新标签页替换扩展,支持:

  • 动态显示时间(年月日、星期、时分秒)
  • 每日一句“彩虹屁”
  • 可切换的搜索引擎(百度、必应、谷歌)
  • 本地/网络图片作为背景,并自动提取主色调整文字颜色
  • 最近访问历史记录
  • 实时天气信息(基于IP定位)

📸 效果预览

安装扩展后,新标签页将呈现如下样式(实际运行截图):

68747470733a2f2f6674702e626d702e6f76682f696d67732f323032302f31322f303539333435373339353631376132612e706e67.png

项目结构

.
├── README.md
├── asset/font                # 自定义字体文件
├── background.html           # 新标签页的HTML结构
├── css/background.css        # 样式文件
├── img/                      # 扩展图标
├── inject/index.js           # 注入所有页面的脚本(本项目中为空)
├── js/
│   ├── background.js         # 主逻辑:页面初始化、事件绑定
│   ├── chrome_runtime.js     # Chrome特定功能(历史记录)
│   ├── comm_js.js            # 公共辅助函数
│   ├── localstorage.js       # 本地存储初始化
│   ├── search_engine.js      # 搜索引擎配置
│   └── weather.js            # 天气功能
└── manifest.json

1. manifest.json 详解

{
  "name": "wangfpp-theme",
  "version": "0.1.0",
  "description": "自定义Chrome主题",
  "manifest_version": 2,
  "browser_action": {
    "default_icon": "img/64.png"
  },
  "background": {
    "scripts": [ "js/background.js" ],
    "css": [ "css/background.css" ]
  },
  "chrome_url_overrides": {
    "newtab": "background.html"
  },
  "content_scripts": [ 
    {
      "all_frames": true,
      "js": [ "inject/index.js" ],
      "match_about_blank": true,
      "matches": [ "<all_urls>" ],
      "run_at": "document_start"
    } 
  ],
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
  "permissions": [ "fontSettings", "<all_urls>", "tabs", "storage", "unlimitedStorage", "topSites", "contextMenus", "history", "fileBrowserHandler" ]
}

重点解读

  • chrome_url_overrides:指定覆盖的页面,"newtab": "background.html" 表示每次新建标签页都会加载 background.html
  • background:声明后台脚本和样式。这里 scripts 和 css 会构成一个后台页面,后台脚本可以一直运行(V2 特性)。
  • content_scripts:向所有页面注入脚本(本项目中为空),可用于实现全局样式修改。
  • permissions:请求了多项权限,包括 history(读取历史记录)、storage(本地存储)、<all_urls>(访问所有网站)等,这些都是实现功能所必需的。

2. 新标签页页面 background.html

这个文件定义了新标签页的布局。为了简洁,我们只展示关键部分:

<div class="date"></div>
<input id="search" type="text" placeholder="搜索一下...">
<div id="chp"></div>
<div class="weather"></div>
<div id="history_container"></div>
<div id="set_btn">⚙️</div>
<div id="menu" class="hidemenu">
  <!-- 搜索引擎切换、背景设置等 -->
</div>

样式写在 css/background.css 中,你可以自由调整布局、字体和配色。

3. 核心功能实现

3.1 时间实时更新(background.js
window.onload = e => {
  let date_node = document.querySelector('.date');
  if (date_node) {
    date_node.innerHTML = formatDateString();
    setInterval(() => {
      if (date_node) {
        date_node.innerHTML = formatDateString();
      }
    }, 1000);
  }
}

formatDateString 定义在 comm_js.js 中,返回包含时、分、秒和年月日的 HTML 字符串。

3.2 搜索引擎切换

配置文件 search_engine.js 定义了搜索引擎字典:

const search_gine_dict = {
  "baidu": {
    text: "百度",
    create_url: val => `https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=${val}`
  },
  "biying": {
    text: "必应",
    create_url: val => `https://www.bing.com/search?q=${val}`
  },
  "google": {
    text: "谷歌",
    create_url: val => `http://www.google.cn/search?q=${val}&hl=zh-CN&client=aff- 360daohang&hs=yhE&affdom=360.cn&newwindow=1&start=10&amp; amp;sa=N`
  }
}

在 background.js 中,监听搜索框回车事件:

input_node.onkeydown = function (e) {
  let { keyCode, target } = e;
  let { value } = target;
  if (keyCode === 13 && value) {
    let engine = window.localStorage.getItem("search_engine") || search_gine_list[0];
    let url = search_gine_dict[engine].create_url(value);
    window.location.href = url;
    target.value = "";
  }
}

菜单中的单选框用于修改本地存储的搜索引擎值。

3.3 背景图片与动态取色(亮点功能)

用户可以上传本地图片或输入网络图片 URL 作为背景,扩展会分析图片中特定区域(日期区域、天气区域、彩虹屁区域)的主色,并设置文字颜色为反色,以保证对比度。

关键代码在 background.js 的 setRootBG 函数中:

function setRootBG(url) {
  if (root_node) {
    root_node.setAttribute("style", `background: url(${url});background-size: cover`);
    let image = new Image();
    image.onload = function(e) {
      if (storage.getItem("color_width_img") == "1") {
        // 获取各区域的位置和大小
        let { offsetTop, offsetLeft, offsetWidth, offsetHeight } = chp_node;
        let { width, height } = e.target;
        if (!(width >= 2000 || height >= 2000)) { // 避免大图性能问题
          let pixel = getImagePix(image); // 获取像素矩阵
          let _date_color = areaPixAverage(pixel, [0, 166], [0, 53]);      // 日期区域
          let weather_color = areaPixAverage(pixel, [width-188, width], [0, 60]); // 天气区域
          let chp_color = areaPixAverage(pixel, [offsetLeft, offsetLeft + offsetWidth], [offsetTop, offsetTop + offsetHeight]); // 彩虹屁区域
          setSearchBg(input_node, pixel);
          // 通过CSS变量传递颜色
          root_node.style.setProperty("--date_color", _date_color);
          root_node.style.setProperty("--weather-color", weather_color);
          root_node.style.setProperty("--chp_color", chp_color);
        }
      }
    }
    image.src = url;
  }
}
  • getImagePix:将图片绘制到 canvas,提取每个像素的 RGBA 值,生成二维数组。
  • areaPixAverage:计算指定矩形区域的平均 RGB,并返回其反色。
  • 搜索框的背景色也会根据区域亮度动态调整(深色背景配浅色文字,反之亦然)。
3.4 彩虹屁 API
function createChp(node) {
  fetch('https://chp.shadiao.app/api.php?').then(res => res.text())
    .then(res => {
      if (res && node) node.innerHTML = res;
    });
}

这个 API 返回纯文本,直接插入即可。

3.5 天气功能(weather.js

流程:

  1. 通过 ip-api.com 获取当前 IP 的经纬度(免费,无需密钥)。
  2. 将经纬度 POST 给 data.cma.cn(中国气象局数据接口)获取实时天气。
  3. 更新 DOM,展示城市、天气状况、温度、风力等。
  4. 每 3 小时自动刷新。
fetch(`http://ip-api.com/json/?lang=zh-CN`).then(res => res.json())
  .then(res => {
    let { lat, lon } = res;
    fetch("http://data.cma.cn/kbweb/home/live", {
      method: "POST",
      body: JSON.stringify({ lat, lon, type: "1" }),
      headers: { "Content-type": "application/json" }
    }).then(res => res.json())
      .then(res => {
        // 解析并渲染天气数据
      });
  });

注意:由于 API 可能变更,实际使用时建议替换为更稳定的天气服务(如和风天气、OpenWeatherMap),并处理好跨域问题(可在后台脚本中请求)。

3.6 历史记录显示(chrome_runtime.js

利用 Chrome 的 chrome.history.search API 获取最近 10 条记录:

if (window.localStorage.getItem("show_history") == "1") {
  chrome.history.search({text: '', maxResults: 10}, function(data) {
    let history_item = "";
    data.forEach(function(page) {
      history_item += `
        <div class="history_item">
          <a href="${page.url}">
            <img src="chrome://favicon/size/20@2x/${page.url}" alt="icon"/>
            <p class="title">${page.title}</p>
          </a>
        </div>
      `;
    });
    history_container.innerHTML = history_item;
  });
} else {
  history_container.style.display = "none";
}

注意:需要在 manifest 中申请 "history" 权限。

4. 本地存储初始化(localstorage.js

在扩展首次运行时,设置默认值:

localStorage.getItem("search_engine") || localStorage.setItem("search_engine", "baidu");
localStorage.getItem("screen_bg") || localStorage.setItem("screen_bg", "https://images.pexels.com/photos/417074/pexels-photo-417074.jpeg");
localStorage.getItem("color_width_img") || localStorage.setItem("color_width_img", "0");
localStorage.getItem("show_history") || localStorage.setItem("show_history", "0");

5. 辅助函数(comm_js.js

提供了常用的 DOM 操作和格式化函数,如 addClassremoveClassdoubleNumweekParse 等,方便复用。


三、打包与发布

  1. 在 chrome://extensions 中,点击“打包扩展程序”。
  2. 选择项目根目录,Chrome 会自动生成 .crx 和 .pem 文件(私钥请妥善保管)。
  3. 如果你想发布到 Chrome 网上应用店,需要注册开发者账号(一次性费用),上传包含所有文件的 zip 包,等待审核。

四、扩展与优化建议

  • 性能优化:背景取色时对过大图片做了限制,你也可以考虑使用 createImageBitmap 或 Web Worker 处理像素数据。
  • 天气 API 替换:现有 API 可能不稳定,建议改用免费且稳定的接口,如和风天气(需注册)、OpenWeatherMap(需 API Key)。
  • 添加更多小部件:你可以在 background.html 中自由添加模块,比如名言警句、待办事项等。
  • 适配 Manifest V3:Chrome 即将全面转向 V3,迁移时需要将后台脚本改为 Service Worker,并调整权限声明。可参考官方迁移指南。

五、结语

通过这个项目,我们不仅掌握了 Chrome 扩展的基本开发流程,还深入实践了图片处理、API 调用、Chrome 特有 API 的使用。希望你能在此基础上发挥创意,打造出属于自己的个性化浏览器工具。

如果你在开发过程中遇到问题,欢迎在评论区交流,也欢迎给项目点个 star 支持一下~

项目完整代码:[GitHub 仓库地址](github.com/wangfpp/chr…

欢迎关注我的公众号

qrcode_for_gh_c5d186e085a2_258.jpg