'How to chrome.runtime.reload() a Chrome Extension when building it with Webpack 5 Boilerplate?
I am using https://github.com/lxieyang/chrome-extension-boilerplate-react as the basis to build a chrome extension. It all works fine, and everything does hot-reloading (popup, background, options, newtab) except for the content-script. Reloading the matching pages, does not reload the underlying .js. It takes to reload/turn-off-on the whole extension in order for the changes to go into effect.
So, in webpack.config.js i commented out 'contentScript' hoping for it to fix that, but it makes no difference.
...
chromeExtensionBoilerplate: {
notHotReload: [
//'contentScript'
],
},
...
In src/pages/Content/index.js it actually states
console.log('Must reload extension for modifications to take effect.');
When developing another extension in plain vanilla js, i dropped a hot-reload.js from https://github.com/xpl/crx-hotreload which worked perfectly. From what i understand it is the 'chrome.runtime.reload()' call that makes chrome completely reload the extension.
So my question(s) actually is:
- When changing src/pages/Content/index.js, webpack does re-build the build/contentScript.bundle.js. But why doesn't manually reloading the tab/page recognize these changes, when for popup, background, etc. it does?
- And if there is no way to let the above boilerplate reload the extension (i don't mind the hard reload) how would i be able to integrate the hot-reload.js (or its effect actually) into this boilerplate? That is, how do i reload the extension when build/contentScript.bundle.js is changed?
Thanks in advance!
Solution 1:[1]
For who is interested. I ended up placing mentioned hot-reload.js in my extension, and loading it from within the background script. That breaks webpack's hot-reloading, by reloading the entire extension on any file-change. But as long as i only work on the content script, thats fine. I can remove it once im done, or if i work on other scripts.
Solution 2:[2]
Use server-sent-events:
const SSEStream = require('ssestream').default;
let sseStream;
...
setupMiddlewares: (middlewares, _devServer) => {
if (!_devServer) {
throw new Error('webpack-dev-server is not defined');
}
/** ???/reload path SSE */
middlewares.unshift({
name: 'handle_content_change',
// `path` is optional
path: '/reload',
middleware: (req, res) => {
console.log('sse reload');
sseStream = new SSEStream(req);
sseStream.pipe(res);
res.on('close', () => {
sseStream.unpipe(res);
});
},
});
return middlewares;
}
- webpack.compiler.hook
let contentOrBackgroundIsChange = false;
compiler.hooks.watchRun.tap('WatchRun', (comp) => {
if (comp.modifiedFiles) {
const changedFiles = Array.from(comp.modifiedFiles, (file) => `\n ${file}`).join('');
console.log('FILES CHANGED:', changedFiles);
if(watchRunDir.some(p => changedFiles.includes(p))) {
contentOrBackgroundIsChange = true;
}
}
});
compiler.hooks.done.tap('contentOrBackgroundChangedDone', () => {
if(contentOrBackgroundIsChange) {
contentOrBackgroundIsChange = false;
console.log('--------- ?? chrome reload ?? ---------');
sseStream?.writeMessage(
{
event: 'content_changed_reload',
data: {
action: 'reload extension and refresh current page'
}
},
'utf-8',
(err) => {
sseStream?.unpipe();
if (err) {
console.error(err);
}
},
);
}
});
- crx background
if(process.env.NODE_ENV === 'development') {
const eventSource = new EventSource(`http://${process.env.REACT_APP__HOST__}:${process.env.REACT_APP__PORT__}/reload/`);
console.log('--- start listen ---');
eventSource.addEventListener('content_changed_reload', async ({ data }) => {
const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
const tabId = tab.id || 0;
console.log(`tabId is ${tabId}`);
await chrome.tabs.sendMessage(tabId, { type: 'window.location.reload' });
console.log('chrome extension will reload', data);
chrome.runtime.reload();
});
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | spaxxUnited |
| Solution 2 | godis |
