Migrating Manifest Version 3 - Webpack (React and Redux) Problem

1,237 views
Skip to first unread message

ULViDO

unread,
Jun 8, 2020, 5:12:46 AM6/8/20
to Chromium Extensions
Hi everyone. I maintain an extension for me and my friends to make our job easier. 

my current status:
- I keep users todolist and notes chrome.storage.sync
- I keep users options chrome.storage.local
- I use redux to keep the state (init from storage.local)
- No sending and receiving data from remote. even fonts are inside the package.

I am not a programmer and very new to this service worker thing. It is said, service worker executes when started and dies when finished.

Q1: Will my redux store be deleted on every run?

Now in MV3 it is suggested to keep state in chrome.storage.sync but it is limited to 100kb.

Secondly I use webpack to bundle react, redux, webext-redux etc... and webpack bundled js needs 'unsafe-eval' in "content_security_policy". 
my current CSP in MV2 is "script-src 'self' 'unsafe-eval'; object-src 'self'"

Q2: What is the equivalent of this policy in MV3? in MV3 "content_security_policy" will be an object but how will we write this? Is there an example?

Thank you.

Ben Dehghan

unread,
Feb 11, 2021, 4:03:28 PM2/11/21
to Chromium Extensions, ulv...@gmail.com
Hey everyone,

We really need an answer to the webpack question. Angular uses webpack and that should be allowed given that it's a Google backed system. How can I package my angular extension so it gets past MV3 restrictions??

Thanks,
Ben

PhistucK

unread,
Feb 12, 2021, 5:16:17 PM2/12/21
to Ben Dehghan, Chromium Extensions, ulv...@gmail.com
I am surprised Webpack mandates eval(). Are you sure about that?

I believe service workers also have access to IndexedDB, which is not limited to 100KB, which can probably be used to store/load the Redux state. Does that help?

PhistucK


--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/c4869558-e581-4560-8646-f9d08c094752n%40chromium.org.

Marcus Carey

unread,
Feb 13, 2021, 10:33:54 PM2/13/21
to Chromium Extensions, ulv...@gmail.com
I'm using redux-webext and it works fine. The store (is not) deleted after each run.

I did have an issue trying to use webext-redux with MV3.

ULViDO

unread,
Feb 14, 2021, 3:41:58 AM2/14/21
to Chromium Extensions
after chrome 88 release in january I'd be able to start development and testing react redux development in mv3. here are the results:

  •     manifest.json

besides some other big changes I think these are the most important ones. here is a part of my manifest.json:

...
"background": {
   "service_worker": "sw.js"
},
"content_security_policy": {
   "extension_pages": "script-src 'self'; object-src 'self'"
},
...

  •     service-worker

for me sw.js only exists. because I prefer the background signalling work done by a redux middleware.

my sw.js file:

//sw.js
"use strict";

self.addEventListener("install", e => {
  console.log("Service Worker Installed.");
});

self.addEventListener("activate", e => {
  console.log("Service Worker Activated.");
});

and you need to register your service worker in your popup.js:

// somewhere in popup.js
...
// register service worker
if ("serviceWorker" in navigator) {
  console.log("Service Worker Supported.");
  window.addEventListener("load", () => {
  navigator.serviceWorker.register("sw.js")
    .then(reg => console.log("Service Registered.", reg))
    .catch(err => console.error("ERROR!", err));
});
}

  •     webpack --mode=production

you need to compile only production even you are testing. otherwise you will face unsafe eval error.

here is js/jsx configuration in my webpack.config.js

{ // JS - BABEL LOADER
   test: /\.(js|jsx|mjs)$/i,
   exclude: /(node_modules|bower_components)/,
   use: [
     {
     loader: "babel-loader",
     options: {
       presets: ["@babel/preset-env", "@babel/preset-react"],
       plugins: ["@babel/plugin-transform-runtime"], // for async functions (not dev, install this one as prod dependency)
       }
     }
   ]
},

  • redux persistence
