We're facing an issue where any event listeners or global variables we attach to window
does not seem to be there in our production
build (but they are there in the development
build).
webpack --mode=production
Context:
We have a use case where our webapp renders inside a parent app. The parent app basically needs to tell us when we need to render our app. To do this, we have tried using event listeners as well as global functions.
To render our webapp inside the parent app, the following happens:
myappwebsite.com/asset-manifest.json
. This is like the default asset-manifest.json
that gets created for any create-react-app
webapp.bundle.js
from this asset manifest, and then makes an HTTP call to fetch our bundle.js
using this path (e.g. myappwebsite.com/bundle.js
).script
tag into their head
with its src
set to our bundle.js
to load our app's bundled javascript.onload
event of this new script
element before trying to call any of our code or dispatching any events.Child app:
// index.tsx
window.addEventListener('renderApp', (event) => {
console.log('This is running!'); // This only prints in `development`
const { rootId } = event.detail;
ReactDOM.render(<App />, document.getElementById(rootId));
})
Parent app:
// index.tsx
console.log('Dispatch is running!'); // This prints in both `development` and `production`
const renderEvent = new CustomEvent('renderApp', { detail: rootId: 'root' });
// This runs in the script.onload function to wait for our app to load
window.dispatchEvent(renderEvent);
This code works in the development
build but not in the production
build. In production
, the dispatch does execute, but for some reason the event listener does not. When we tried to set some breakpoints on the minified production bundle, we noticed that the addEventListener
code is there, however it is not actually executing... This is strange because the addEventListener
is at the top level of the index.tsx
in the child app and is not conditionally added.
Child app:
// index.tsx
window.renderApp = (rootId) => {
console.log('Child render is running'); // This only prints in `development`
ReactDOM.render(<App />, document.getElementById(rootId));
})
Parent app:
// index.tsx
console.log('Render is running!'); // This prints in both `development` and `production`
// This runs in the script.onload function to wait for our app to load
window.renderApp(rootId);
Same issue here, the code works in the development
build but not in the production
build. In production
, the call goes through but the global function does not seem to be on window
. I am able to verify this by printing out window
in the console.
It seems that any globals I set on window
or any event listeners I set to it get ignored in the production build. Is this by Webpack's design? Or do you think something is messed up in my config/build script that is causing this to happen?
webpack's environment variables are different from the environment variables of operating system shells like bash and CMD.exe The webpack command line environment option --env allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your webpack.config.js.
To disambiguate in your webpack.config.js between development and production builds you may use environment variables. webpack's environment variables are different from the environment variables of operating system shells like bash and CMD.exe
Also, we've added the recommended devtool for that environment (strong source mapping), as well as our devServer configuration. Finally, in webpack.prod.js, mode is set to production which loads TerserPlugin, which was first introduced by the tree shaking guide.
The webpack command line environment option --env allows you to pass in as many environment variables as you like. Environment variables will be made accessible in your webpack.config.js. For example, --env production or --env goal=local. npx webpack --env goal=local --env production --progress
The problem ended up being an issue where the output of our bundle was separated into main.js
and vendor.js
, but we were only loading the main.js
into the parent app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With