迁移到清单 V3
让你朝着正确的方向前进。
发表于 •更新日期
本指南为开发人员提供了开始将扩展从 Manifest V2 迁移到 Manifest V3 (Manifest V3) 所需的信息。一些扩展只需要很少的改动就可以使其符合 Manifest V3,而另一些则需要在某种程度上进行重新设计。有 Manifest V2 经验的开发人员以及正在创建新的 Manifest V3 扩展的开发人员也可能会发现这很有帮助。有关快速参考指南,请参阅迁移清单。
Manifest V3 提供了许多反映我们平台愿景目标的改进。
#功能摘要
使用 Manifest V3 的扩展有许多新特性和功能更改:
- 服务工作者替换背景页面。
- 现在使用新的declarativeNetRequest API处理网络请求修改。
- 不再允许远程托管代码;扩展只能执行包含在其包中的 JavaScript。
- 许多方法都添加了Promise支持,但仍支持回调作为替代方案。(我们最终将支持所有适当方法的承诺。)
- Manifest V3 中还引入了许多其他相对较小的功能更改。
有关这些更改的更完整描述,请参阅Manifest V3 概述。
#更新 manifest.json 文件
要使用 Manifest V3 的功能,您需要先更新您的清单文件。当然,您会将清单版本更改为“3”,但清单文件中还有许多其他内容需要更改:主机权限、内容安全策略、操作声明和 Web 可访问资源。
#清单版本
更改 manifest_version 元素的值是升级扩展的关键。这决定了您使用的是 Manifest V2 还是 Manifest V3 功能集:
// Manifest V2
"manifest_version": 2
// Manifest V3
"manifest_version": 3
#主机权限
在 Manifest V3 中,您需要将主机权限与其他权限分开指定:
// 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 网上应用店审核流程会将它们视为主机权限请求。
#内容安全政策
扩展的内容安全策略(CSP) 在 Manifest V2 中指定为字符串;在 Manifest V3 中,它是一个对象,其成员代表替代 CSP 上下文:
// Manifest V2
"content_security_policy": "..."
// Manifest V3
"content_security_policy": {
"extension_pages": "...",
"sandbox": "..."
}
extension_pages
:此政策涵盖您的扩展程序中的页面,包括 html 文件和服务人员。
这些页面类型由chrome-extension://
协议提供。例如,您的扩展程序中的一个页面是chrome-extension://EXTENSION_ID/foo.html
.
sandbox
:此政策涵盖您的扩展程序使用的任何沙盒扩展程序页面。
此外,Manifest V3 不允许extension_pages
Manifest V2 中允许的某些 CSP 修改。,script-src,
object-src
和worker-src
指令只能具有以下值:
self
none
- 任何 localhost 源、(
http://localhost
、http://127.0.0.1
或这些域上的任何端口)
CSP 修改sandbox
没有这样的新限制。
#动作 API 统一
在 Manifest V2 中,有两种不同的 API 来实现操作:browser_action
和page_action
. 这些 API 在引入时扮演了不同的角色,但随着时间的推移它们变得多余,因此在 Manifest V3 中,我们将它们统一为单个action
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": [
RESOURCE_PATHS
]
// Manifest V3
"web_accessible_resources": [{
"resources": [RESOURCE_PATHS],
"matches": [MATCH_PATTERNS],
"extension_ids": [EXTENSION_IDS],
optional "use_dynamic_url": boolean
}]
替换以下内容:
RESOURCE_PATHS
: 字符串列表,每个字符串都包含从扩展的根目录到给定资源的相对路径。MATCH_PATTERNS
: 一个字符串列表,每个字符串都包含一个 [match pattern][doc-match-pattern] 指定哪些站点可以访问这组资源。EXTENSION_IDS
:字符串列表,每个字符串都包含给定扩展的 ID。
以前,Web 可访问资源列表适用于所有网站和扩展程序,这为指纹识别或无意资源访问创造了机会。更新后的 API 让扩展更严格地控制其他站点或扩展可以访问扩展资源的内容。有关使用信息,请参阅Web 可访问资源文档。
#代码执行
Manifest V3 施加了新的限制,通过平台更改和策略限制的组合来限制扩展执行未经审查的 JavaScript 的能力。
许多扩展不受此更改的影响。但是,如果您的 Manifest V2 扩展程序执行远程托管脚本、将代码字符串注入页面或在运行时评估字符串,则在迁移到 Manifest V3 时您需要更新代码执行策略。
使用 Manifest V3,该executeScript()
方法也移至不同的 API。
- 清单 V2: chrome.tabs.executeScript()
- 清单 V3: chrome.scripting.executeScript()。
如果您在代码中的任何位置使用 executeScript(),则需要更新该调用以使用新 API。和方法类似地从 chrome.tabs 移动到 chrome.scripting insertCSS()
。removeCSS()
#远程托管代码
远程托管代码是指任何未包含在扩展程序包中的代码作为可加载资源。例如,以下两个都被视为远程托管代码:
- 从远程服务器拉取的 JavaScript 文件
- 在运行时传递给 eval 的代码字符串
In Manifest V3, all of your extension's logic must be bundled with the extension. You can no longer load and execute a remotely hosted file. A number of alternative approaches are available, depending on your use case and the reason for remote hosting. Two such approaches are:
Configuration-driven features and logic—In this approach, your extension loads a remote configuration (for example a JSON file) at runtime and caches the configuration locally. The extension then uses this cached configuration to decide which features to enable.
Externalize logic with a remote service—Consider migrating application logic from the extension to a remote web service that your extension can call. (Essentially a form of message passing.) This provides you the ability to keep code private and change the code on demand while avoiding the extra overhead of resubmitting to the Chrome Web Store.
# Executing arbitrary strings
In Manifest V2 it was possible to execute an arbitrary string of code using tabs.executeScript
and the code
property on the options object. Manifest V3 does not allow arbitrary code execution. In order to adapt to this requirement, extension developers can either use the scripting.executeScript
API to inject a static file or a function.
Static file injection with scripting.executeScript
is almost identical to it used to work in Tabs API. While the old method only took a single file, the new method now takes an array of files.
// 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');
If you need more dynamism, the new func
property allows you to inject a function as a content script and pass variables using the args
property. Note that the function is not run as if it was located within the content script; rather, its source is sent to the target tab and it is run there.
// 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],
});
A functional version of the Manifest V3 snippets in this section can be found in the chrome-extensions-samples repository. See the Tabs API examples for an implementation of getCurrentTab
.
# Background service workers
Background pages in Manifest V2 are replaced by service workers in Manifest V3: this is a foundational change that affects most extensions.
Service workers are event based, and like event pages they do not persist between invocations. This change generally requires some redesign, with a number of factors to consider: see Migrating from Background Pages to Service Workers for additional details.
In order to aid with the migration process, Manifest V2 extensions can use background service workers as of Chrome 87.
# Modifying network requests
There is a new declarativeNetRequest for network request modification, which provides an alternative for much of the webRequest AP's functionality.
# When can you use blocking webRequest?
The blocking version of the webRequest API still exists in Manifest V3 but its use is restricted to force-installed extensions only. See Chrome Enterprise policies: ExtensionSettings, ExtensionInstallForcelist.
All other extensions must now use declarativeNetRequest for network request modification. This moves the actual modification of the network request into the Chrome browser: the extension no longer can read the actual network request, and in most cases needs no host permissions.
Request redirects and header modifications do require the user to grant host permissions.
# How do you use declarativeNetRequest?
Instead of reading the request and programmatically altering it, your extension specifies a number of rules, which map a set of conditions to corresponding actions. See the declarativeNetRequest reference documentation for a more detailed description of rules.
This feature allows content blockers and other request-modifying extensions to implement their use cases without requiring host permissions, and without needing to read the actual requests.
In order to aid with the migration process, the declarativeNetRequest API is available for use in Manifest V2 extensions as of Chrome 84.
# Conditional permissions and declarativeNetRequest
Most use cases for declarativeNetRequest don't require any host permissions at all. However, some do.
Request redirects and header modifications do require the user to grant host permissions.
When extensions require host permissions for these use cases, we recommend a "tiered" permissions strategy. This means implementing the extension's core functionality without using these permissions; putting the more advanced use cases behind an optional permission.
This approach allows privacy-conscious users to withhold those permissions and still use much of the extension's functionality. This means that developers can implement many common use cases, such as content-blocking functionality, without requiring any host permissions.
# Sunset for deprecated APIs
There are a number of APIs that have long been deprecated. Manifest V3 finally removes support for these deprecated APIs. These include:
- 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,则在迁移到 Manifest V3 时需要进行适当的更改。
最近更新时间: 改进文章