Solution over AWS and Lambda
server.ts
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { fileURLToPath } from 'url';
import { dirname, join, resolve } from '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 serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');
const indexHtml = join(serverDistFolder, 'index.server.html');
const commonEngine = new CommonEngine();
server.set('view engine', 'html');
server.set('views', browserDistFolder);
// Serve static files from /browser
server.get('*.*', express.static(browserDistFolder, {
maxAge: '1y'
}));
// All regular routes use the Angular engine
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap: bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => {
res.send(html)
})
.catch((err) => {
next(err)
});
});
return server;
}
export * from './src/main.server';
lambda.js
const awsServerlessExpress = require('aws-serverless-express');
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware');
const binaryMimeTypes = [
"application/javascript",
"application/json",
"application/octet-stream",
"application/xml",
"image/jpeg",
"image/png",
"image/webp",
"image/gif",
"text/comma-separated-values",
"text/css",
"text/html",
"text/javascript",
"text/plain",
"text/text",
"text/xml",
"image/x-icon",
"image/svg+xml",
"application/x-font-ttf",
"font/ttf",
"font/otf",
"font/woff",
"font/woff2"
];
module.exports.handler = async (event, context) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
try {
// Import the app from the ES module
const server = await import('./dist/app-name/server/server.mjs');
const app = await server.app();
app.use(awsServerlessExpressMiddleware.eventContext());
// Create a server with the specified MIME types
const serverAws = awsServerlessExpress.createServer(app, null, binaryMimeTypes);
if (!app) {
console.error('Server is not initialized');
return;
} else {
return awsServerlessExpress.proxy(serverAws, event, context, 'PROMISE').promise;
}
} catch (error) {
console.error('Failed to import app:', error);
}
};
serverless.yml
service: service-name
frameworkVersion: '3'
plugins:
- serverless-apigw-binary
provider:
name: aws
runtime: nodejs20.x
memorySize: 192
timeout: 10
region: us-east-1
apiGateway:
shouldStartNameWithService: true
package:
excludeDevDependencies: true
exclude:
- ./**
- '!node_modules/@vendia/**'
include:
- "node_modules/aws-serverless-express/**"
- "node_modules/binary-case/**"
- "node_modules/type-is/**"
- "node_modules/media-typer/**"
- "node_modules/mime-types/**"
- "node_modules/mime-db/**"
- "node_modules/@angular/ssr"
- "node_modules/@codegenie/**"
- "dist/**"
- "lambda.js"
functions:
server:
handler: lambda.handler
events:
- http: ANY /{proxy+}
- http: ANY /
resources:
- ${file(resources.yml)}
Also in angular.json you shoud change this line
"prerender": false, //<-Change to false
tsconfig.server.json
by removingtarget
and setting"module": "CommonJS"
? The builder should generate a single js filr – Lauricetsconfig.server.json
– Foran