unfortunately I couln't be able to persist redux store between tabs. so I wanted unlimited storage permission in manifest.json

//manifest.json
...
"permissions": [
  ...
   "unlimitedStorage",
],
...

STORE DATA: make a "storage.js" middleware for redux and pass {storage: true} meta with it. for example:

// actions.js
const setThemeColor = color => ({
   type: SET_THEME_COLOR,
   payload: {
   data: color, // theme_color : action.payload.data
   meta: {
     storage: true,
     type: "string", // for storage middleware
     key: "theme_color"
     }
   }
});

// storage.js middleware
...
const read = key => new Promise((resolve, reject) => {
   if (chrome.runtime.lastError) {
   reject("chrome runtime error read[key] @storage middleware");
   } else {
   chrome.storage.local.get(key, obj => {
   resolve(obj);
   });
   }
});

const storage = store => next => action => {
// check if storage meta in action
if (action.payload && action.payload.meta && action.payload.meta.storage) {
 
let { type, key } = action.payload.meta;

   switch (type) {

   case "string":
   read(key) // get saved value
   .then(val => { // if key not exists
   if (val[key] === undefined) val[key] = "";
   return val;
   })
   // begin storage process
   .then(val => {
     chrome.storage.local.set({
     ...val, // don't change others
       [key]: action.payload.data 
     }, () => {
   return next(action); // save completed! continue next middleware.
   });
})
.catch(err => {
   console.error(err, "Some error occured @storage middleware.");
});
return;

RETRIVE DATA: make an "initLocalStorage.js" and import it in popup.js.

// initLocalStorage.js (logic may change according your data storing perefer)
"use strict";

// REDUX
import store from "../redux/store.js";

chrome.storage.local.get(null, all => {
    store.dispatch({ type: `INIT_STORAGE`, payload: { data: all } });
});


and catch your "INIT_STORAGE" action in your reducers.
for every each reducer have an "INIT_STORAGE" action by default.
reduce your initial state and check if that key blongs to that reducer and place it if so.

//themeReducer.js
...
export default (state = initialState, { type, payload }) => {
   let newState = { ...state };
   switch (type) {

     case INIT_STORAGE:
       newState = Object.keys(newState).reduce((acc, cur) => {
       if (cur in payload["data"]) {
         acc[cur] = payload["data"][cur];
       } else {
         acc[cur] = newState[cur];
       }
       return acc;
     }, {});
   return newState;
...


this is as far as I can go for react redux extension development for mv3. maybe I will find a simpler way in the future.

have a nice day
Ulvi.










14 Şubat 2021 Pazar tarihinde saat 06:33:54 UTC+3 itibarıyla marcu...@gmail.com şunları yazdı:

wOxxOm

unread,
Feb 14, 2021, 10:04:48 AM2/14/21
to Chromium Extensions, ulv...@gmail.com
There is no need to register the background service worker explicitly in ManifestV3 as this is performed automatically when the extension is installed so I would expect such code to cause some problems, not necessarily those you reported here though...

ULViDO

unread,
Feb 14, 2021, 1:12:49 PM2/14/21
to Chromium Extensions, wOxxOm, ULViDO
it is true. thank you. no need to register service worker.


//** IGNORE START **//
  and you need to register your service worker in your popup.js:

  and you need to register your service worker in your popup.js:

  // somewhere in popup.js
  ...
  // register service worker
  if ("serviceWorker" in navigator) {
  console.log("Service Worker Supported.");
  window.addEventListener("load", () => {
  navigator.serviceWorker.register("sw.js")
    .then(reg => console.log("Service Registered.", reg))
    .catch(err => console.error("ERROR!", err));
  });
  }

//** IGNORE END **//
14 Şubat 2021 Pazar tarihinde saat 18:04:48 UTC+3 itibarıyla wOxxOm şunları yazdı:
Reply all
Reply to author
Forward
0 new messages