Chrome扩展 - 在使用内容脚本时减少加载时间的最佳方法 [英] chrome extension - best method of reducing load time while using content scripts

查看:118
本文介绍了Chrome扩展 - 在使用内容脚本时减少加载时间的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个chrome扩展,该扩展应该查看超过12,000个值的数组,并将其与网页 p 标记进行比较,如果来自数组位于 p 标签内,它应该突出显示文本,并且当它悬停时它应该显示一些信息。因此,我认为使用内容脚本很容易,但是使用run_at:document_end使网页加载速度降低了3倍,并且使用我的扩展加载了将近10秒。显然不理想。



这是我的内容脚本代码:

  jQuery (document).ready(function($){

var $ all_p = $(p);

$ .each(arrayObj,function(key,value) {
$ all_p.highlight(key,{caseSensitive:true,className:'highlight-882312',wordsOnly:true});
});

$('。 ()函数(){

var currentKey = $(this).text();
console.log(currentKey);

//在hover上创建工具提示
Tipped.create(this,< iframe id ='cardiFrame'src ='https://mywebsite.com/word?q =+ footballers [currentKey] + '>< / iframe>,{
skin:white,
hook:'rightmiddle',
maxWidth:306,
maxHeight:365,
背景:'#eee',
});

});
});

无论如何,这对我来说太慢了,但我仍然想要构建扩展,所以我想我可以将所有 p 标签的数组发送到我的背景/弹出框,以便在背景/弹出框内循环查找关键字,然后显示匹配的关键字在弹出窗口内并将消息发回给哪些关键字匹配的内容脚本,以便它们可以突出显示。这会减少加载时间吗?这是一个很好的解决我的问题,因为额外的10秒加载时间并不理想?



我真的很感激任何建议。

编辑:arrayObj:

  var arrayObj = {

word1:'word_word1',
word2:'word_word2',
word3:'word_word3',

//额外12K行...
}

Manifest.json:

