|
1 |
| -<div align="center"> |
2 |
| - |
3 |
| -<picture> |
4 |
| - <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/99cb6303-64e4-4bed-bf3f-35735353e6de" /> |
5 |
| - <source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/a5dbf71c-c509-4c4f-80f4-be88a1943b0a" /> |
6 |
| - <img alt="Logo" src="https://github.com/user-attachments/assets/99cb6303-64e4-4bed-bf3f-35735353e6de" /> |
7 |
| -</picture> |
8 |
| - |
9 |
| - |
10 |
| - |
11 |
| - |
12 |
| - |
13 |
| - |
14 |
| - |
| 1 | +# 项目基础 |
| 2 | +一个基于 https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite 模板的chrome插件项目 |
| 3 | +## 技术栈 |
| 4 | + |
| 5 | +React 18 |
| 6 | +TypeScript |
| 7 | +Vite (构建工具) |
| 8 | +TailwindCSS (样式框架) |
| 9 | +Turborepo (monorepo 管理工具) |
| 10 | + |
| 11 | +## 主要功能 |
| 12 | + |
| 13 | +支持 Chrome Extensions Manifest V3 (最新版扩展标准) |
| 14 | +支持热更新(HMR)开发 |
| 15 | +内置国际化(i18n)支持 |
| 16 | +完整的 TypeScript 类型支持 |
| 17 | +包含 ESLint 和 Prettier 代码规范配置 |
| 18 | +自定义 HMR(热模块重建)插件 |
| 19 | +使用 WebdriverIO 进行端到端测试 |
| 20 | + |
15 | 21 |
|
16 |
| -<img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https://github.com/Jonghakseo/chrome-extension-boilerplate-react-viteFactions&count_bg=%23#222222&title_bg=%23#454545&title=😀&edge_flat=true" alt="hits"/> |
17 |
| -<a href="https://discord.gg/4ERQ6jgV9a" target="_blank"><img src="https://discord.com/api/guilds/1263404974830915637/widget.png"/></a> |
| 22 | +## 项目结构 |
18 | 23 |
|
19 |
| -> This boilerplate |
20 |
| -> has [Legacy version](https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/tree/legacy) |
| 24 | +主要包含以下几个部分: |
| 25 | +pages/: 扩展的各个页面 |
| 26 | +popup (点击扩展图标显示的弹窗) |
| 27 | +options (扩展的设置页面) |
| 28 | +content (注入到网页中的脚本) |
| 29 | +devtools (开发者工具面板) |
| 30 | +new-tab (新标签页) |
| 31 | +side-panel (侧边栏) |
| 32 | +packages/: 共享的功能模块 |
| 33 | +ui (UI组件) |
| 34 | +storage (存储相关) |
| 35 | +i18n (国际化) |
| 36 | +shared (共享代码) |
21 | 37 |
|
22 |
| -</div> |
| 38 | +## 开发流程 |
23 | 39 |
|
24 |
| -> [!NOTE] |
25 |
| -> This project is listed in the [Awesome Vite](https://github.com/vitejs/awesome-vite) |
| 40 | +```bash |
| 41 | +# 安装依赖 |
| 42 | +pnpm install |
26 | 43 |
|
27 |
| -> [!TIP] |
28 |
| -> Share storage state between all pages |
29 |
| -> |
30 |
| -> https://github.com/user-attachments/assets/3b8e189f-6443-490e-a455-4f9570267f8c |
| 44 | +# 开发模式 |
| 45 | +pnpm dev |
31 | 46 |
|
32 |
| -## Table of Contents |
| 47 | +# 生产构建 |
| 48 | +pnpm build |
| 49 | +``` |
33 | 50 |
|
34 |
| -- [Intro](#intro) |
35 |
| -- [Features](#features) |
36 |
| -- [Structure](#structure) |
37 |
| - - [ChromeExtension](#structure-chrome-extension) |
38 |
| - - [Packages](#structure-packages) |
39 |
| - - [Pages](#structure-pages) |
40 |
| -- [Getting started](#getting-started) |
41 |
| - - [Chrome](#getting-started-chrome) |
42 |
| - - [Firefox](#getting-started-firefox) |
43 |
| -- [Install dependency](#install-dependency) |
44 |
| - - [For root](#install-dependency-for-root) |
45 |
| - - [For module](#install-dependency-for-module) |
46 |
| -- [Community](#community) |
47 |
| -- [Reference](#reference) |
48 |
| -- [Star History](#star-history) |
49 |
| -- [Contributors](#contributors) |
| 51 | +## 项目启动后 |
50 | 52 |
|
51 |
| -## Intro |
| 53 | +1. 首先运行开发命令: `pnpm dev` |
| 54 | +2. 打开 Chrome 浏览器,进入扩展管理页面: |
| 55 | + 在地址栏输入: chrome://extensions/ |
| 56 | + 或者点击浏览器右上角的"扩展"图标,选择"管理扩展程序" |
| 57 | +3. 在扩展管理页面: |
| 58 | +- 打开右上角的"开发者模式"开关 |
| 59 | +- 点击左上角的"加载已解压的扩展程序"按钮 |
| 60 | +- 选择项目中的 dist 目录 |
| 61 | +4. 安装成功后,您可以在以下位置看到扩展的不同部分: |
| 62 | +- 弹出窗口(Popup) |
| 63 | +- 点击浏览器工具栏中的扩展图标 |
| 64 | +5. 新标签页(New Tab) |
| 65 | +- 打开新的标签页即可看到 |
| 66 | +6. 内容脚本(Content Script) |
| 67 | +- 访问任意网页,在页面底部可以看到注入的 UI |
| 68 | +7. 开发者工具面板(DevTools) |
| 69 | +- 打开浏览器开发者工具(F12) |
| 70 | +- 在顶部标签中可以看到新增的面板 |
| 71 | +8. 侧边栏(Side Panel) |
| 72 | +- 点击浏览器工具栏的扩展图标 |
| 73 | +- 选择"在侧边栏中打开" |
| 74 | +9. 选项页面(Options) |
| 75 | +- 在扩展图标上右键 |
| 76 | +- 选择"选项" |
52 | 77 |
|
53 |
| -This boilerplate helps you create Chrome/Firefox extensions using React and Typescript. It improves |
54 |
| -the build speed and development experience by using Vite and Turborepo. |
| 78 | +开发提示: |
| 79 | +代码修改后会自动重新构建 |
| 80 | +大多数情况下会自动重新加载扩展 |
| 81 | +如果没有自动重新加载,可以在扩展管理页面手动点击"重新加载" |
| 82 | +建议打开 Chrome 的开发者工具查看控制台输出 |
55 | 83 |
|
56 |
| -## Features |
57 | 84 |
|
58 |
| -- [React18](https://reactjs.org/) |
59 |
| -- [TypeScript](https://www.typescriptlang.org/) |
60 |
| -- [Tailwindcss](https://tailwindcss.com/) |
61 |
| -- [Vite](https://vitejs.dev/) (and [Rollup](https://rollupjs.org/)) |
62 |
| -- [Turborepo](https://turbo.build/repo) |
63 |
| -- [Prettier](https://prettier.io/) |
64 |
| -- [ESLint](https://eslint.org/) |
65 |
| -- [Chrome Extensions Manifest Version 3](https://developer.chrome.com/docs/extensions/mv3/intro/) |
66 |
| -- [Custom i18n package](/packages/i18n/) |
67 |
| -- [Custom HMR (Hot Module Rebuild) plugin](/packages/hmr/) |
68 |
| -- [End-to-end testing with WebdriverIO](https://webdriver.io/) |
| 85 | +## 知识点 |
69 | 86 |
|
70 |
| -## Getting started |
| 87 | +1)chrome.tabs.create :在当前窗口中创建一个新标签页,并导航到指定的 URL |
71 | 88 |
|
72 |
| -1. When you're using Windows run this: |
73 |
| - - `git config --global core.eol lf` |
74 |
| - - `git config --global core.autocrlf input` |
| 89 | +2)chrome.scripting.executeScript :在当前页面中注入脚本 , |
| 90 | +```js |
| 91 | +chrome.scripting.executeScript({ |
| 92 | + target: { tabId: tab.id! }, |
| 93 | + files: ['/content-runtime/index.iife.js'], |
| 94 | +}) |
| 95 | +``` |
| 96 | +- target :指定注入目标,tabId 表示指定标签页,如果不指定,则默认注入到当前标签页 |
| 97 | +- files :指定注入的脚本文件,相对于 manifest.json 中的 js 字段 |
75 | 98 |
|
76 |
| - **This will set the EOL (End of line) character to be the same as on Linux/macOS. Without this, our bash script won't work, and you will have conflicts with developers on Linux/macOS.** |
77 |
| -2. Clone this repository. |
78 |
| -3. Edit `/packages/i18n/locales/`{your locale(s)}/`messages.json` |
79 |
| -4. In the objects `extensionDescription` and `extensionName`, change the `message` fields (leave `description` alone) |
80 |
| -5. In `/.package.json`, change the `version` to the desired version of your extension. |
81 |
| -6. Install pnpm globally: `npm install -g pnpm` (check your node version >= 18.19.1)) |
82 |
| -7. Run `pnpm install` |
| 99 | +3)chrome.tabs.query :获取当前页面信息,{ currentWindow: true, active: true } 表示当前窗口和当前活动标签页,返回一个包含当前标签页信息的数组 |
83 | 100 |
|
84 |
| -Then, depending on the target browser: |
| 101 | +# 码农写作助手开发 |
85 | 102 |
|
86 |
| -### For Chrome: <a name="getting-started-chrome"></a> |
| 103 | +package.json 修改 |
87 | 104 |
|
88 |
| -1. Run: |
89 |
| - - Dev: `pnpm dev` (on Windows, you should run as administrator; see [issue#456](https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/issues/456)) |
90 |
| - - Prod: `pnpm build` |
91 |
| -2. Open in browser - `chrome://extensions` |
92 |
| -3. Check - <kbd>Developer mode</kbd> |
93 |
| -4. Click - <kbd>Load unpacked</kbd> in the upper left corner |
94 |
| -5. Select the `dist` directory from the boilerplate project |
95 | 105 |
|
96 |
| -### For Firefox: <a name="getting-started-firefox"></a> |
| 106 | +pages/popup 改造 |
97 | 107 |
|
98 |
| -1. Run: |
99 |
| - - Dev: `pnpm dev:firefox` |
100 |
| - - Prod: `pnpm build:firefox` |
101 |
| -2. Open in browser - `about:debugging#/runtime/this-firefox` |
102 |
| -3. Click - <kbd>Load Temporary Add-on...</kbd> in the upper right corner |
103 |
| -4. Select the `./dist/manifest.json` file from the boilerplate project |
104 | 108 |
|
105 |
| -> [!NOTE] |
106 |
| -> In Firefox, you load add-ons in temporary mode. That means they'll disappear after each browser close. You have to load the add-on on every browser launch. |
| 109 | +```typescript |
| 110 | +const currentWindow = await chrome.windows.getCurrent():获取当前窗口 |
| 111 | +chrome.sidePanel.open({windowId: currentWindow.id}):打开侧边栏 |
| 112 | +``` |
107 | 113 |
|
108 |
| -## Install dependency for turborepo: <a name="install-dependency"></a> |
| 114 | +packages/i18n 改造 |
109 | 115 |
|
110 |
| -### For root: <a name="install-dependency-for-root"></a> |
| 116 | +改为自己的语言包 |
111 | 117 |
|
112 |
| -1. Run `pnpm i <package> -w` |
| 118 | +pages/side-panel 改造 |
113 | 119 |
|
114 |
| -### For module: <a name="install-dependency-for-module"></a> |
115 | 120 |
|
116 |
| -1. Run `pnpm i <package> -F <module name>` |
117 | 121 |
|
118 |
| -`package` - Name of the package you want to install e.g. `nodemon` \ |
119 |
| -`module-name` - You can find it inside each `package.json` under the key `name`, e.g. `@extension/content-script`, you can use only `content-script` without `@extension/` prefix |
120 | 122 |
|
121 |
| -## Environment variables |
122 |
| - |
123 |
| -To add an environment variable: |
124 |
| - |
125 |
| -1. Copy `.example.env` to `.env` (in the same directory) |
126 |
| -2. Add a new record inside `.env`, prefixed with `VITE_`, e.g. `VITE_MY_API_KEY=...` |
127 |
| -3. Edit `./vite-env.d.ts` and in the `ImportMetaEnv` interface, add your variable with the appropriate type, e.g. |
128 |
| - |
129 |
| - `readonly VITE_MY_API_KEY: string;` |
130 |
| -4. Then you can read the variable via `import.meta.env.MY_API_KEY` (learn more at [Env Variables and Modes](https://vite.dev/guide/env-and-mode)) |
131 |
| - |
132 |
| -#### If you want to set it for each package independently: |
133 |
| - |
134 |
| -1. Create `.env` inside that package |
135 |
| -2. Open related `vite.config.mts` and add `envDir: '.'` at the end of this config |
136 |
| -3. Rest steps like above |
137 |
| - |
138 |
| -#### Remember you can't use global and local at the same time for the same package(It will be overwritten) |
139 |
| - |
140 |
| -## Boilerplate structure <a name="structure"></a> |
141 |
| - |
142 |
| -### Chrome extension <a name="structure-chrome-extension"></a> |
143 |
| - |
144 |
| -The extension lives in the `chrome-extension` directory and includes the following files: |
145 |
| - |
146 |
| -- [`manifest.js`](chrome-extension/manifest.js) - script that outputs the `manifest.json` |
147 |
| -- [`src/background`](chrome-extension/src/background) - [background script](https://developer.chrome.com/docs/extensions/mv3/background_pages/) |
148 |
| - (`background.service_worker` in manifest.json) |
149 |
| -- [`public`](chrome-extension/public/) - icons referenced in the manifest; content CSS for user's page injection |
150 |
| - |
151 |
| -> [!IMPORTANT] |
152 |
| -> To facilitate development, the boilerplate is configured to "Read and change all your data on all websites". |
153 |
| -> In production, it's best practice to limit the premissions to only the strictly necessary websites. See |
154 |
| -> [Declaring permissions](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions) |
155 |
| -> and edit `manifest.js` accordingly. |
156 |
| -
|
157 |
| -### Packages <a name="structure-packages"></a> |
158 |
| - |
159 |
| -Some shared packages: |
160 |
| - |
161 |
| -- `dev-utils` - utilities for Chrome extension development (manifest-parser, logger) |
162 |
| -- `i18n` - custom internationalization package; provides i18n function with type safety and other validation |
163 |
| -- `hmr` - custom HMR plugin for Vite, injection script for reload/refresh, HMR dev-server |
164 |
| -- `shared` - shared code for the entire project (types, constants, custom hooks, components etc.) |
165 |
| -- `storage` - helpers for easier integration with [storage](https://developer.chrome.com/docs/extensions/reference/api/storage), e.g. local/session storages |
166 |
| -- `tailwind-config` - shared Tailwind config for entire project |
167 |
| -- `tsconfig` - shared tsconfig for the entire project |
168 |
| -- `ui` - function to merge your Tailwind config with the global one; you can save components here |
169 |
| -- `vite-config` - shared Vite config for the entire project |
170 |
| -- `zipper` - run `pnpm zip` to pack the `dist` folder into `extension.zip` inside the newly created `dist-zip` |
171 |
| -- `e2e` - run `pnpm e2e` for end-to-end tests of your zipped extension on different browsers |
172 |
| - |
173 |
| -### Pages <a name="structure-pages"></a> |
174 |
| - |
175 |
| -Code that is transpiled to be part of the extension lives in the [pages](pages/) directory. |
176 |
| - |
177 |
| -- [`content`](pages/content/) - [content scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts) |
178 |
| - (`content_scripts` in manifest.json) |
179 |
| -- [`content-ui`](pages/content-ui) - React UI rendered in the current page (you can see it at the very bottom when you get started) |
180 |
| - (`content_scripts` in manifest.json) |
181 |
| -- [`content-runtime`](pages/content-runtime/src/) - [injected content scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts#functionality); |
182 |
| - this can be injected from `popup` like standard `content` |
183 |
| -- [`devtools`](pages/devtools/) - [extend the browser DevTools](https://developer.chrome.com/docs/extensions/how-to/devtools/extend-devtools#creating) |
184 |
| - (`devtools_page` in manifest.json) |
185 |
| -- [`devtools-panel`](pages/devtools-panel/) - [DevTools panel](https://developer.chrome.com/docs/extensions/reference/api/devtools/panels) |
186 |
| - for [devtools](pages/devtools/src/index.ts) |
187 |
| -- [`new-tab`](pages/new-tab/) - [override the default New Tab page](https://developer.chrome.com/docs/extensions/develop/ui/override-chrome-pages) |
188 |
| - (`chrome_url_overrides.newtab` in manifest.json) |
189 |
| -- [`options`](pages/options/) - [options page](https://developer.chrome.com/docs/extensions/develop/ui/options-page) |
190 |
| - (`options_page` in manifest.json) |
191 |
| -- [`popup`](pages/popup/) - [popup](https://developer.chrome.com/docs/extensions/reference/api/action#popup) shown when clicking the extension in the toolbar |
192 |
| - (`action.default_popup` in manifest.json) |
193 |
| -- [`side-panel`](pages/side-panel/) - [sidepanel (Chrome 114+)](https://developer.chrome.com/docs/extensions/reference/api/sidePanel) |
194 |
| - (`side_panel.default_path` in manifest.json) |
195 |
| - |
196 |
| -## Community |
197 |
| - |
198 |
| -To chat with other community members, you can join the [Discord](https://discord.gg/4ERQ6jgV9a) server. |
199 |
| -You can ask questions on that server, and you can also help others. |
200 |
| - |
201 |
| -Also, suggest new features or share any challenges you've faced while developing Chrome extensions! |
202 |
| - |
203 |
| -## Reference |
204 |
| - |
205 |
| -- [Chrome Extensions](https://developer.chrome.com/docs/extensions) |
206 |
| -- [Vite Plugin](https://vitejs.dev/guide/api-plugin.html) |
207 |
| -- [Rollup](https://rollupjs.org/guide/en/) |
208 |
| -- [Turborepo](https://turbo.build/repo/docs) |
209 |
| -- [Rollup-plugin-chrome-extension](https://www.extend-chrome.dev/rollup-plugin) |
210 |
| - |
211 |
| -## Star History <a name="star-history"></a> |
212 |
| - |
213 |
| -<a href="https://star-history.com/#Jonghakseo/chrome-extension-boilerplate-react-vite&Date"> |
214 |
| - <picture> |
215 |
| - <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Jonghakseo/chrome-extension-boilerplate-react-vite&type=Date&theme=dark" /> |
216 |
| - <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Jonghakseo/chrome-extension-boilerplate-react-vite&type=Date" /> |
217 |
| - <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Jonghakseo/chrome-extension-boilerplate-react-vite&type=Date" /> |
218 |
| - </picture> |
219 |
| -</a> |
220 |
| - |
221 |
| -## Contributors <a name="contributors"></a> |
222 |
| - |
223 |
| -This Boilerplate is made possible thanks to all of its contributors. |
224 |
| - |
225 |
| -<a href="https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite/graphs/contributors"> |
226 |
| - <img width="500px" src="https://contrib.rocks/image?repo=Jonghakseo/chrome-extension-boilerplate-react-vite" alt="All Contributors"/> |
227 |
| -</a> |
228 |
| - |
229 |
| ---- |
230 |
| - |
231 |
| -## Special Thanks To |
232 |
| - |
233 |
| -| <a href="https://jb.gg/OpenSourceSupport"><img width="40" src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains Logo (Main) logo."></a> | <a href="https://www.linkedin.com/in/j-acks0n"><img width="40" style="border-radius:50%" src='https://avatars.githubusercontent.com/u/23139754' alt='Jackson Hong'/></a> | |
234 |
| -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
235 |
| - |
236 |
| ---- |
237 |
| - |
238 |
| -Made by [Jonghakseo](https://jonghakseo.github.io/) |
0 commit comments