Chrome 扩展开发 - 使用 TypeScript、React、Tailwind CSS 和 Webpack 开发最小应用程序
介绍
在本博客中,我们将探索如何使用 TypeScript、React、Tailwind CSS 和 Webpack 设置和开发 Chrome 扩展。我们将创建一个名为“NoteMe”的最小扩展✍️来测试我们的理解。我们的扩展将包括以下功能:
- 允许用户为给定网站添加多个注释
- 使用户能够查看给定网站的已保存笔记
- 提供删除给定网站的注释的选项
- 将笔记本地保存在浏览器存储中
- 可选择与云存储后端同步笔记
复习
在本博客中,我们将学习如何使用现代技术构建 Chrome 扩展程序。本指南假设您已经对在本地开发期间构建和上传 Chrome 扩展程序有一定的了解。如果您对此不熟悉或需要详细的基础知识演练,我建议您查看我之前的博客:链接
扩展预览
该扩展将包括以下组件:
- 切换按钮:打开和关闭侧边栏的按钮。
- 侧边栏:多功能面板,用户可以: 写新笔记。 查看保存的笔记。 删除已保存的笔记。 与后端同步笔记(代码中提供,但当前未连接后端)。
- 弹出窗口:一个小窗口,允许用户将切换按钮(用于打开/关闭侧边栏)重新定位在屏幕上的预先指定位置 注意:虽然此实现中没有后端集成,但代码包含将来连接后端的规定。
下面的屏幕截图展示了扩展完成后的外观:
先决条件
在深入学习本教程之前,请确保您的系统上安装了以下工具:
- Node.js(v18.16 LTS 或更高版本)
- NPM(节点包管理器,与 Node.js 捆绑)
- TypeScript
- Webpack
- VS 代码编辑器(或您选择的任何代码编辑器)
从 40,000 英尺延伸
上图提供了此扩展的内部工作原理的高级概述。以下是我们可以从图中得出的一些关键点:
- 内容脚本直接与父网页的 DOM 交互,使其能够修改页面的内容。
- 弹出窗口、背景和内容脚本通过Chrome的运行时消息系统相互通信。
- 对于与 Chrome 存储或后端 API 调用相关的任务,内容 或 弹出脚本使用运行时消息传递系统将责任委托给后台工作人员。
- 后台脚本充当应用后端和Chrome存储的唯一中介。它还使用运行时消息传递将通知(如果有)转发给其他脚本。
- 弹出窗口和内容脚本直接通过Chrome的运行时消息传递系统交换信息。
扩展的设置
虽然 Chrome 扩展项目不强制要求特定的项目结构,但它们确实需要一个位于构建目录根目录的 manifest.json 文件。利用这种灵活性,我们将定义一个自定义项目结构,帮助有效地组织不同的脚本。这种结构将能够更好地跨脚本重用代码并最大程度地减少重复,从而简化我们的开发流程。
第一步:创建项目的基本目录结构
首先,我们将为该项目设置一个基础目录结构。您可以使用以下 bash 脚本来创建基本结构以及 manifest.json 文件:
#!/bin/bash bash_script_absolute_path=$(pwd) declare public_paths=("public" "public/assets" "public/assets/images") declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles") declare public_directory_path="public" declare manifest_file="manifest.json" declare project_name="note-me" create_directory () { if [ ! -d "" ]; then mkdir fi } create_file () { if [ ! -e "/" ]; then touch / fi } create_public_directories () { for public_path in "${public_paths[@]}"; do create_directory $public_path done } create_source_directories () { for source_path in "${source_paths[@]}"; do create_directory $source_path done } execute () { echo "creating project struture at "${bash_script_absolute_path} create_directory $project_name cd $bash_script_absolute_path"/"$project_name create_public_directories create_source_directories create_file $manifest_file $public_directory_path echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name } execute
确保您的目录结构类似于下面的屏幕截图所示。
步骤 2:位于公共目录中的manifest.json 文件的结构应如下所示:
{ "manifest_version": 3, "name": "NoteMe", "version": "1.0", "description": "A Chrome extension built with React and TypeScript using Webpack.", "action": { "default_popup": "popup.html", "default_icon": "app-icon.png" }, "background": { "service_worker": "background.js", "type": "module" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_end" } ], "permissions": [ "storage", "activeTab", "scripting", "webNavigation" ], "host_permissions": ["<all_urls>"], "web_accessible_resources": [ { "resources": ["styles.css", "sidebar-open.png", "sidebar-close.png"], "matches": ["<all_urls>"] } ] }
注意事项:
- 文件扩展名是.js,因为.ts文件会被编译成.js文件,在Chrome环境下运行时需要。
- 匹配字段使用
;作为其值,使扩展程序能够在 Chrome 中加载的任何网页上运行。 - 引用了三个图片文件:app-icon.png、sidebar-open.png、sidebar-close.png。您可以在本博客末尾链接的存储库中找到这些文件。
- 项目构建后,manifest.json 文件必须放置在 dist 目录的根级别。为了确保这一点,我们需要配置 webpack 设置以在构建过程中适当地移动它。
第3步:初始化npm并安装依赖项
- 首先使用以下命令在项目中初始化 npm:npm init -y
- 将必要的开发依赖项添加到项目的 devDependencies 部分。运行以下命令: npm i --save-dev @types/chrome @types/react @types/react-dom autoprefixer copy-webpack-plugin css-loader mini-css-extract-plugin postcss postcss-loader style-loader tailwindcss ts-loader typescript webpack webpack-cli webpack-dev-server
- 添加运行项目所需的运行时依赖项: npm i --保存反应反应-dom
步骤 4:创建在manifest.json中引用的文件
创建在manifest.json中引用的以下文件:backgroun.ts、content.ts和popup.html。
- background.ts:在 src/scripts/background 目录中创建此文件
- content.ts:在 src/scripts/content 目录中创建此文件
- popup.html 在公共目录中创建此文件
第5步:更新弹出窗口和背景代码
在public目录下的popup.html文件中添加以下代码:
#!/bin/bash bash_script_absolute_path=$(pwd) declare public_paths=("public" "public/assets" "public/assets/images") declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles") declare public_directory_path="public" declare manifest_file="manifest.json" declare project_name="note-me" create_directory () { if [ ! -d "" ]; then mkdir fi } create_file () { if [ ! -e "/" ]; then touch / fi } create_public_directories () { for public_path in "${public_paths[@]}"; do create_directory $public_path done } create_source_directories () { for source_path in "${source_paths[@]}"; do create_directory $source_path done } execute () { echo "creating project struture at "${bash_script_absolute_path} create_directory $project_name cd $bash_script_absolute_path"/"$project_name create_public_directories create_source_directories create_file $manifest_file $public_directory_path echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name } execute
注意:
上面的代码安装了两个监听器:
- 只要浏览器中安装了扩展程序,由 chrome.runtime.onInstalled.addListener 注册的函数就会执行。这可用于以预定义状态初始化 Chrome 存储或后端(如果适用)。
- 每当后台脚本收到来自内容或弹出脚本的消息时,由 chrome.runtime.onMessage.addListener 注册的函数就会执行。
此外,import 语句从 src/lib 目录引入监听器。核心应用程序逻辑构建在 src/lib 中,可以在不同上下文(例如内容和后台脚本)之间重用。
第 6 步:浏览 src/lib 目录
src/lib 目录包含扩展的核心逻辑。以下是其结构和关键组件的概述:
- 组件目录: 包含扩展中使用的所有 React 组件。
- lib/components/ContentApp.tsx: 充当内容脚本的容器组件。
- lib/components/NoteMePosition.tsx: 包含负责弹出脚本的组件。
- helpers.ts: 包括整个扩展中使用的辅助函数。
- 存储模型.ts: 管理与 Chrome 本地存储的交互。有关存储数据结构的详细信息,请参阅此文件以及 types.ts。
- 类型.ts: 定义扩展中使用的自定义类型。
- worker.ts: 包含后台事件监听器的回调。
详细实现请参考仓库中的实际代码。
第7步:安装React组件
在这一步中,我们挂载React组件进行渲染。这些组件安装在两个不同的脚本中:src/scripts/content/content.ts 和 src/scripts/popup/popup.ts。
弹出脚本:位于 src/scripts/popup/popup.ts。
#!/bin/bash bash_script_absolute_path=$(pwd) declare public_paths=("public" "public/assets" "public/assets/images") declare source_paths=("src" "src/lib" "src/scripts" "src/scripts/background" "src/scripts/content" "src/scripts/injected" "src/scripts/popup" "src/styles") declare public_directory_path="public" declare manifest_file="manifest.json" declare project_name="note-me" create_directory () { if [ ! -d "" ]; then mkdir fi } create_file () { if [ ! -e "/" ]; then touch / fi } create_public_directories () { for public_path in "${public_paths[@]}"; do create_directory $public_path done } create_source_directories () { for source_path in "${source_paths[@]}"; do create_directory $source_path done } execute () { echo "creating project struture at "${bash_script_absolute_path} create_directory $project_name cd $bash_script_absolute_path"/"$project_name create_public_directories create_source_directories create_file $manifest_file $public_directory_path echo "done creating project struture at "${bash_script_absolute_path}" with project name "$project_name } execute
内容脚本:位于 src/scripts/content/content.ts。
{ "manifest_version": 3, "name": "NoteMe", "version": "1.0", "description": "A Chrome extension built with React and TypeScript using Webpack.", "action": { "default_popup": "popup.html", "default_icon": "app-icon.png" }, "background": { "service_worker": "background.js", "type": "module" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_end" } ], "permissions": [ "storage", "activeTab", "scripting", "webNavigation" ], "host_permissions": ["<all_urls>"], "web_accessible_resources": [ { "resources": ["styles.css", "sidebar-open.png", "sidebar-close.png"], "matches": ["<all_urls>"] } ] }
要点:
- 单独的安装脚本: 弹出窗口和内容脚本在不同的上下文中运行
- 弹出脚本: 在加载它的 popup.html 网页的上下文中运行。
- 内容脚本:在浏览器中加载的主网页的上下文中运行。
-
内容脚本的 Shadow DOM:
- 内容脚本注入的样式可能会影响父网页的外观。
- 为了防止这种情况,我们使用 Shadow DOM 来封装样式,确保它们在扩展中保持隔离。
- 这对于弹出脚本来说不是必需的,因为它在自己的隔离环境(popup.html)中运行。
第8步:编译和构建的配置
添加编译和构建扩展所需的配置
要成功编译和构建扩展,我们需要配置以下文件:
- postcss.config.js
- tailwind.config.js
- tsconfig.json
- webpack.config.js
要点:
- 默认设置: 只要有可能,都会提供默认设置来简化流程并确保重点始终放在主要目标上 - 构建功能齐全的扩展。
- 存储库中的详细信息:这些文件的完整配置和详细设置请参考代码存储库。
这些配置处理 TypeScript 编译、Tailwind CSS 集成以及扩展的整体 Webpack 构建过程。
测试扩展
- 生成 dist 目录: 运行以下命令创建 dist 目录:npm run build
-
上传至 Chrome:
- 打开 Chrome 并导航至 chrome://extensions/。
- 启用右上角的开发者模式。
- 点击加载已解压的并选择dist目录。
-
验证安装:
- 加载后,扩展程序的图标将默认出现在每个页面的右下角。
-
功能检查:
- 位置控制:使用弹出窗口中的控件来更改图标的位置。
- 注释功能:每个网站的注释都是独立保存的,并且可以针对特定网站删除而不影响其他网站。
-
后端模拟:
- 虽然当前没有连接后端,但代码包含与后端集成的规定。
- 当前实现使用 setTimeout 模拟后端连接,并承诺模拟异步交互。
以下是扩展测试期间捕获的一些屏幕截图。
要点
以下是此博客的一些关键要点,
- 我们探索了 Chrome 环境的各种组件(例如内容脚本、弹出脚本和后台工作人员)如何使用 Chrome 的运行时消息传递系统相互通信。
- 我们学习了如何从头开始配置和构建 Chrome 扩展,包括设置项目结构、安装依赖项和编写核心功能。
- 我们发现了一些好的做法,例如:
- 增强跨脚本的代码可重用性,以实现可维护性和可扩展性。
- 在内容脚本中使用 Shadow DOM 来防止与父网页的样式冲突。
瞥见前方
将来,我计划撰写另一个博客,我们将探索将功能齐全的 Chrome 扩展程序发布到 Chrome 网上应用店的过程。该博客的目标是:
- 开发一个足够复杂的扩展来解决现实世界的问题。
- 演示将扩展程序发布到 Chrome 应用商店的分步过程。
感谢您花时间阅读此博客!您的兴趣和支持对我来说意义重大。在继续这一旅程时,我很高兴能分享更多见解。
编码愉快!
github 链接:https://github.com/gauravnadkarni/chrome-extension-starter-app
本文最初发表于Medium。
以上是Chrome 扩展开发 - 使用 TypeScript、React、Tailwind CSS 和 Webpack 开发最小应用程序的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...
