# 02 lazy loading webpack <hr /> `[@microapp/clock]` - El primer paso importante es hacer uso del import dinámico. El objetivo es que nuestro entrypoint para microapp sea algo tan sencillo como una importación dinámica del interface. Con esto conseguiremos que se generen 2 bundles en lugar de uno, el primer bundle cargará de forma asíncrona al segundo. pero el primero será muy pequeño, su unica funcionalidad es esa, hacer la carga asíncrona del segundo. - Para ello vamos a dividir nuestro `microapp.entrypoint.tsx` en 2 ficheros. Renombramos el actual `microapp.entrypoint.tsx` como `microapp.interface.tsx` y creamos uno nuevo para entrypoint: ```text [RENAME] microapp.entrypoint.tsx -> microapp.interface.tsx [CREATE] microapp.entrypoint.tsx ``` `[@microapp/clock] microapp.entrypoint.tsx` ```tsx // Import dinámico de webpack. Asi habilitamos code-splitting. export default () => import("./microapp.interface"); ``` `[@microapp/clock] tsconfig.json` - **WARNING**: Atentos al error que nos da TS. Para soportar la sintaxis de import dinámico tenemos que cambiar el formato de los módulos a ESNext. Lo hacemos: ```diff "compilerOptions": { "lib": ["DOM", "ESNext"], "target": "es6", + "module": "ESNext", "moduleResolution": "node", "declaration": false, "noImplicitAny": false, "sourceMap": true, "jsx": "react", "noLib": false, "suppressImplicitAnyIndexErrors": true, "skipLibCheck": true, "allowSyntheticDefaultImports": true }, ``` `[@microapp/clock] microapp.d.ts` - Actualizamos el tipado en nuestro ambient file, ya no exportamos el interfaz directamente sino una funcion para la carga lazy: ```diff export type MicroappRenderFunction = (container: Element) => void; export type MicroappUnmountFunction = (container: Element) => boolean; export interface MicroappInterface { render: MicroappRenderFunction; unmount: MicroappUnmountFunction; } + declare function Microapp(): Promise<MicroappInterface>; + export default Microapp; ``` `[@microapp/clock] standalone.entrypoint.ts` - Tenemos que actualizar también el standalone entrypoint. Ya no consumirá un interfaz directamente sino una función asíncrona que nos devuelve dicho interfaz mediante promesa: ```diff import "./standalone.styles"; + import Microapp from "./microapp.entrypoint"; + Microapp().then(microapp => microapp.MicroappInterface?.render(document.getElementById("root"))); ``` `[@microapp/clock]` - Llegados a este punto podemos probar a lanzar una compilación para microapp e inspeccionar los bundles resultantes. - Abrir el report generado por el bundle analyzer. ```text npm run build:microapp:dev ``` - Tenemos 3 bundles: - Nuestro `clock.js` que pesa muy poco y cuya misión simplemente es contener un pequeño runtime para cargar de forma asíncrona a los otros 2 bundles restantes. - Bundle `0.js`, que será un bundle asíncrono con todo el codigo de vendor. - Bundle `1.js`, que será un bundle asíncrono con todo el codigo propietario. - Esta es la nomenclatura que utiliza `webpack` por defecto, pero como vamos a usarlo junto con otros microapps que también generarán multiples bundles asíncronos, los nombres podrían colisionar. Por ese motivo, hacemos un último cambio en la configuración: `[@microapp/clock] microapp.js`: - Vamos a nombrar los bundles que se generan con el code-splitting con algún sufijo que evite las colisiones. Para eso renombramos los chunks que se generan: ```diff output: { path: helpers.buildMicroappPath, filename: `[name].js`, + chunkFilename: `${helpers.bundleName}.async.[id].js`, // Esta es la forma mas sencilla de exportar la librería al hacer microfrontends // aunque no la más compatible de cara a consumirla para otros usos. libraryTarget: "var", library: helpers.bundleNamePascalCase, }, ``` - **OPCIONAL** Además también tenemos como paso OPCIONAL si queremos, desactivar la separación en 2 bundles distintos para vendor y para código nuestro. Podemos dejarlo todo en un único bundle si queremos: ```diff + optimization: { + splitChunks: { + chunks: "all", + cacheGroups: { + vendors: false, + }, + }, + }, ``` `[@microapp/clock]` - Probamos de nuevo y comprobamos el resultado: ```text npm run build:microapp:dev ``` <hr />