├── .gitignore ├── README.md ├── manifest.ts ├── package.json ├── pnpm-lock.yaml ├── rsbuild.config.ts ├── src ├── background │ └── index.ts ├── devtools │ ├── devtools.tsx │ ├── index.html │ └── index.tsx ├── env.d.ts └── popup │ ├── index.html │ ├── index.tsx │ └── popup.tsx └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Local 2 | .DS_Store 3 | *.local 4 | *.log* 5 | 6 | # Dist 7 | node_modules 8 | dist/ 9 | 10 | # IDE 11 | .vscode/* 12 | !.vscode/extensions.json 13 | .idea 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chrome Extension Boilerplate with React + Rsbuild + TypeScript 2 | 3 | ## Features 4 | 5 | - [React 18](https://reactjs.org/) 6 | - [TypeScript](https://www.typescriptlang.org/) 7 | - [Rsbuild](https://rsbuild.dev/) 8 | - [Chrome Extension Manifest Version 3](https://developer.chrome.com/docs/extensions/mv3/intro/) 9 | 10 | ## Installing and Running 11 | 12 | ### Procedures: 13 | 14 | 1. Clone this repository. 15 | 2. Change the package's name and description in package.json. 16 | 3. Run `pnpm install` to install the dependencies. 17 | 18 | ## And next, depending on the needs: 19 | 20 | ### For Chrome: 21 | 22 | 1. Run: 23 | - Dev: `pnpm dev` or `npm run dev` 24 | - Prod: `pnpm build` or `npm run build` 25 | 2. Open in browser - `chrome://extensions` 26 | 3. Check - `Developer mode` 27 | 4. Click - `Load unpacked extension` 28 | 5. Select - `dist` folder 29 | 30 | ### For Firefox: 31 | 32 | 1. Run: 33 | - Dev: `pnpm dev:firefox` or `npm run dev:firefox` 34 | - Prod: `pnpm build:firefox` or `npm run build:firefox` 35 | 2. Open in browser - `about:debugging#/runtime/this-firefox` 36 | 3. Click - `Load Temporary Add-on...` 37 | 4. Select - `dist` folder 38 | -------------------------------------------------------------------------------- /manifest.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | const packageJson = JSON.parse(fs.readFileSync("./package.json", "utf8")); 3 | 4 | const manifest: chrome.runtime.ManifestV3 = { 5 | manifest_version: 3, 6 | name: packageJson.name, 7 | version: packageJson.version, 8 | description: packageJson.description || "", 9 | action: { 10 | default_popup: "./src/popup/index.html", 11 | }, 12 | background: { 13 | service_worker: "./src/background/index.ts", 14 | type: "module", 15 | }, 16 | devtools_page: "./src/devtools/index.html", 17 | }; 18 | 19 | export default manifest; 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rsbuild-chrome-extension-boilerplate-react", 3 | "description": "A boilerplate for building Chrome extensions with rsbuild and React", 4 | "private": true, 5 | "version": "1.0.0", 6 | "scripts": { 7 | "dev": "rsbuild dev --open", 8 | "build:watch": "rsbuild build --watch", 9 | "build": "rsbuild build", 10 | "preview": "rsbuild preview" 11 | }, 12 | "type": "module", 13 | "dependencies": { 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0" 16 | }, 17 | "devDependencies": { 18 | "rsbuild-plugin-web-extension": "^0.0.10", 19 | "@rsbuild/core": "^1.0.16", 20 | "@rsbuild/plugin-react": "^1.0.5", 21 | "@types/chrome": "^0.0.263", 22 | "@types/node": "^20.11.28", 23 | "@types/react": "^18.2.47", 24 | "@types/react-dom": "^18.2.18", 25 | "typescript": "^5.4.2" 26 | } 27 | } -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | react: 9 | specifier: ^18.2.0 10 | version: 18.2.0 11 | react-dom: 12 | specifier: ^18.2.0 13 | version: 18.2.0(react@18.2.0) 14 | 15 | devDependencies: 16 | '@rsbuild/core': 17 | specifier: ^1.0.16 18 | version: 1.0.16 19 | '@rsbuild/plugin-react': 20 | specifier: ^1.0.5 21 | version: 1.0.5(@rsbuild/core@1.0.16) 22 | '@types/chrome': 23 | specifier: ^0.0.263 24 | version: 0.0.263 25 | '@types/node': 26 | specifier: ^20.11.28 27 | version: 20.11.28 28 | '@types/react': 29 | specifier: ^18.2.47 30 | version: 18.2.47 31 | '@types/react-dom': 32 | specifier: ^18.2.18 33 | version: 18.2.18 34 | rsbuild-plugin-web-extension: 35 | specifier: ^0.0.10 36 | version: 0.0.10(@rsbuild/core@1.0.16) 37 | typescript: 38 | specifier: ^5.4.2 39 | version: 5.4.2 40 | 41 | packages: 42 | 43 | /@module-federation/runtime-tools@0.5.1: 44 | resolution: {integrity: sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==} 45 | dependencies: 46 | '@module-federation/runtime': 0.5.1 47 | '@module-federation/webpack-bundler-runtime': 0.5.1 48 | dev: true 49 | 50 | /@module-federation/runtime@0.5.1: 51 | resolution: {integrity: sha512-xgiMUWwGLWDrvZc9JibuEbXIbhXg6z2oUkemogSvQ4LKvrl/n0kbqP1Blk669mXzyWbqtSp6PpvNdwaE1aN5xQ==} 52 | dependencies: 53 | '@module-federation/sdk': 0.5.1 54 | dev: true 55 | 56 | /@module-federation/sdk@0.5.1: 57 | resolution: {integrity: sha512-exvchtjNURJJkpqjQ3/opdbfeT2wPKvrbnGnyRkrwW5o3FH1LaST1tkiNviT6OXTexGaVc2DahbdniQHVtQ7pA==} 58 | dev: true 59 | 60 | /@module-federation/webpack-bundler-runtime@0.5.1: 61 | resolution: {integrity: sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==} 62 | dependencies: 63 | '@module-federation/runtime': 0.5.1 64 | '@module-federation/sdk': 0.5.1 65 | dev: true 66 | 67 | /@rsbuild/core@1.0.16: 68 | resolution: {integrity: sha512-ioQg9HfDh5eXPZi+An7yCRaSE9TH4W3IBqrxBrv4IjOg/ajpVpKidiKwyYpX3QPbxY1ybfvQTH7HwATND4crCA==} 69 | engines: {node: '>=16.7.0'} 70 | hasBin: true 71 | dependencies: 72 | '@rspack/core': 1.0.13(@swc/helpers@0.5.13) 73 | '@rspack/lite-tapable': 1.0.1 74 | '@swc/helpers': 0.5.13 75 | core-js: 3.38.1 76 | optionalDependencies: 77 | fsevents: 2.3.3 78 | dev: true 79 | 80 | /@rsbuild/plugin-react@1.0.5(@rsbuild/core@1.0.16): 81 | resolution: {integrity: sha512-9n3oaWH36y07C5vmQOHhPscKkM14cJZEapozopvSzNXyEHLRN4PFhPhJB6tFA5C/yXnxo8BQCKYw2ejNL0gdvA==} 82 | peerDependencies: 83 | '@rsbuild/core': 1.x || ^1.0.1-rc.0 84 | dependencies: 85 | '@rsbuild/core': 1.0.16 86 | '@rspack/plugin-react-refresh': 1.0.0(react-refresh@0.14.2) 87 | react-refresh: 0.14.2 88 | dev: true 89 | 90 | /@rspack/binding-darwin-arm64@1.0.13: 91 | resolution: {integrity: sha512-HepE4V5Rj53o+o8AMzlkdeBxZnsyXKrOJ2oumVtqRLXihVlMguYwNTSkjfmjAqq/4PJAhEeaeIFyomZg+zKC0A==} 92 | cpu: [arm64] 93 | os: [darwin] 94 | requiresBuild: true 95 | dev: true 96 | optional: true 97 | 98 | /@rspack/binding-darwin-x64@1.0.13: 99 | resolution: {integrity: sha512-ucHf0q2V+K19z75BvjU6EbQggNFiz1/xJ5tSgOXUfRu5omZF1jpN/epeMGqh0MkExRwOMYKJR/pVHDw5ITcU8g==} 100 | cpu: [x64] 101 | os: [darwin] 102 | requiresBuild: true 103 | dev: true 104 | optional: true 105 | 106 | /@rspack/binding-linux-arm64-gnu@1.0.13: 107 | resolution: {integrity: sha512-0fqLWDG9Z2VKxy3u6+jLVJgT2E24Xb2umP4Jtx2uNf2+aHLXifgqUdwgCElO+dj+PpOp/q8zmV5U2DXykvPU3w==} 108 | cpu: [arm64] 109 | os: [linux] 110 | requiresBuild: true 111 | dev: true 112 | optional: true 113 | 114 | /@rspack/binding-linux-arm64-musl@1.0.13: 115 | resolution: {integrity: sha512-eK72/jAofJRcZ23FTteUh1MfTbErWYNwVLuxnliyf1f1PwH0a7exGE6ik0/y/LdAt5PWP1r8r981EEjrpsTfRQ==} 116 | cpu: [arm64] 117 | os: [linux] 118 | requiresBuild: true 119 | dev: true 120 | optional: true 121 | 122 | /@rspack/binding-linux-x64-gnu@1.0.13: 123 | resolution: {integrity: sha512-C9wGDim1Euc10qRk5ztPvgK4NAi6bi6Ck3+ugaRzYXPFIVegnFyXu2fv42j3Y0LRhBjnKMXZJzME5nQUPuT6Ug==} 124 | cpu: [x64] 125 | os: [linux] 126 | requiresBuild: true 127 | dev: true 128 | optional: true 129 | 130 | /@rspack/binding-linux-x64-musl@1.0.13: 131 | resolution: {integrity: sha512-7bQyGEoMCxXUS+RDo6qej8JjqS8kYd8CvlnfYZVUqWgCxgn19j29lKvWVibey0lnFpoJrqReOdSypbk91tSrzA==} 132 | cpu: [x64] 133 | os: [linux] 134 | requiresBuild: true 135 | dev: true 136 | optional: true 137 | 138 | /@rspack/binding-win32-arm64-msvc@1.0.13: 139 | resolution: {integrity: sha512-6QOHiCwaQeCZApWRe1y8ZNZGOj00EFdX1ypOc3R1GrfSjn+UjoKhbBtgVl2w+sPTaCZ4SvknOk9usSgcWO4gOQ==} 140 | cpu: [arm64] 141 | os: [win32] 142 | requiresBuild: true 143 | dev: true 144 | optional: true 145 | 146 | /@rspack/binding-win32-ia32-msvc@1.0.13: 147 | resolution: {integrity: sha512-ucm7emxYDjTsOGNwgYGz30oKcnzXLjg/Fcs0mNMmQgMEFpwBXhczfKJimCyMIlAhQCFPP4WzrXFdf03EPuw6CA==} 148 | cpu: [ia32] 149 | os: [win32] 150 | requiresBuild: true 151 | dev: true 152 | optional: true 153 | 154 | /@rspack/binding-win32-x64-msvc@1.0.13: 155 | resolution: {integrity: sha512-9G/hvr47ECjDEmBCyyQTZFilmEOIQJCQvpx6hUgDWsfUApwF9LZBW/PqBCSwhY+tIErr/AurJnBVAYub0MYpHA==} 156 | cpu: [x64] 157 | os: [win32] 158 | requiresBuild: true 159 | dev: true 160 | optional: true 161 | 162 | /@rspack/binding@1.0.13: 163 | resolution: {integrity: sha512-mnSCZ3Qb/I3LzsYoo24AG4LgmaSOIc1CS38A9L9nv4MJj8x+1D2BaLErpaaMmhqI3lQBIcBSQkN7+WbpsCP3Uw==} 164 | optionalDependencies: 165 | '@rspack/binding-darwin-arm64': 1.0.13 166 | '@rspack/binding-darwin-x64': 1.0.13 167 | '@rspack/binding-linux-arm64-gnu': 1.0.13 168 | '@rspack/binding-linux-arm64-musl': 1.0.13 169 | '@rspack/binding-linux-x64-gnu': 1.0.13 170 | '@rspack/binding-linux-x64-musl': 1.0.13 171 | '@rspack/binding-win32-arm64-msvc': 1.0.13 172 | '@rspack/binding-win32-ia32-msvc': 1.0.13 173 | '@rspack/binding-win32-x64-msvc': 1.0.13 174 | dev: true 175 | 176 | /@rspack/core@1.0.13(@swc/helpers@0.5.13): 177 | resolution: {integrity: sha512-lh8toWSWcYjlOuriQ8/h0U8riaaRQfzwU0oUNykFj1xokJMSKIQFH5WQWj2DQ386uHNv52nMbc+Jiuml1vYboA==} 178 | engines: {node: '>=16.0.0'} 179 | peerDependencies: 180 | '@swc/helpers': '>=0.5.1' 181 | peerDependenciesMeta: 182 | '@swc/helpers': 183 | optional: true 184 | dependencies: 185 | '@module-federation/runtime-tools': 0.5.1 186 | '@rspack/binding': 1.0.13 187 | '@rspack/lite-tapable': 1.0.1 188 | '@swc/helpers': 0.5.13 189 | caniuse-lite: 1.0.30001669 190 | dev: true 191 | 192 | /@rspack/lite-tapable@1.0.1: 193 | resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} 194 | engines: {node: '>=16.0.0'} 195 | dev: true 196 | 197 | /@rspack/plugin-react-refresh@1.0.0(react-refresh@0.14.2): 198 | resolution: {integrity: sha512-WvXkLewW5G0Mlo5H1b251yDh5FFiH4NDAbYlFpvFjcuXX2AchZRf9zdw57BDE/ADyWsJgA8kixN/zZWBTN3iYA==} 199 | peerDependencies: 200 | react-refresh: '>=0.10.0 <1.0.0' 201 | peerDependenciesMeta: 202 | react-refresh: 203 | optional: true 204 | dependencies: 205 | error-stack-parser: 2.1.4 206 | html-entities: 2.5.2 207 | react-refresh: 0.14.2 208 | dev: true 209 | 210 | /@swc/helpers@0.5.13: 211 | resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} 212 | dependencies: 213 | tslib: 2.6.2 214 | dev: true 215 | 216 | /@types/chrome@0.0.263: 217 | resolution: {integrity: sha512-As0vzv99ov3M6ZR7R6VzhMWFZXkPMrFrCEXXVrMN576Cm70fTkj7Df2CF+qEo170JepX50pd11cX6O4DSAtl2Q==} 218 | dependencies: 219 | '@types/filesystem': 0.0.35 220 | '@types/har-format': 1.2.15 221 | dev: true 222 | 223 | /@types/filesystem@0.0.35: 224 | resolution: {integrity: sha512-1eKvCaIBdrD2mmMgy5dwh564rVvfEhZTWVQQGRNn0Nt4ZEnJ0C8oSUCzvMKRA4lGde5oEVo+q2MrTTbV/GHDCQ==} 225 | dependencies: 226 | '@types/filewriter': 0.0.33 227 | dev: true 228 | 229 | /@types/filewriter@0.0.33: 230 | resolution: {integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==} 231 | dev: true 232 | 233 | /@types/har-format@1.2.15: 234 | resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} 235 | dev: true 236 | 237 | /@types/node@20.11.28: 238 | resolution: {integrity: sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==} 239 | dependencies: 240 | undici-types: 5.26.5 241 | dev: true 242 | 243 | /@types/prop-types@15.7.11: 244 | resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} 245 | dev: true 246 | 247 | /@types/react-dom@18.2.18: 248 | resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} 249 | dependencies: 250 | '@types/react': 18.2.47 251 | dev: true 252 | 253 | /@types/react@18.2.47: 254 | resolution: {integrity: sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==} 255 | dependencies: 256 | '@types/prop-types': 15.7.11 257 | '@types/scheduler': 0.16.8 258 | csstype: 3.1.3 259 | dev: true 260 | 261 | /@types/scheduler@0.16.8: 262 | resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} 263 | dev: true 264 | 265 | /caniuse-lite@1.0.30001669: 266 | resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} 267 | dev: true 268 | 269 | /core-js@3.38.1: 270 | resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} 271 | requiresBuild: true 272 | dev: true 273 | 274 | /csstype@3.1.3: 275 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 276 | dev: true 277 | 278 | /error-stack-parser@2.1.4: 279 | resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} 280 | dependencies: 281 | stackframe: 1.3.4 282 | dev: true 283 | 284 | /fsevents@2.3.3: 285 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 286 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 287 | os: [darwin] 288 | requiresBuild: true 289 | dev: true 290 | optional: true 291 | 292 | /html-entities@2.5.2: 293 | resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} 294 | dev: true 295 | 296 | /js-tokens@4.0.0: 297 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 298 | dev: false 299 | 300 | /loose-envify@1.4.0: 301 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 302 | hasBin: true 303 | dependencies: 304 | js-tokens: 4.0.0 305 | dev: false 306 | 307 | /react-dom@18.2.0(react@18.2.0): 308 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 309 | peerDependencies: 310 | react: ^18.2.0 311 | dependencies: 312 | loose-envify: 1.4.0 313 | react: 18.2.0 314 | scheduler: 0.23.0 315 | dev: false 316 | 317 | /react-refresh@0.14.2: 318 | resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} 319 | engines: {node: '>=0.10.0'} 320 | dev: true 321 | 322 | /react@18.2.0: 323 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 324 | engines: {node: '>=0.10.0'} 325 | dependencies: 326 | loose-envify: 1.4.0 327 | dev: false 328 | 329 | /rsbuild-plugin-web-extension@0.0.10(@rsbuild/core@1.0.16): 330 | resolution: {integrity: sha512-YVwcFEjV4q5iKxChvYfjh3A+13oaw/KF17JH19KVBswYFCpbD9HH6C5PljaJZvDGA9d4OeR83EN1D/9E8IyRJQ==} 331 | peerDependencies: 332 | '@rsbuild/core': 1.x 333 | dependencies: 334 | '@rsbuild/core': 1.0.16 335 | dev: true 336 | 337 | /scheduler@0.23.0: 338 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 339 | dependencies: 340 | loose-envify: 1.4.0 341 | dev: false 342 | 343 | /stackframe@1.3.4: 344 | resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} 345 | dev: true 346 | 347 | /tslib@2.6.2: 348 | resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} 349 | dev: true 350 | 351 | /typescript@5.4.2: 352 | resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} 353 | engines: {node: '>=14.17'} 354 | hasBin: true 355 | dev: true 356 | 357 | /undici-types@5.26.5: 358 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 359 | dev: true 360 | -------------------------------------------------------------------------------- /rsbuild.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "@rsbuild/core"; 2 | import { pluginReact } from "@rsbuild/plugin-react"; 3 | import { pluginWebExtension } from "rsbuild-plugin-web-extension"; 4 | import manifest from "./manifest"; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | pluginReact(), 9 | pluginWebExtension({ 10 | manifest, 11 | }), 12 | ], 13 | }); 14 | -------------------------------------------------------------------------------- /src/background/index.ts: -------------------------------------------------------------------------------- 1 | console.log("background script"); 2 | -------------------------------------------------------------------------------- /src/devtools/devtools.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export const DevTools = () => { 4 | const [count, setCount] = useState(0); 5 | 6 | return ( 7 |
Count: {count}
9 | 10 |Count: {count}
9 | 10 |