浏览器扩展:如何将 javascript 代码注入页面而不会发生冲突?

Posted

技术标签:

【中文标题】浏览器扩展:如何将 javascript 代码注入页面而不会发生冲突?【英文标题】:Browser extensions: how can injecting javascript code into a page work without conflicts? 【发布时间】:2012-07-15 14:49:26 【问题描述】:

我已经开始开发浏览器扩展。我注意到一个常见的概念是扩展可以将 JS 代码注入到当前浏览器选项卡中。

我有点困惑,为什么这不会经常引起问题。

我的意思是,如果我将版本 x 的 JQuery(通过我的浏览器扩展)注入到已经包含版本 y 的 JQuery 的页面中,事情怎么可能仍然有效? $()函数不会有冲突吗?

事情怎么可能这么顺利?开发人员是否应该采用任何特定技术来确保不会发生此类冲突,或者浏览器会处理所有事情?

【问题讨论】:

【参考方案1】:

虽然noConflict() 可能大部分时间都适用于 jQuery,但它对于扩展来说仍然是个坏主意,并且不适用于大多数其他库或实用程序。

明智的做法是根本不注入代码(有一个例外1)。该扩展可以包含您需要的任何库,这样做有很多好处:

    不可能与页面的javascript发生冲突。

    不依赖页面的JS,更改不另行通知,您的扩展将不那么频繁地崩溃。

    当您注入一个库时,它必须从某个外部服务器获取。这会减慢您的扩展程序并使其容易受到您无法控制的崩溃的影响。

    当您在扩展中包含该库时,它是:(a) 始终存在,(b) 始终是已知良好的版本,以及 (c) 几乎立即从本地计算机加载,而不是从某个遥远的服务器加载。

    即使页面的 javascript 被禁用,您的扩展程序也可以运行。

    您的扩展程序可以同时利用库和扩展程序 API。

使用扩展很容易合并像 jQuery 这样的库。例如,使用 Chrome:

    将库文件复制到您的扩展文件夹。

    将库添加到manifest.json 文件。

    包含 jQuery 的简单清单可以是:

    
        "content_scripts": [ 
            "exclude_globs":    [  ],
            "include_globs":    [ "*" ],
            "js":               [ "jquery.min.js", "myJS.js" ],
            "matches":          [ "http://***.com/*"
                                ]
         ],
        "description":  "Hello world with jQuery",
        "name":         "Hello world with jQuery",
        "version":      "1"
    
    

Firefox 和其他浏览器的机制类似。


1 一个例外?对于扩展,当且仅当满足所有这些条件时才注入代码:

    该扩展程序仅适用于一个特定站点。 您绝对必须使用目标页面创建的某些对象/函数。 在扩展程序中轻松复制功能太复杂了。 您不介意为网站设计的每一个细微变化都重写或调整您的扩展程序。 您可以确保所有用户都启用了网站的 javascript。 您可以确定为您的图书馆提供服务的网站运行速度相当快,而且不会经常离线。

【讨论】:

我认为 content_scripts 总是被注入 - 看看 Chrome 文档:code.google.com/chrome/extensions/content_scripts.html,在第一段“Manifest”。 尽管该页面误用了“注入”一词,但它们并不像其他任何人使用该术语(在目标页面范围内运行的代码)那样表示“注入”。事实上,Chrome 文档在其他地方描述了实际行为,包括稍后在同一页面上。见Execution environment。 ... ...“注入”的常见和正确用法是当您的脚本或扩展创建<script> 节点(或unsafeWindow 的某些用法)时。 你说得对——在那个段落中,他们甚至说“例如,内容脚本可以包含 JQuery v1,页面可以包含 JQuery v2,它们不会相互冲突。” - 正是我所要求的。谢谢。 基本上我对他们使用“注入”一词的方式感到困惑 是的,该页面的使用令人困惑且不标准。这仅适用于 Chrome 吗?【参考方案2】:

jQuery 有一个 noConflict() 函数,可用于将 jQuery 与使用 $ 命名空间的其他任何东西(例如 jQuery 的不同实例)隔离开来。

避免前向命名空间污染的更通用方法是考虑在闭包中执行 JavaScript。

(function () 
    // Your Code Here
)();

这将阻止闭包范围内的任何内容在您自己的代码之外可用。

【讨论】:

【参考方案3】:

此问题的常见解决方案是使用 jQuery.noConflict() 将您的 jQuery 别名为不同的变量,确保它不会与页面的 $ 冲突。

【讨论】:

另一个很多注入使用的好习惯是检查并查看 jQuery 在注入之前是否已经存在。如果做不到这一点,是的,noConflict 有效。 (每当我必须做那种事情时,我通常使用$$,但如果你想要超级安全,你可能想使用YourPlugin$。这听起来可能很痛苦,打字,但是如果你使用模块模式(你可能应该使用它)你只需要在每个文件中输入一次。

以上是关于浏览器扩展:如何将 javascript 代码注入页面而不会发生冲突?的主要内容,如果未能解决你的问题,请参考以下文章

专业技术揭秘安卓浏览器如何注入javascript脚本

javascript 当您单击浏览器操作图标时,只需极少的Chrome扩展即可将JS文件注入给定页面。然后脚本插入一个n

javascript 当您单击浏览器操作图标时,只需极少的Chrome扩展即可将JS文件注入给定页面。然后脚本插入一个n

Selenium:如何在加载/执行页面的任何其他脚本之前将 Javascript 注入/执行到页面中?

在Chrome扩展程序中,您可以强制在一切之前注入一些javascript吗?

译Cromos – 下载并注入代码到谷歌 Chrome 浏览器扩展中