4

I'm trying to build a chrome extension using React. I've ejected create-react-app and have made necessary changes to emit content.chunk.js which is included in manifest.json as below

{
  "manifest_version": 2,
  "version": "0.0.1",
  "name": "My extension",
  "description": "Some description",
  "permissions": [],
  "browser_action": {
    "default_title": "My extension",
    "default_popup": "index.html"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "css": ["/static/css/content.chunk.css"],
    "js": ["/static/js/content.chunk.js"]
  }]
}

my content.js

import React from 'react';
import ReactDOM from 'react-dom';
import Main from 'extensionContainers/Main';

alert('bazooka!');
const app = document.createElement('div');
app.id = "extension-root";
document.body.appendChild(app);

ReactDOM.render(<Main />, app);

after build, when I load my extension this doesn't do anything. However, when I edit the contents of content.chunk.js generated by webpack to alert("something"), the extension works fine and shows alert on every URL.

Why is my react code isn't doing anything? There are no error logs.

2
  • The usual reason is that your config produces a module script that only registers its exported functions but never actually invokes them. I don't know react/webpack so I don't know what exactly you need to change in your config, but hopefully there are existing solutions. Commented Jul 30, 2019 at 12:02
  • @wOxxOm I don't think that's happening. If I add the generated content.chunk.js in an HTML page as a script tag, it works as expected. However, through content script I don't see anything happening. Commented Jul 31, 2019 at 10:00

2 Answers 2

9

Answering my own question if anyone else stumbles upon this.

So, I realized that the Webpack config from [email protected] ejection had code split configurations enabled. Which was splitting react library code from my code making it inexecutable.

Here are the settings I changed in the webpack config to get it working. (note that this is only advisable to do when developing chrome extension)

In webpack.config.js remove the configuration for splitChunks under optimization node, and set runtimeChunk to false.

...
optimization: {
  .
  .
  // remove spitChunks config
  splitChunks: {
     chunks: 'all',
     name: false,
  },
  runtimeChunk: true, // set this to false
}
...

the generated bundle will now be named as content.js (considering content as the entry point) link this content.js in your manifest.json under content_scripts and you're good to go.

Sign up to request clarification or add additional context in comments.

2 Comments

@Vishal which folder should I place content.js?
@S.J.Lin content.js will be bundled in your build folder at /static/js/content.js just reference it in your manifest.json and you are good to go.
0

Now, we don't need to edit the Webpack.config.js anymore instead, we can configure our own using

  1. customize-cra,
  2. react-app-rewired,
  3. copy-webpack-plugin,
  4. react-app-rewire-multiple-entry

1 and 2 will overwrite the webpack default configuration, 3 to copy all of our assets files, and 4 to add multiple files

Just install it:

npm -i customize-cra react-app-rewired copy-webpack-plugin react-app-rewire-multiple-entry --save-dev

Yarn

yarn add customize-cra react-app-rewired copy-webpack-plugin react-app-rewire-multiple-entry --dev

Configuration

create a config-overrides.js file in your root directory / and put use this code

const {
   override,
   overrideDevServer,
   addWebpackPlugin
} = require("customize-cra");
const CopyPlugin = require('copy-webpack-plugin');

const multipleEntry = require('react-app-rewire-multiple-entry')([
   {
      // points to the popup entry point
      entry: 'src/popup/index.js',
      template: 'public/popup.html',
      outPath: '/popup.html'
   },
   {
      // points to the options page entry point
      entry: 'src/options/index.js',
      template: 'public/index.html',
      outPath: '/index.html'
   }
]);

const devServerConfig = () => config => {
   return {
      ...config,
      // webpackDevService doesn't write the files to desk
      // so we need to tell it to do so so we can load the
      // extension with chrome
      writeToDisk: true
   }
}

const copyPlugin = new CopyPlugin({
   patterns: [
      // copy assets
      { from: 'public', to: '' },
      { from: 'src/background.js', to: '' }
   ]
})

module.exports = {
   webpack: override(
      addWebpackPlugin(
         copyPlugin
      ),
      multipleEntry.addMultiEntry,
   ),
   devServer: overrideDevServer(
      devServerConfig()
   ),

};

go ahead and create two folders in src/, options/, and popup containing the index.js and app.js files, mean copy all the files from src/ when you install React and past it to these both folders. for the background.js file you should put this on the src/:

/
   src/
      background.js
      index.js // empty file only
      options
         index.js
         app.js
         app.css
      popup
         index.js
         app.js
         app.css
 

Also overide the script in the package.json file to:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  }

now you don't need to reload the extension after changes, it will automatically trigger when you save your code.

another file is to create is .env in the root directory and past this:

INLINE_RUNTIME_CHUNK=false

Now run the command yarn start or npm start, load the extension you should be good to go!

Resource to learn

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.