在 Chrome 扩展中的 CSS 注入期间闪烁 [英] Flickering during CSS injection in Chrome Extension

查看:31
本文介绍了在 Chrome 扩展中的 CSS 注入期间闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个插件,它通过注入 CSS 文件完全改变了网站的外观.它可以工作,但是在新外观出现之前的一瞬间,旧外观就在那里,因此每次加载页面时都会导致闪烁".新外观改变了背景颜色等,因此切换非常明显.(我只在我的桌面上注意到这一点,而不是在我的笔记本电脑上.我不知道为什么,但其他用户也报告了这一点,也许更快的计算机使页面的显示速度比注入 CSS 所需的速度更快?).CSS 注入需要发生,因此注入的 CSS 是最重要的(如最后).

I have an addon that changes the look of a website completely by injecting a CSS file. It works but for a split second before the new look appear the old look is there, thus causing the "flicker" each time a page loads. The new look changes the background color etc. so the switch is very noticeable. (I only notice this on my desktop, not on my laptop. I don't know why but other users report it as well, perhaps the faster computer makes the page show faster than it takes to get the CSS injected?). The CSS injection need to happen so the injected CSS is the most important (as in last).

我尝试过的导致此问题的方法(之后的代码):

What I've tried that cause this issue (code afterwards):

  1. 清单:确保 css 位于 web_accessible_resources
  2. Manifest:直接在content_scripts
  3. 中进行注入
  4. 清单:通过从 content_scripts
  5. 运行的 javascrip 来实现
  6. 清单:确保所有内容脚本都在 document_start
  7. 运行
  8. 清单:尝试从后台页面上运行的脚本运行注入
  9. JS 注入时间:为 DOMSubtreeModified 添加了事件监听器
  10. JS 注入时间:为 chrome.webNavigation.onCommitted 添加了事件监听器
  11. JS 注入时机:等待 document.head/document.body
  12. JS注入方法:appendChild
  13. JS注入方法:chrome.tabs.executeScript()
  14. JS 注入代码:链接元素链接到扩展中的 css 文件
  15. JS注入代码:直接执行javascript
  1. Manifest: Made sure css is in web_accessible_resources
  2. Manifest: Doing the injection directly in content_scripts
  3. Manifest: Doing it through a javascrip run from the content_scripts
  4. Manifest: Making sure all content-scripts are run at document_start
  5. Manifest: Tried running the injection from a script running on the background page
  6. JS Injection Timing: Added eventlistener for DOMSubtreeModified
  7. JS injection Timing: Added eventlistener for chrome.webNavigation.onCommitted
  8. JS Injection Timing: Waiting for document.head / document.body
  9. JS Injection Method: appendChild
  10. JS Injection Method: chrome.tabs.executeScript()
  11. JS Injection Code: Link element linking to css file in extension
  12. JS Injection Code: Directly executed javascript

代码示例:

清单:

{
  "manifest_version": 2,
  "name": "foo",
  "short_name": "bar",
  "description": "baz",
  "options_page": "options.html",
  "version": "2.1.1",
  "homepage_url": "http://google.com/",
  "permissions": ["storage", "*://google.com/*", "webNavigation", "tabs", "activeTab"],
  "browser_action": {
    "default_icon": "icon16.png",
    "default_title": "title",
    "default_popup": "popup.html"
  },
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "content_scripts": [
    {
      "matches": ["*://google.com/*"],
      "js": ["carbonicEditionScript.js"],
      "all_frames": true,
      "run_at": "document_start"
    }
  ],
  "background": {
    "page": "popup.html"
  },
  "web_accessible_resources": ["carbonicEditionStyle.css"]
}

carbonicEditionScript.js

carbonicEditionScript.js

document.addEventListener('DOMSubtreeModified', injectStyle, false);
function injectStyle(){
    document.removeEventListener('DOMSubtreeModified', injectStyle, false);
    var style = document.createElement('style');
    style.setAttribute("id", "CarbonicEditionStyle");
    style.setAttribute("class", "CarbonicEditionStyle");
    style.setAttribute("type", "text/css");
    style.appendChild(document.createTextNode(css));
    document.getElementsByTagName("html")[0].appendChild(style);
}

carbonicEditionScript替代.js

carbonicEditionScriptAlternative.js

document.addEventListener('DOMSubtreeModified', injectCSS, false);
function injectCSS(){
var style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = chrome.extension.getURL('carbonicEditionStyle.css');
if(document.head){
  document.removeEventListener('DOMSubtreeModified', injectCSS, false);
  (document.head||document.documentElement).appendChild(style);
}}

背景.js

chrome.webNavigation.onCommitted.addListener(function(o) {
  chrome.tabs.executeScript(o.tabId, {
        code: "var css = 'body{background-color: green !important;}'; var style = document.createElement('style'); style.setAttribute('id', 'CarbonicEditionStyle'); style.setAttribute('class', 'CarbonicEditionStyle'); style.setAttribute('type', 'text/css'); style.appendChild(document.createTextNode(css)); document.getElementsByTagName('html')[0].appendChild(style);"
  });
}, {
  url: [{hostContains: 'google.com'}]
});

有人知道这是怎么回事吗?以上所有解决方案都有效,但闪烁仍在发生.

Does anyone know what's going on? All the solutions above work but the flicker is still happening.

推荐答案

Stylish-chrome 扩展只需使用 webNavigation.onCommited修复闪烁/code> 事件,因此您应该已经能够解决问题.但是,您遇到的问题可能是由于您提到了 web_accessible_resources 后从扩展包中异步读取 css 代码引起的.在这种情况下,将其缓存在 chrome.storage.localsessionStoragelocalStorage 中.或者考虑在您的内容脚本中嵌入 CSS.

Stylish-chrome extension fixed the flicker just by using webNavigation.onCommited event so you should've been already able to fix the issue. However, the problem you experience might be caused by asynchronous reading of the css code from the extension package since you mention web_accessible_resources. In this case cache it in chrome.storage.local or sessionStorage or localStorage. Or consider embedding the CSS inside your content script.

关于您发布的代码的一些 [可能是多余的] 注释:

Some [probably redundant] notes on the code you've posted:

  1. 不要使用 DOMSubtreeModified 事件,因为它 a) 实际上并不需要 -(您甚至可以在解析网页之前注入元素)并且 b) 它是古老的/不推荐使用的/缓慢的/坏的.

  1. Don't use DOMSubtreeModified event because it's a) not actually needed - (you can inject elements even before the webpage is parsed) and b) it's ancient/deprecated/slow/bad.