我的清单很典型,但内容脚本信息是:

 content_scripts:[
{
matches:[http:// * / *,https:// * / *],
css:[styles.css,tipped。 css],
js:[jquery.min.js,jquery-highlight1.js,spinners.min.js,tipped.js,word.js, script.js],
run_at:document_end
}
],


解决方案

更新 http ://jsfiddle.net/r4bnxemL/3/

这种新方法不那么复杂,它不会将每个单词合并成一个大的正则表达式。相反,它只是使用setTimeout技巧的asycn循环方法。

  var words = ['dolor','sit','odio' ]。 

var ele = document.getElementById('text'),
html = ele.innerHTML;


asycnIterator(单词,
函数(单词){
var reg = new RegExp('\\b'+ word +'\\ b','ig');
html = html.replace(reg,'< span class =marked>'+ word +'< / span>');
}, function(){
ele.innerHTML = html;
});

函数asycnIterator(arr,func,cb){
var i = 0;

nextCall();

function nextCall(){
func(arr [i ++]);
if(i> = arr.length){
if(cb)cb();
return;
}
setTimeout(nextCall,1);


$ / code>

首先你可以先做两件事将循环分成小块,它可能会让整个过程在更多时间内完成一些,但它不会阻塞其他所有内容,JavaScript单线程,因此使用事件循环。



例如,您可以使用setTimeout来完成此操作。 (注意需要使用回调模式,因为它会立即返回,下一行的执行将不会等待循环完成)

  var arr = [1,2,3 .... 100000]; 
var i = 0;
nonBlockingAsycnLoop(); //将在控制台中打印所有值而不会阻塞

函数nonBlockingAsycnLoop(){
console.log(arr [i ++]);
setTimeout(nonBlockingAsycnLoop,0);
}

您可以做的第二件事是快速查找。对于这个问题,你使用的原生方法越好。这只是我的做法


  1. 将所有数组元素连接成一个字符串

  2. 正则表达式

  3. 存储索引

以下函数执行该操作并调用cb

 函数returnOccurences(str,arr,cb){
var ele = null,
index = 0,
occurences = [],
regexp ='\\ b'+ arr.join('\\b | \\b')+'\\ b';

getNextWord();
函数getNextWord(){
ele = str.substr(index).match(new RegExp(regexp,'i'));
if(!ele){
cb(occurences);
return;
}
occurences.push({i:ele.index,len:ele [0] .length,word:ele [0]});
index = ele [0] .length + ele.index;
setTimeout(getNextWord,0); //使得它不被阻止


$ $
$ b $字符串匹配函数docs < a href =https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match =nofollow> MDN LINK 它如果没有被调用正则表达式的参数 g ,而不是返回包含非可枚举属性的数组,这些属性是找到的单词的索引,包含原始文本的输入。



我们可以使用索引在第一次匹配之后进一步解析字符串。

I'm building a chrome extension that is supposed to look through an array of over 12,000 values and compare it to the webpages p tags, and if a value from the array is inside the p tag it should highlight the text and when hovered it should display some information. So, easy enough I suppose using content scripts but using "run_at": "document_end" made the webpage load 3 times slower, almost 10 seconds more to load with my extension. Obviously not ideal.

This is my content script code by the way:

jQuery(document).ready(function($) {

var $all_p = $("p");

$.each(arrayObj, function(key, value) {
      $all_p.highlight(key, {caseSensitive: true, className: 'highlight-882312', wordsOnly:true });
});

$('.highlight-882312').each(function() {    

    var currentKey = $(this).text();
    console.log(currentKey);

        //Create tooltip on hover.
        Tipped.create(this, "<iframe id='cardiFrame' src='https://mywebsite.com/word?q="+footballers[currentKey]+"'></iframe>", {
            skin: "white",
            hook: 'rightmiddle',
            maxWidth: 306,
            maxHeight: 365,
            background: '#eee',
        }); 

});
});

Anyway, this was way too slow for me, but I still wanted to build the extension so I thought I could send an array of all the p tags to my background/popup so that within the background/popup it would loop through to find the keywords and then display the keywords that matched inside the popup and send a message back to the content script of which keywords matches so that they could be highlighted. Would this reduce load time? Is this a good work around for my issue since an extra 10 second load time isn't ideal at all?

I'd appreciate any advice really.

Edit: arrayObj:

var arrayObj = {

"word1": 'word_word1',
"word2": 'word_word2',
"word3": 'word_word3',

// extra 12K lines...
}

Manifest.json:

My manifest is quite typical, but content script information is:

 "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "css": ["styles.css", "tipped.css"],
      "js": ["jquery.min.js", "jquery-highlight1.js", "spinners.min.js", "tipped.js", "word.js", "script.js"],
      "run_at": "document_end"
    }
  ],

解决方案

Update http://jsfiddle.net/r4bnxemL/3/

This new approach is less complicated and it doesn't merge each word into one big regex. Instead it just uses asycn looping method using setTimeout trick.

var words = ['dolor', 'sit', 'odio'];

var ele = document.getElementById('text'),
    html = ele.innerHTML;


asycnIterator(words,
    function (word) {
        var reg = new RegExp('\\b' + word + '\\b', 'ig');
        html = html.replace(reg, '<span class="marked">' + word + '</span>');
    }, function () {
        ele.innerHTML = html;
});

function asycnIterator(arr, func, cb) {
    var i = 0;

    nextCall();

    function nextCall() {
        func(arr[i++]);
        if (i >= arr.length) {
            if (cb) cb();
            return;
        }
        setTimeout(nextCall, 1);
    }
}

First of all there are two things you could do first break the loop into tiny pieces it will probably make the whole process finish a bit in more time BUT it won't block everything else, Javascript single threaded so use event loop.

You can do it using setTimeout for example. (note will need to use callback pattern as it will return immediately, next line's execution wont wait for loop to finish)

var arr = [1,2,3....100000];
var i = 0 ;
nonBlockingAsycnLoop(); //will prints all values in console without blocking

function nonBlockingAsycnLoop() {
   console.log(arr[i++]);
   setTimeout(nonBlockingAsycnLoop,0);
}

Second thing you can do is make looking up faster. For that matter the more native method you use the better it's going to be. This is just my approach

  1. join all array elements into a string
  2. then search using them as regex
  3. store the indexes

This following function does that and invokes cb with list of all occurrences.

function returnOccurences(str, arr, cb) {
    var ele = null,
        index = 0,
        occurences = [],
        regexp = '\\b' + arr.join('\\b|\\b') + '\\b';

    getNextWord();
    function getNextWord() {
        ele = str.substr(index).match(new RegExp( regexp , 'i'));
        if (!ele) {
            cb(occurences);
            return;
        }
        occurences.push({i: ele.index, len: ele[0].length, word: ele[0]});
        index = ele[0].length + ele.index;
        setTimeout(getNextWord,0); //makes it non blocking
    }
}

String match function docs MDN LINK It if is not invoked with parameter g for regex than it return array with non enumerable properties which are index of the word found and input that contains the original text.

We can use index to parse further the string ahead after first match.

这篇关于Chrome扩展 - 在使用内容脚本时减少加载时间的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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