Search code examples
javascriptgoogle-chrome-extensionwebpackdllreferenceplugin

Chrome Extension: Resource not available even adding it in web_accessible_resources


I'm developing a Chrome Extension using React/Redux. For that, I'm using Webpack and now I'm migrating some resources to a separated file using the WebPack DLLReference plugin to optimize the build process.

Then I need to load the generated dll/dll.vendor.js into both my popup and injected content. For the popup it works fine, but it's not working for the injected content.

I've added it to the manifest

"web_accessible_resources": [
    "dll/dll.vendor.js"
],

The file is there, I can even access it using the path: chrome-extension:///dll/dll.vendor.js

But it's not present in the injected content, as I can see opening the Developer Tools -> Sources Which, of course, generate errors of missing objects later on.

Everything was working fine before migrating to DLLReferencePlugin.

My DLL webpack config file: https://pastebin.com/z9RjRUqm

My Content webpack config file: https://pastebin.com/0Niw2Fqm

The error I'm receiving

The line that triggers the error:

module.exports = vendor;

If I check the popup, it has the same line, if I set a breakpoint there and watch the variable it's defined, the problem only happens in the content.

The code to inject my Extension toolbar into the page: content/src/index.js

import React from 'react';
import {render} from 'react-dom';
import {Provider} from 'react-redux';
import {Store} from 'react-chrome-redux';

const anchor = document.createElement('div');
anchor.id = 'my-anchor';
document.body.appendChild(anchor)

const vendorUrl = chrome.runtime.getURL("dll/dll.vendor.js")

render(
  <Provider store={proxyStore}>
      <div>
          <script src={vendorUrl}></script>
          <link id='semantic-ui' rel='stylesheet' type='text/css'
                href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css' media='all' />
          <AppContainer>
              <ToolbarContent />
          </AppContainer>
      </div>
  </Provider>
  , document.getElementById('my-anchor'));

Any idea what else could be the cause for this issue? Any better way to debug why the resource is not being available to the content environment?

UPDATE

Based on my last findings it happens because the code depending on dll.vendor is executed before the injection happens on the page, but I don't know how can I avoid this to happen.


Solution

  • There's one thing missing from your understanding of content scripts, the Isolated World paradigm:

    Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.

    How does this relate? Well, if you're adding a <script> element to the page's DOM, the code will execute in the page's context - not your content script's context. This technique is called "page level" or "injected" scripts.

    However, that's not what you want. You want it in the content script context, so you can use the libraries. Then you have options:

    1. If you always need the same script configuration, adding scripts as an array in the manifest is probably best. Load order matters:

      "js" : [ "library.js", "actual_code.js" ]
      
    2. If you for some reason need to load code dynamically at runtime from an existing content script, you can request the background page to inject it programmatically for you. If you're already doing it, just chain the calls in the right order.

    3. Not a technically ideal solution, but you could XHR your internal resource and then eval() from the content script context.