所以整个内容脚本可能是:

So the entire content script might be:

var style = document.createElement('style');
style.id = "CarbonicEditionStyle";
style.className = "CarbonicEditionStyle";
style.type = "text/css";
style.textContent = "body{background-color: green !important;}";
(document.body || document.head || document.documentElement).appendChild(style);

  • executeScript 中使用 runAt: "document_start",因为默认情况下它是 document_idle,通常仅在加载 DOM 时发生并且解析:

  • Use runAt: "document_start" in executeScript as by default it's document_idle which occurs usually only when the DOM is loaded and parsed:

    chrome.tabs.executeScript(o.tabId, {runAt: "document_start", code: "......"});
    

  • 考虑通过 insertCSS 直接注入 CSS(并不是真正需要消除闪烁,它不会允许您禁用注入的样式,但为了完整性):

  • Consider injecting the CSS directly via insertCSS (not really needed to eliminate the flicker and it won't allow you to disable the injected style but for the sake of completeness):

    chrome.tabs.insertCSS(o.tabId, {runAt: "document_start", code: "body{background....."});
    

  • "matches": ["*://google.com/*"], 不会匹配默认使用的 www.google.com 所以它应该是 "匹配": ["*://*.google.com/*"],
  • google.com 不是唯一的域名,还有很多国际域名.
  • "matches": ["*://google.com/*"], won't match www.google.com which is used by default so it should be "matches": ["*://*.google.com/*"],
  • google.com isn't the only domain, there are also lots of international domains.
  • 这篇关于在 Chrome 扩展中的 CSS 注入期间闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