-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple entry points not working correctly #88
Comments
This is easy to reproduce with the following one-line change to the webpack-dev-server example: diff --git a/examples/webpack-dev-server/webpack.config.js b/examples/webpack-dev-server/webpack.config.js
index 0422c13..a5cd4b2 100644
--- a/examples/webpack-dev-server/webpack.config.js
+++ b/examples/webpack-dev-server/webpack.config.js
@@ -8,6 +8,7 @@ module.exports = {
mode: isDevelopment ? 'development' : 'production',
entry: {
main: './src/index.js',
+ test1: './src/ClassDefault.jsx',
},
module: {
rules: [
|
It is intended - there is no way we can control the execution order of multiple entry points. I would love to help, but I cannot comment on your specific case unless I have more context.
This is not necessarily how multi-entry should be used to my understanding. If you're doing a single page app, you should use a single entry point and use Referencing the Webpack docs here:
I'll tinker with Webpack and see if there's anything I can do in this regard. |
Our use case is that we load Sentry (a JS error tracking framework) via a separate bundle. If we had the ability to exclude entry points from being injected with react-refresh, it would solve our issue. Would you be OK with a pull request adding a new option to disable entries |
What is the root of the actual issue? Why is it bad (from one point of view) or necessary (from another point of view) to inject it in all entries? Every option makes configuring it more error-prone. Can we figure out a reasonable default behavior? |
Not too sure what the root issue is.. the runtime looks like it just calls |
In my preliminary tests it seems that the
The main issue with multiple entries is that there's no deterministic way for us to ensure that code will be executed in a specific order. For the case of This is partially an artifact from the webpack<4 era, when people used to use entries to do chunking and create async/parallel-loaded independent bundles. This is not really the case now - multiple entries are discouraged by Webpack officially for single-page apps and should be used only when you have multiple HTML entries. CC @sokra - would love your thoughts on my take on this.
If my interpretation above is correct, then the current behaviour is a reasonable default - we're ensuring that the refresh runtime will be ran for all independent HTML entry points at the start, and they won't intervene with each other.
This will work, but I would want to try and see if we can solve this by other means before resorting to exposing more options here. |
Why does including the runtime multiple times cause a problem? Can we simply make its second execution a no-op? i.e. it would not override any globals and would not do any side effects if |
You can use multiple entry points on a single page, but make sure to use Webpack will also add the ability to create entry points that are children of other entries with Anyway: Use a single webpack runtime per html page. |
I think it would be the best to avoid using globals and instead plugin into the parser to rewrite The webpack ApiPlugin has examples how to rewrite in the parser. It need to be rewritten e.g. to something like |
@pmmmwh Do you think this will be straightforward to implement? We can workaround on our side, debating whether we should do the workaround, or wait for an update on the plugin. No worries either way! Just want to figure out what works best on our side. |
It will probably take some time (few days to 1-2 weeks) because the fix Tobias suggested will require some work to properly wire up Webpack parser hooks. If you have a work-around, feel free to do so. |
we'll actually probably hold off until this issue is fixed! let me know if I can do anything to help. |
@sokra I was thinking to do something along the lines of: // Somehow get this injected
__webpack_require__.$RefreshRuntime$ = require('react-refresh/runtime'); Do I need to somehow get the source of the module and evaluate it to string? When I started writing the plugin I recall myself going down this path too, but was unable to properly make this work (without multiple evaluation passes/busting cache all the time). |
Try to place only It need to be an extra object as You can't access modules in the runtime since they may not be loaded at this point, e.g. when using |
I'm also having trouble with this. In my case, this plugin inserts itself into the polyfill bundle, breaking IE 11 because it's using URLSearchParams internally (which is not yet defined). Would it be possible to expose something like |
Hmm ... The call to
The difficult part is that there's both code to run BEFORE any user code, and AFTER all user code. The runtime, as of it's current state, is also quite coupled with the |
Thanks for the reply @pmmmwh. I'll get back to you if I can better isolate the issue (or if I manage to find it's because of something else). |
I am facing a similar problem. I want the webpack runtime bundle to always include certain modules. This is turning out hard to do with multiple entry points ( each with their own runtime) as the custom module is extracted in a default common chunk by SplitChunk plugin. The use case I have is I am loading the bundle in a non-browser environment and I need to use custom modules for chunk fetching. |
In case anyone is looking for a workaround for multiple entry points this worked for me: const BaseReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
class ReactRefreshWebpackPlugin extends BaseReactRefreshWebpackPlugin {
apply(compiler) {
super.apply(compiler);
if (compiler.options.entry.djangoStyles) {
// Remove all the hot module related packages from djangoStyles entry point.
// Without this HMR breaks with error `Uncaught Error: Iframe has not been created yet.`
// This came from react-error-overlay but this issue is likely related:
// https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/88
// There's no option to disable it directly
const excludeEntries = [
'@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js',
'@alliance-software/webpack-dev-utils/client/hot-client-errors.js',
'webpack/hot/dev-server.js',
];
compiler.options.entry.djangoStyles = compiler.options.entry.djangoStyles.filter(
path => excludeEntries.filter(p => path.endsWith(p)).length === 0
);
}
}
} |
If anyone is using Webpack 5 feel free to give the latest beta a try, it should inject everything as global instead on a specific entrypoint, effectively eliminating the issue. |
Our team has a config with the form:
We were very excited to try out
react-refresh-webpack-plugin
, but unfortunately, could not get it working!Through a process of trial and error, I removed
entry2
, and it started working. I think this is due to the logic ininjectRefreshEntry
, which would double-append react refresh into both entries. Is this intentional behavior?Thanks!
Mike
The text was updated successfully, but these errors were encountered: