使用 Reactjs 构建 Web 扩展 - 从 0 到发布!
Web 扩展 - 你可能听说过,很可能已经在用了 - 例如?AdBlock、Grammarly、Save to Pocket 等等。在本文中,我们将使用 Reactjs 从头开始构建一个 Web 扩展。
我们将制作一个“新标签问候扩展”并将其发布在Chrome Web Store
和上Firefox Addon Dashboard
。

步骤 1 - 创建应用程序:
让我们用CRA创建一个 React 应用程序:
npx create-react-app greetings-web-extension
cd greetings-web-extension
让我们做一些快速清理:在文件夹
下,删除除、和之外src
的所有其他内容。App.js
index.js
index.css
从文件夹中 - 删除除和 之外public
的所有内容。index.html
favicon.ico
最后,我们应该有以下目录结构:
- 问候网络扩展
- 节点模块
- 民众
- 网站图标
- 索引.html
- 源码
- App.js
- 索引.css
- index.js
- .gitignore
- 包.json
- 自述文件.md
- 其他的
第 2 步 - 准备应用程序:
快速修改几个文件如下:
- /src/index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
- /src/index.css
html,
body,
#root {
height: 100%;
}
body {
margin: 0;
text-align: center;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.App {
height: 100%;
background: linear-gradient(to bottom right, #7b4397, #dc2430);
color: white;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
- /src/App.js
import React from "react";
const greetings = {
morning: "Good morning",
noon: "Good afternoon",
evening: "Good evening",
night: "Good night",
};
class App extends React.Component {
constructor() {
super();
this.state = {
greeting: greetings.morning,
};
this.startTime = this.startTime.bind(this);
}
componentDidMount() {
this.startTime();
}
startTime() {
let today = new Date();
let h = today.getHours();
let greeting;
if (h > 6 && h < 12) {
greeting = greetings.morning;
} else if (h >= 12 && h < 17) {
greeting = greetings.noon;
} else if (h >= 17 && h < 20) {
greeting = greetings.evening;
} else {
greeting = greetings.night;
}
this.setState({ greeting });
setTimeout(this.startTime, 1000);
}
render() {
return (
<div className="App">
<h1>{this.state.greeting}</h1>
</div>
);
}
}
export default App;
- /公共/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<title>Greetings</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
步骤3-测试React App:
让我们快速测试一下现有的东西。
启动它npm start
。
您应该在浏览器中看到类似这样的内容:
步骤 4——准备 Web 扩展:
我们首先需要的是一个manifest.json
文件——它是我们正在构建的 Web 扩展的描述文件。
创建一个目录extras
,manifest.json
在其下创建一个新文件并复制/粘贴以下内容:
{
"name": "greetings",
"offline_enabled": true,
"short_name": "greetings",
"description": "Everyday greetings",
"version": "1.0.0",
"chrome_url_overrides": {
"newtab": "index.html"
},
"manifest_version": 2
}
- offline_enabled:呃!
- chrome_url_overrides:我们希望此扩展程序能够
newtab
用覆盖我们的index.html
。因此……
现在,让我们为我们的 react-app 创建一个构建:INLINE_RUNTIME_CHUNK=false react-scripts build
为什么INLINE_RUNTIME_CHUNK=false
?
因为如果我们不这样做,最终index.html
构建过程中会包含一个内联脚本。扩展程序建议使用外部脚本,不鼓励使用内联脚本。使用INLINE_RUNTIME_CHUNK
环境变量,我们可以绕过上述问题。
上述命令将导致build
在我们的项目根目录下生成一个文件夹。
现在,将manifest.json
我们创建的文件复制/粘贴到这个新的构建文件夹中。(为什么我们不直接在构建文件夹中创建文件?因为每次运行构建命令时,构建文件夹都会被清除并重新创建。因此,我们将其保存在 下extras
。)
步骤 5——测试扩展:
现在启动 Chrome 浏览器,进入chrome://extensions/
并启用开发者模式。
现在单击Load unpacked
按钮并指向我们项目的构建文件夹。
通过在 Chrome 中打开新标签页进行测试。

步骤 6 - 为 Chrome 和 Firefox 打包:
Chrome 的打包只需一个 zip 命令即可。Firefox
的打包可以使用推荐的工具web-ext。使用 全局安装即可npm i -g web-ext
。
为了帮助您省去复制/粘贴 manifest.json 文件、运行 Firefox 和 Chrome 打包命令等手动步骤,我创建了一个node.js
可以完成这项工作的小脚本。
在项目根目录下创建一个新文件,我们称之为buildPackage.js
。将以下内容放入其中。
const { execSync } = require("child_process");
// FILENAMES
const manifestFileName = "manifest.json";
// DIRECTORIES
const buildDir = "./build/";
const extensionDir = "./extras/";
const outputs = "./";
// OUTPUTS
const chromeOutput = "greetings-chrome.zip";
console.log("Building Extension Packages");
console.log("***COPYING MANIFEST FILE***\n\n");
execSync(
`cp ${extensionDir}${manifestFileName} ${buildDir}${manifestFileName}`
);
execSync(`zip -r ${outputs}${chromeOutput} ${buildDir}`);
console.log("***CHROME BUILT SUCCESSFULLY***\n\n");
execSync(`web-ext build -s ${buildDir} -a ${outputs} --overwrite-dest`);
console.log("***FIREFOX BUILT SUCCESSFULLY***");
修改package.json
以将此脚本作为构建过程的一部分运行。在scriptspackage.json
标签下,按如下所示进行修改:
“build”:“INLINE_RUNTIME_CHUNK = false react-scripts build && node buildPackage.js”,
现在使用触发构建脚本npm run build
,您应该会看到在项目根目录中创建了 2 个新文件:
- Greetings-chrome.zip //适用于 Chrome
- Greetings-1.0.0.zip // 适用于 Firefox
步骤 7 - 发布:
铬合金:
- 前往Google Chrome 开发者信息中心
- 使用您的 Google 帐户登录或创建一个新帐户
- 点击“+ 新建项目”按钮
- 添加
greetings-chrome.zip
上一步创建的文件 - 填写所需信息并提交审核
(通常需要 12 小时左右才能发布)
火狐浏览器:
- 前往Mozilla 附加组件仪表板
- 使用您的 Mozilla 帐户登录或创建一个新帐户
- 点击提交新附加组件按钮
- 对于分发,选择
On this site
并继续 - 添加
greetings-1.0.0.zip
上一步创建的文件 - 填写所需信息并提交审核
(通常需要 6-10 分钟左右发布)
最后说明:
- 您需要为扩展程序添加一个图标,请创建一个尺寸为 128x128 的图标(命名为 icon_128.png),并将其放在构建目录中。将以下内容添加到
manifest.json
:
"icons": {
"128": "icon_128.png"
},
- 在某些情况下,您的 Web 扩展程序可能需要存储和检索数据。虽然您可以使用浏览器本地存储 (localStorage),但我们强烈建议不要将其用于 Web 扩展程序。您应该为扩展程序使用更可靠的专用数据库存储区域。点击此处了解更多信息。
- 这是我们创建的一个非常基本的扩展,通常,它可能会更复杂一些 - 包括 API 调用、存储、后台脚本等。所有这些都是可能的!
- 尝试保持 Web 扩展轻量 - 这意味着扩展应该加载速度快、应该服务于单一目的、应该是可访问的,等等。
我创建了一个适用于 Chrome 和 Firefox 的 Web 扩展程序 - minimylist。如果您喜欢,欢迎查看并分享。
![]()
亚什·索尼@iyash_soni
2020年6月13日上午8:26
下次再见,再见!👋🏻
