迁移到 Manifest V3
让你朝着正确的方向前进。
本指南为开发人员提供了开始将扩展从 Manifest V2 迁移到 Manifest V3 (MV3) 所需的信息。一些扩展只需要很少的改动就可以使它们符合 MV3,而另一些扩展则需要在一定程度上重新设计。具有 MV2 经验以及正在创建新的 MV3 扩展的开发人员也可能会发现这很有帮助。有关快速参考指南,请参阅迁移清单。
Manifest V3 提供了许多反映我们平台愿景目标的改进。
# 功能总结
使用 MV3 的扩展有许多新特性和功能更改:
- Service workers 替换 background pages.
- 现在使用新的 declarativeNetRequest API 处理网络请求修改。
- 不再允许远程托管代码;扩展只能执行包含在其包中的 JavaScript。
- Promise 支持已添加到许多方法中,但仍支持回调作为替代方法。 (我们最终将支持对所有适当方法的承诺。)
- MV3 中还引入了许多其他相对较小的功能更改。
有关这些更改的更完整说明,请参阅 MV3 概述。
# 更新 manifest.json 文件
要使用 MV3 的功能,您需要先更新您的manifest文件。当然,您会将清单版本更改为“3”,但您还需要在manifest文件中更改许多其他内容:
# Manifest 版本
更改 manifest_version 元素的值是升级扩展的关键。这决定了您使用的是 MV2 还是 MV3 功能集:
// Manifest V2
"manifest_version": 2
// Manifest V3
"manifest_version": 3
# Host permissions
在 MV3 中,您需要将host权限与其他权限分开指定:
// Manifest V2
"permissions": [
"tabs",
"bookmarks",
"http://www.blogger.com/",
],
"optional_permissions": [
"*://*/*",
"unlimitedStorage"
]
// Manifest V3
"permissions": [
"tabs",
"bookmarks"
],
"optional_permissions": [
"unlimitedStorage"
],
"host_permissions": [
"http://www.blogger.com/",
"*://*/*"
],
警告!
您不必在 host_permissions 中声明内容脚本匹配模式来注入内容脚本。但是,Chrome 网上应用店审核流程会将它们视为host权限请求。
# 内容安全政策
扩展的内容安全策略 (CSP) 在 MV2 中指定为字符串;在 MV3 中,它是一个对象,其成员代表替代 CSP 上下文:
// Manifest V2
"content_security_policy": "..."
// Manifest V3
"content_security_policy": {
"extension_pages": "...",
"sandbox": "..."
}
extension_pages
:此策略涵盖扩展程序中的页面,包括 html 文件和 Service Worker。
这些页面类型由 chrome-extension://
协议提供。例如,扩展程序中的页面是 chrome-extension://<extension-id>/foo.html
。
此外,MV3 不允许对 MV2 中允许的 extension_pages
进行某些 CSP 修改。script-src
、object-src
和 worker-src
指令可能只有以下值:
self
none
- 任何本地主机源,(
http://localhost
、http://127.0.0.1
或这些域上的任何端口)
sandbox
(沙箱)的 CSP 修改没有这样的新限制。
# Action API 统一
在 MV2 中,有两种不同的 API 来实现操作:browser_action
和 page_action
。这些 API 在引入时扮演了不同的角色,但随着时间的推移,它们变得多余,因此在 MV3 中,我们将它们统一为单个操作 API:
// Manifest V2
// manifest.json
{
"browser_action": { … },
"page_action": { … }
}
// background.js
chrome.browserAction.onClicked.addListener(tab => { … });
chrome.pageAction.onClicked.addListener(tab => { … });
// Manifest V3
// manifest.json
{
"action": { … }
}
// background.js
chrome.action.onClicked.addListener(tab => { … });
# 可通过网络访问的资源
此更改将扩展资源的访问权限限制为特定站点/扩展。您现在提供了一个对象列表,而不是提供文件列表,每个对象都可以将一组资源映射到一组 URL 或扩展 ID:
// Manifest V2
"web_accessible_resources": [
<files>
]
// Manifest V3
"web_accessible_resources": [{
"resources": [<resources>],
"matches": [<urls>],
"extension_ids": [<keys>],
optional "use_dynamic_url": boolean
}]
以前,Web 可访问资源列表适用于所有网站和扩展程序,这为指纹识别或无意的资源访问创造了机会。更新后的 API 允许扩展更严格地控制哪些其他站点或扩展可以访问扩展资源。有关使用信息,请参阅 Web 可访问资源文档
# 代码执行
MV3 施加了新的限制,通过平台更改和策略限制的组合来限制扩展执行未经审查的 JavaScript 的能力。
许多扩展不受此更改的影响。但是,如果您的 MV2 扩展执行远程托管脚本,则会将代码字符串注入页面,或在运行时对字符串求值,您需要在迁移到 MV3 时更新您的代码执行策略。
在 Manifest V3 中,
executeScript()
方法也移动到不同的 API。如果您在代码中的任何位置使用
executeScript()
,则需要更新该调用以使用新 API。insertCSS()
和removeCSS()
方法类似地从chrome.tabs
移动到chrome.scripting
。
# 远程托管代码
远程托管代码是指未作为可加载资源包含在扩展包中的任何代码。例如,以下两种代码都被视为远程托管代码:
- 从远程服务器拉取的 JavaScript 文件
- 在运行时传递给 eval 的代码字符串
在 MV3 中,所有扩展的逻辑都必须与扩展捆绑在一起。您不能再加载和执行远程托管的文件。有多种替代方法可用,具体取决于您的用例和远程托管的原因。两种这样的方法是:
配置驱动的特性和逻辑 -- 在这种方法中,您的扩展在运行时加载远程配置(例如 JSON 文件)并在本地缓存配置。然后,扩展程序使用此缓存配置来决定启用哪些功能。
使用远程服务外部化逻辑 -- 考虑将应用程序逻辑从扩展程序迁移到您的扩展程序可以调用的远程 Web 服务。 (本质上是一种消息传递形式。)这使您能够将代码保密并按需更改代码,同时避免重新提交到 Chrome 网上应用店的额外开销。
# 执行任意字符串
在 Manifest V2 中,可以使用 tabs.executeScript 和选项对象上的 code
属性执行任意代码字符串。Manifest V3 不允许任意代码执行。为了适应这种需求,扩展开发者可以使用 scripting.executeScript API 来注入静态文件或函数。
使用 scripting.executeScript
的静态文件注入几乎与在 Tabs API 中使用的相同。旧方法只处理一个文件,而新方法现在需要一个文件数组。
// Manifest V2
// background.js
chrome.tabs.executeScript({
file: 'content-script.js'
});
// content-script.js
alert('File test alert');
// Manifest V3
// background.js
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['content-script.js']
});
// content-script.js
alert('File test alert');
如果您需要更多动态,新的 func
属性允许您将函数作为内容脚本注入并使用 args
属性传递变量。请注意,该函数不会像位于内容脚本中那样运行;相反,它的源被发送到目标选项卡并在那里运行。
// Manifest V2
// background.js
let name = 'World!';
chrome.tabs.executeScript({
code: `alert('Hello, ${name}!')`
});
// Manifest V3
// background.js
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();
function showAlert(givenName) {
alert(`Hello, ${givenName}`);
}
let name = 'World';
chrome.scripting.executeScript({
target: {tabId: tab.id},
func: showAlert,
args: [name],
});
可以在 chrome-extensions-samples 存储库中找到本节中 Manifest V3 片段的功能版本。有关 getCurrentTab
的实现,请参阅 Tabs API 示例。
# 后台service workers
MV2 中的Background pages被 MV3 中的 Service Worker 替换:这是影响大多数扩展的基础性更改。
Service Worker 是基于事件的,并且与事件页面一样,它们不会在调用之间持续存在。这种变化通常需要一些重新设计,需要考虑许多因素:background pages迁移到 Service Workers 以获取更多详细信息。
为了帮助迁移过程,从 Chrome 87 开始,MV2 扩展程序可以使用后台服务工作者。
# 修改网络请求
有一个新的 declarativeNetRequest 用于网络请求修改,它为 webRequest AP 的大部分功能提供了替代方案。
# 什么时候可以使用阻塞 webRequest?
将向 WebRequest API的阻挡版仍然存在MV3但它的使用仅限于强制安装的扩展。请参阅 Chrome 企业政策:ExtensionSettings、ExtensionInstallForcelist。
所有其他扩展现在必须使用 declarativeNetRequest 进行网络请求修改。这会将网络请求的实际修改移动到 Chrome 浏览器中:扩展不再能够读取实际的网络请求,并且在大多数情况下不需要host permissions。
请求重定向和标头修改确实需要用户授予host permissions。
# 你如何使用 declarativeNetRequest?
您的扩展不是读取请求并以编程方式更改它,而是指定了许多规则,这些规则将一组条件映射到相应的操作。有关规则的更详细说明,请参阅 declarativeNetRequest 参考文档。
此功能允许内容拦截器和其他请求修改扩展在不需要host permissions的情况下实现它们的用例,也不需要读取实际请求。
为了帮助迁移过程,从 Chrome 84 开始,declarativeNetRequest API 可用于 MV2 扩展。
# Conditional permissions 和 declarativeNetRequest
declarativeNetRequest 的大多数用例根本不需要任何主机权限。然而,有些人这样做。
请求重定向和标头修改确实需要用户授予主机权限。
当扩展需要这些用例的主机权限时,我们建议使用“tiered(分层)”权限策略。这意味着在不使用这些权限的情况下实现扩展的核心功能;将更高级的用例置于可选权限(optional permission)之后。
这种方法允许注重隐私的用户保留这些权限,并仍然使用扩展程序的大部分功能。这意味着开发人员可以实现许多常见用例,例如内容阻止(content-blocking)功能,而无需任何主机权限。
# Sunset for deprecated APIs(弃用的APIs)
有许多 API 早已被弃用。 Manifest V3 最终取消了对这些已弃用 API 的支持。这些包括:
- chrome.extension.sendRequest()
- chrome.extension.onRequest
- chrome.extension.onRequestExternal
- chrome.extension.lastError
- chrome.extension.getURL()
- chrome.extension.getExtensionTabs()
- chrome.tabs.Tab.selected
- chrome.tabs.sendRequest()
- chrome.tabs.getSelected()
- chrome.tabs.getAllInWindow()
- chrome.tabs.onSelectionChanged
- chrome.tabs.onActiveChanged
- chrome.tabs.onHighlightChanged
以及未记录的:
- chrome.extension.sendMessage()
- chrome.extension.connect()
- chrome.extension.onConnect
- chrome.extension.onMessage
如果您的扩展使用这些已弃用的 API 中的任何一个,则在迁移到 MV3 时需要进行适当的更改。
By.一粒技术服务