惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
爱范儿
爱范儿
Y
Y Combinator Blog
Last Week in AI
Last Week in AI
博客园 - Franky
MongoDB | Blog
MongoDB | Blog
aimingoo的专栏
aimingoo的专栏
T
Tailwind CSS Blog
Microsoft Azure Blog
Microsoft Azure Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
月光博客
月光博客
Martin Fowler
Martin Fowler
A
About on SuperTechFans
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
J
Java Code Geeks
博客园 - 聂微东
宝玉的分享
宝玉的分享

Last Blog

CMU 15-213 Attack Lab GAMES101 [1] Affine Transformation & Projection CMU 15-213 Bomblab CMU 15-213 [1] Scribe.cx 2 - 对话与持久化存储 关于 X11 与 Wayland 的剪贴板同步问题 关于 X11 与 Wayland 的剪贴板同步问题 Page Assist 2025 年终总结 2025 年终总结 Linuxqq 粘贴板同步问题 关于所谓“配置工程师” 记一次小端序内存的实际体现 CS110L L3 - Memory Safety in Rust CS110L L2 - Program Analysis CS110L L1 - Safety in System Programming 在 Neovim(v0.10+) 上使用 arduino-language-server PA3 - Batch Processing System 2024 年终总结 Arcaea 曲名匹配器 Arcaea 曲名匹配器 PA W9 - Linking & Loading Hyprland 二周目 Hyprland 二周目 PA2 Part 2 - Emulated Hardware Device PA W8 - IO Devices Learn C the Hard Way PA2 Part 1 - Instruction Set Implementation & KLIB Learning Makefile with PA 阅读 MQTTX 项目:Protobuf Test Case
Scribe.cx 1 - 跨浏览器的插件侧板控制
Last · 2026-01-30 · via Last Blog

webextension-polyfill

  • 查阅 wxt 相关 README

    1
    pnpm i @wxt-dev/webextension-polyfill webextension-polyfill
  • 以及在 wxt.config.ts 中加入:

    1
    2
    3
    4
    5
    export default defineConfig({

    modules: ["@wxt-dev/webextension-polyfill"]

    });
  • 此外,还需要 @types/webextension-polyfill 以及 @types/firefox-webext-browser 来扩展 browser 的 Firefox 成员。

    1
    pnpm i -D @types/firefox-webext-browser

括号作为行开头

semi-1.png

semi-2.png

  • 这就是 JavaScript ASI 吗,给我整笑了。

默认打开 Side Panel

Firefox

  • 经测试,manifest.json 中的 sidebar_action 或者 side_panel 事实上没有任何作用。

  • 也可能是 WXT 抹平了这其中的一些坑,没有细究。


  • 对于 Firefox,点击扩展图标触发 listener 函数的机制和 default_popup冲突 的,这意味着如果浏览器发现 manifest 中的 action 一项中存在 default_popup,那么点击扩展图标只会打开 popup 窗口而不会触发 background.ts 中挂载的 listener 函数。

  • 因此,想要默认打开侧板,需要删除 entrypoints 中的 popup 来防止 wxt 自动在 manifest.json 中生成 default_popup

  • 但是不能完全删去 action,因为这样一来background.ts 就无法访问 browser.browserAction 或者 browser.action

    https://github.com/wxt-dev/wxt/issues/669
    https://wxt.dev/guide/essentials/config/manifest.html#action-without-popup

    • 可以在 wxt.config.ts 中的 manifest 部分添加一个空的 action,如下所示:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      export default defineConfig({

      manifest: {

      action: {}

      }

      });
  • 然后在 background.ts 中注册监听函数:

    1
    2
    3
    4
    5
    if (import.meta.env.MANIFEST_VERSION === 3) {
    browser.action.onClicked.addListener(sidePanelManager.open);
    } else {
    browser.browserAction.onClicked.addListener(sidePanelManager.open);
    }

Chrome

  • 同样的,需要 manifest.json 中包含 action,且需要删除 popup

    https://developer.chrome.com/docs/extensions/reference/api/sidePanel#open-action-icon

  • 经测试,当 PanelBehavior 中的 openPanelOnActionClick 被设为 true 的时候,点击扩展图标同样不会触发 background.ts 中挂载的 listener 函数。

  • openPanelOnActionClick 默认设置为 false,保险起见再手动设置一遍:

    1
    2
    3
    4
    5
    6
    7


    if (import.meta.env.CHROME && typeof chrome.sidePanel?.setPanelBehavior === "function") {
    chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: false }).catch((error) => {
    console.error("[Chrome] Error resetting panel behavior: ", error);
    });
    }

完整代码

@/utils/sidepanel.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Tabs } from "webextension-polyfill";






export interface SidePanelManager {




open: (tab: Tabs.Tab) => Promise<void>;
}





async function ChromeOpenSidePanel(tab: Tabs.Tab) {

if (typeof chrome.sidePanel?.open !== "function") {
console.error(
"[Chrome] sidePanel.open is not available. Check 'sidePanel' permission and ensure Chrome version >= 116"
);
return;
}


const windowId = tab.windowId ?? chrome.windows.WINDOW_ID_CURRENT;

try {
await chrome.sidePanel.open({ windowId: tab.windowId });
console.log("[Chrome] Side panel opened via action click.");
} catch (error) {
console.error("[Chrome] Failed to open side panel: ", error);
}
}





async function FirefoxOpenSidePanel(tab: Tabs.Tab) {
try {
await browser.sidebarAction.open();
console.log("[Firefox] Side panel opened via action click.");
} catch (error) {
console.error("[Firefox] Failed to open side panel: ", error);
}
}

const panelImpl: Record<string, SidePanelManager> = {
chrome: { open: ChromeOpenSidePanel },
firefox: { open: FirefoxOpenSidePanel }
};





export const sidePanelManager: SidePanelManager =
panelImpl[import.meta.env.BROWSER] ?? panelImpl["chrome"];













export function openSidePanelAsDefault() {



if (import.meta.env.MANIFEST_VERSION === 3) {
browser.action.onClicked.addListener(sidePanelManager.open);
} else {
browser.browserAction.onClicked.addListener(sidePanelManager.open);
}



if (import.meta.env.CHROME && typeof chrome.sidePanel?.setPanelBehavior === "function") {
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: false }).catch((error) => {
console.error("[Chrome] Error resetting panel behavior: ", error);
});
}
}
  • Title: Scribe.cx 1 - 跨浏览器的插件侧板控制
  • Author: Last
  • Created at : 2026-01-30 17:08:26
  • Link: https://blog.imlast.top/2026/01/30/scribecx-1/
  • License: This work is licensed under CC BY-NC-SA 4.0.

On this page

Scribe.cx 1 - 跨浏览器的插件侧板控制

  1. webextension-polyfill
  2. 括号作为行开头
  3. 默认打开 Side Panel
    1. Firefox
    2. Chrome
    3. 完整代码