user
user

Reputation: 103

Loading libraries for use in a content script

I created a Firefox extension that works, for the most part. I am having a hard time importing jQuery. I have downloaded it locally. I am getting no errors. So, sometimes the extension will work and jQuery will load. Sometimes it won't. Other times I have to reload the page 5 or 6 times to get it to work.

I am not a JavaScript developer and this is my first time attempting an extension. I have Googled and tried a bunch of things with no luck.

Below is my manifest.json

"web_accessible_resources" : ["/jquery-3.2.1.min.js","/jquery.csv.min.js","/ui.js"],
  "icons": {
    "128": "icon_128px.png",
    "48": "icon_48px.png"
  },
 "browser_action": {
    "default_icon": "icon_48px.png"
  },
"content_scripts": [
  {
    "matches": ["https://*****.com/*"],
    "js": ["content.js"],
    "run_at": "document_end"
  }
],
"permissions":[
    "activeTab"
    ],
"homepage_url": "https://*****.com"

}

content.js

function injectJs(link) {
    var scr = document.createElement("script");
    scr.type="text/javascript";
    scr.src=link;
    (document.head || document.body || document.documentElement).appendChild(scr);
}

injectJs(chrome.extension.getURL("/jquery-3.2.1.min.js"));
injectJs(chrome.extension.getURL("/jquery.csv.min.js"));
injectJs(chrome.extension.getURL("/ui.js"));

Upvotes: 2

Views: 2202

Answers (1)

Makyen
Makyen

Reputation: 33306

Normally, you would load jQuery by including it within the js key in your manifest.json content_scripts entry. For example:

"content_scripts": [
  {
    "matches": ["https://example.com/*"],
    "js": ["jquery-3.2.1.min.js", "jquery.csv.min.js", "ui.js", "content.js"]
  }
]

Scripts are loaded in the order listed. So, you need to list the libraries which depend on others after the ones they depend upon (e.g. "jquery-3.2.1.min.js" before "jquery.csv.min.js").

What you were doing

The way that you were doing it inserted the scripts into the page context using <script> tags. Such tags are loaded asynchronously. Thus, there was no guarantee that your scripts which depended on jQuery were actually loaded after jQuery. For what you are doing, you don't want to be loading the scripts into the page context, which is separate from the content script context where your content scripts normally run. If you want more information as to how you can do that successfully, you can see my answer to How to sequentially insert scripts into the page context using tags, which has fully functional code to insert multiple dependent libraries into the page context.

Use .tabs.executeScript() to dynamically load scripts when they are not used 100% of the time

However, if you are loading your content script into a large number of pages (e.g. matches being "<all_urls>", *://*/*, etc.), then you should use a manifest.json content_scripts entry to load only the bare minimum needed to show the initial portion of your user interface (i.e. just the static portion seen prior to the user interacting). Only once the user begins interacting with your user interface should you then send a message, using .runtime.sendMessage(), to your background script, received using .runtime.onMessage(), to instruct your background script to inject the rest of the files needed for your complete user interface. You background script would then use .tabs.executeScript() to load the additional scripts you need and, perhaps, tabs.insertCSS() to inject any additional CSS which you may need.

The point of doing the above is to minimize the impact your extension has on the user/browser during the time which the user is not actively using your extension, which is most of the time under most conditions.

Upvotes: 2

Related Questions