Nos enfrentamos a un problema en el que los detectores de eventos o las variables globales que adjuntamos a la window no parecen estar allí en nuestra compilación de production (pero están allí en la compilación de development ).
webpack --mode=productionContexto :
Tenemos un caso de uso en el que nuestra aplicación web se representa dentro de una aplicación principal. La aplicación principal básicamente necesita decirnos cuándo necesitamos renderizar nuestra aplicación. Para hacer esto, hemos intentado usar detectores de eventos y funciones globales.
Para representar nuestra aplicación web dentro de la aplicación principal, sucede lo siguiente:
myappwebsite.com/asset-manifest.json . Esto es como el asset-manifest.json predeterminado que se crea para cualquier aplicación web create-react-app .bundle.js principal.js desde este manifiesto de activos y luego realiza una llamada HTTP para obtener nuestro bundle.js usando esta ruta (por ejemplo myappwebsite.com/bundle.js ).script en su head con su src establecido en nuestro bundle.js para cargar el javascript incluido de nuestra aplicación.onload de este nuevo elemento de secuencia de script antes de intentar llamar a nuestro código o enviar cualquier evento.Aplicación infantil:
// 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)); })Aplicación para padres:
// 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); Este código funciona en la compilación de development pero no en la compilación de production . En production , el envío se ejecuta, pero por alguna razón el detector de eventos no lo hace. Cuando intentamos establecer algunos puntos de interrupción en el paquete de producción minimizado, notamos que el código addEventListener está allí, sin embargo, en realidad no se está ejecutando... Esto es extraño porque addEventListener está en el nivel superior de index.tsx en el niño aplicación y no se agrega condicionalmente.
Aplicación infantil:
// index.tsx window.renderApp = (rootId) => { console.log('Child render is running'); // This only prints in `development` ReactDOM.render(<App />, document.getElementById(rootId)); })Aplicación para padres:
// 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); El mismo problema aquí, el código funciona en la compilación de development pero no en la compilación de production . En production , la llamada pasa pero la función global no parece estar en window . Puedo verificar esto imprimiendo una window en la consola.
Parece que cualquier global que configuro en la window o cualquier detector de eventos que configuro se ignora en la compilación de producción. ¿Es esto por el diseño de Webpack? ¿O cree que algo está mal en mi secuencia de comandos de configuración/construcción que está causando que esto suceda?
El problema terminó siendo un problema en el que la salida de nuestro paquete se separó en main.js y vendor.js , pero solo estábamos cargando main.js en la aplicación principal.
Agregue una entrada de nodo con global: true a su configuración:
node: { global: true, __filename: false, __dirname: false, },Webpack se comporta un poco extraño cuando se trata de objetos de Windows y podemos ubicar varias discusiones sobre este asunto.
De acuerdo con esta respuesta , agregar globalObject: 'this' a la sección de output en el archivo de configuración del paquete web podría solucionar el problema.
Otras referencias https://github.com/webpack/webpack/issues/7112 https://github.com/markdalgleish/static-site-generator-webpack-plugin/issues/130