初始化
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
---
|
||||
inclusion: manual
|
||||
---
|
||||
|
||||
# Plasmo 框架技术说明
|
||||
|
||||
## 1️⃣ 框架定位
|
||||
|
||||
Plasmo 是一个 Chrome 扩展开发框架,核心价值是:**让你用写 React 项目的方式来写 Chrome 插件**。
|
||||
|
||||
它帮你处理了:
|
||||
- manifest.json 自动生成(不用手写)
|
||||
- TypeScript/React 编译打包(内置,不用配 webpack)
|
||||
- Content Script 样式隔离(Shadow DOM)
|
||||
- 开发时热更新(改代码自动刷新扩展)
|
||||
|
||||
## 2️⃣ 约定式文件结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── popup.tsx # 点击插件图标弹出的小窗口
|
||||
├── options.tsx # 插件设置页(右键图标→选项)
|
||||
├── newtab.tsx # 覆盖浏览器新标签页
|
||||
├── sidepanel.tsx # 浏览器侧边栏面板
|
||||
│
|
||||
├── background/
|
||||
│ └── index.ts # 后台 Service Worker,监听事件、做中转
|
||||
│
|
||||
├── contents/
|
||||
│ └── xxx.tsx / xxx.ts # 注入到目标网页里的脚本(可以有多个)
|
||||
│
|
||||
├── components/ # 自己的 UI 组件(非框架约定)
|
||||
│ └── Button.tsx
|
||||
│
|
||||
└── lib/ # 工具函数(非框架约定)
|
||||
└── api.ts
|
||||
```
|
||||
|
||||
**核心规则:文件放对位置就自动生效,不需要任何注册或配置。**
|
||||
|
||||
| 文件 | 有就生效,没有就没这功能 |
|
||||
|------|------------------------|
|
||||
| `popup.tsx` | 有 → 点图标弹窗;没有 → 点图标触发 background 事件 |
|
||||
| `options.tsx` | 有 → 有设置页;没有 → 没设置页 |
|
||||
| `newtab.tsx` | 有 → 新标签页被接管;没有 → 正常新标签页 |
|
||||
| `sidepanel.tsx` | 有 → 有浏览器侧边栏;没有 → 没有 |
|
||||
| `background/index.ts` | 有 → 有后台服务;没有 → 没后台逻辑 |
|
||||
| `contents/任意名.tsx` | 有几个就注入几个脚本到网页里 |
|
||||
|
||||
## 3️⃣ 文件后缀规则
|
||||
|
||||
跟目录无关,跟内容有关:
|
||||
|
||||
| 后缀 | 能写 HTML 标签(JSX)吗 | 用途 |
|
||||
|------|------------------------|------|
|
||||
| `.ts` | ❌ 不能 | 纯逻辑、工具函数、类型定义 |
|
||||
| `.tsx` | ✅ 能 | 任何需要写 `<div>`、`<button>` 等标签的文件 |
|
||||
|
||||
**简单记:有尖括号标签的用 `.tsx`,没有的用 `.ts`。**
|
||||
|
||||
## 4️⃣ TSX vs Vue 文件对比
|
||||
|
||||
| | `.vue` | `.tsx` |
|
||||
|--|--------|--------|
|
||||
| 框架 | Vue | React |
|
||||
| 结构 | template / script / style 三段式 | 全部写在一个函数里 |
|
||||
| HTML 写法 | 写在 `<template>` 里,正常 HTML | 写在 JS 的 return 里,叫 JSX |
|
||||
| 变量绑定 | `{{ msg }}` 双花括号 | `{msg}` 单花括号 |
|
||||
| 思路 | HTML 为主,往里面插逻辑 | JS 为主,在逻辑里写 HTML |
|
||||
|
||||
**一句话:`.vue` 是"HTML 里面嵌 JS",`.tsx` 是"JS 里面嵌 HTML"。**
|
||||
|
||||
## 5️⃣ Background Service Worker
|
||||
|
||||
### 执行时机
|
||||
- **没有固定执行时机**,完全由事件驱动
|
||||
- 有事件触发时唤醒,没事干 30 秒左右自动休眠
|
||||
- 全局只有一个实例
|
||||
|
||||
### 能做什么
|
||||
- 监听插件图标点击
|
||||
- 接收/转发消息(content script ↔ background)
|
||||
- 调用 `chrome.cookies`、`chrome.tabs` 等完整 Chrome API
|
||||
- 定时任务(必须用 `chrome.alarms`,不能用 `setInterval`)
|
||||
|
||||
### 不能做什么
|
||||
- 不能访问 DOM(没有页面)
|
||||
- 不能写持续运行的逻辑(会被休眠打断)
|
||||
|
||||
### 代码结构
|
||||
里面基本全是事件监听器注册:
|
||||
```ts
|
||||
chrome.action.onClicked.addListener(...) // 图标被点击
|
||||
chrome.runtime.onMessage.addListener(...) // 收到消息
|
||||
chrome.runtime.onInstalled.addListener(...) // 安装/更新
|
||||
```
|
||||
|
||||
## 6️⃣ Content Script
|
||||
|
||||
### 执行时机
|
||||
- 页面加载时自动注入(匹配 `matches` 规则的 URL)
|
||||
- 默认在 `document_idle` 时机注入(DOM 解析完成后)
|
||||
- 每个匹配的标签页各一个独立实例(内存不共享)
|
||||
|
||||
### 能做什么
|
||||
- 读写目标网页的 DOM
|
||||
- 往网页里注入 UI 组件(通过 Shadow DOM 隔离样式)
|
||||
- 通过 `chrome.runtime.sendMessage` 与 background 通信
|
||||
- 调用部分 Chrome API(storage、runtime 等)
|
||||
|
||||
### 不能做什么
|
||||
- 不能直接调用 `chrome.cookies`(需要通过 background 中转)
|
||||
- 不能访问其他标签页
|
||||
|
||||
### 两种用法
|
||||
| 用法 | 文件后缀 | 例子 |
|
||||
|------|----------|------|
|
||||
| 往网页里塞 UI | `.tsx` | 侧边栏面板、悬浮按钮 |
|
||||
| 只跑逻辑不画界面 | `.ts` | 读取页面数据、监听事件 |
|
||||
|
||||
## 7️⃣ Content Script UI(Shadow DOM)
|
||||
|
||||
当 content script 需要往网页里渲染 UI 时,Plasmo 自动用 Shadow DOM 包裹:
|
||||
|
||||
```
|
||||
目标网页
|
||||
├── 网页自己的 HTML、CSS
|
||||
└── Shadow DOM(隔离墙)
|
||||
└── 你的 React 组件 + 你的样式
|
||||
```
|
||||
|
||||
- 网页的 CSS 影响不到你的组件
|
||||
- 你的 CSS 也不会搞乱网页
|
||||
- 通过 `getStyle` 导出函数将样式注入 Shadow DOM 内部
|
||||
|
||||
## 8️⃣ Manifest 配置
|
||||
|
||||
Plasmo 不需要手写 `manifest.json`,通过 `package.json` 的 `manifest` 字段声明权限:
|
||||
|
||||
```json
|
||||
{
|
||||
"manifest": {
|
||||
"permissions": ["activeTab", "storage", "tabs", "cookies"],
|
||||
"host_permissions": ["<all_urls>"],
|
||||
"action": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
框架会自动合并源码中的信息(如 content script 的 matches 配置)生成最终的 manifest.json。
|
||||
|
||||
## 9️⃣ 开发工作流
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 开发模式(热更新)
|
||||
npm run dev
|
||||
# 产物在 build/chrome-mv3-dev
|
||||
|
||||
# 生产构建
|
||||
npm run build
|
||||
# 产物在 build/chrome-mv3-prod
|
||||
|
||||
# 打包 zip(用于上架)
|
||||
npm run package
|
||||
```
|
||||
|
||||
### 加载到 Chrome
|
||||
1. 打开 `chrome://extensions/`
|
||||
2. 右上角开启「开发者模式」
|
||||
3. 点击「加载已解压的扩展程序」
|
||||
4. 选择 `build/chrome-mv3-dev` 目录
|
||||
|
||||
### 查看日志
|
||||
| 代码位置 | 在哪看日志 |
|
||||
|----------|-----------|
|
||||
| Background | 扩展管理页 → 点击 "Service Worker" 链接 → 打开 DevTools |
|
||||
| Content Script | 目标网页 → F12 → Console |
|
||||
| Popup / SidePanel | 右键插件图标 → 审查弹出内容 |
|
||||
|
||||
## 🔟 环境变量
|
||||
|
||||
Plasmo 支持 `.env` 文件,变量必须以 `PLASMO_PUBLIC_` 前缀命名才能在代码中访问:
|
||||
|
||||
```env
|
||||
PLASMO_PUBLIC_API_URL=http://localhost:8080/api
|
||||
```
|
||||
|
||||
代码中通过 `process.env.PLASMO_PUBLIC_API_URL` 读取。
|
||||
|
||||
> 本项目未使用此机制,而是通过 `src/config.ts` 手动管理多环境配置。
|
||||
Reference in New Issue
Block a user