El equipo de Angular está trabajando en un nuevo constructor llamado aplicación (el constructor actual se llama navegador), ya está disponible como vista previa para desarrolladores en Angular 16.2 y será el predeterminado para las nuevas aplicaciones generadas utilizando Angular 17
así que primero
¿Qué es un constructor en Angular?
Angular builder (llamado executer en nx repos) es básicamente el compilador que convierte tu aplicación Angular TS, Angular HTML, y archivos SCSS en HTML plano, JS y archivos css que pueden ser entendidos por el navegador
ahora mismo tenemos múltiples constructores
@angular-devkit/build-angular:browser
: para la compilación de producción@angular-devkit/build-angular:dev-server
para servir p.ej. ng serve que todavía usa@angular-devkit/build-angular:browser
bajo el capó pero sin mucha optimización y exponiendo algunas partes del compilador Angular en el tiempo de ejecución.@angular-devkit/build-angular
:server para ssr production build@nguniversal/builders:ssr-dev-server
para ssr serve@nguniversal/builders:
prerender para prerender.
ahora todos estos estan basados en webpack, hay uno nuevo @angular-devkit/build-angular:browser-esbuild
y como su nombre indica usa esbuild, actualmente esta disponible como developer preview (de hecho lo estoy usando en produccion para https://interview.community sin ningun problema)
¿dónde encaja el nuevo constructor?
Usará @angular-devkit/build-angular:browser-esbuild
bajo el capó pero lo extenderá para reemplazar también @angular-devkit/build-angular:server
y @nguniversal/builders:prerender
y como ahora puede hacerlo tanto el navegador como el ssr build, hará que @angular-devkit/build-angular:dev-server pueda reemplazar a @nguniversal/builders:ssr-dev-server
así que básicamente en el futuro tendremos 2 en lugar de los 5 actuales (bueno, hay algunos otros constructores para pruebas unitarias e i18n, pero eso es otra historia)
¿Cuáles son los beneficios de hacer todo esto?
- Configuración más simple en el angular.json (o
project.json
en el caso de nx), ya que no es necesario repetir la configuración en un montón de lugares) - Es más rápido, ya que hay algunos pasos comunes entre la construcción del navegador, prerender, y ssr tener un constructor significará que estos pasos se ejecutarán una vez en lugar de 3 ahora.
- habilitará el uso de módulos es (aka esm) en el SSR, ahora funciona para proyectos que no tienen SSR
¿cómo probar este nuevo constructor?
- Actualiza a la última versión de Angular (@angular/cli es 16.2.3 en el momento en que publiqué el artículo)
- actualiza tu archivo angular.json: cambia tu constructor en build de
@angular-devkit/build-angular:browser a @angular-devkit/build-angular:application
- (opcional) actualiza
outputPath
para que no tenga browser ya que ahora es una carpeta para el servidor y el browser reemplazar clave principal para ser navegador que apunta todavía a su archivomain.ts
- Añade "server":
"src/main.server.ts"
o cualquiera que sea la ruta para sumain.server.ts
- Añade "ssr:
{ "entry": "server.ts" }
en sus configuraciones de producción o si prefiere tener ssr en su desarrollo entonces añádalo como opción - Elimina server , serve-ssr , y prerender de su archivo
actualice su archivo server.ts para que sea.
3. Actualice su archivo server.ts
para que sea
import { APP_BASE_HREF } from '@angular/common';
import { ngExpressEngine } from '@nguniversal/express-engine';
import express from 'express';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import bootstrap from './src/main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = dirname(fileURLToPath(import.meta.url));
const indexHtml = join(distFolder, 'index.server.html');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap
}));
server.set('view engine', 'html');
server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
function run(): void {
const port = process.env['PORT'] || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
run();
4. Actualiza su tsconfig.app.json
para que sea
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": [],
"allowSyntheticDefaultImports": true
},
"files": [
"src/main.ts",
"src/main.server.ts",
"server.ts"
],
"include": [
"src/**/*.d.ts"
]
}
5. tu script serve:ssr
será node dist/nombre_proyecto/server.mjs
y eso es todo, usted es bueno ir ahora
puedes ver el ejemplo de cambios y la aplicación funcionando aquí