I'm in the process of migrating an angular 7 application to angular 9, which uses server side rendering (angular universal) and angular i18n for 2 languages (french and english).
In the old angular 7 process, since I was using AOT I had to do 5 builds for production:
- 2 x client build (1 for french, 1 for english)
- 2 x server build (1 for french, 1 for english)
- build of server.ts
Then, in server.ts
I was loading dynamically the correct server bundle
old server.ts
app.engine('html', (_, options: any, callback) => {
const isFR= options.req.url.indexOf('site-fr') >= 0 ;
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = isFR ? require('./dist/server/fr/main') : require('./dist/server/en/main');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', isFR ? 'fr' : 'en', 'index.html')).toString();
renderModuleFactory(AppServerModuleNgFactory, {
// Our index.html
document: template,
I migrated the app to angular 9, and now from what I understand in the documentation, only one client build is needed.
You can also provide the --localize option to the ng build command with your existing production configuration. In this case, the CLI builds all locales defined under i18n in the project configuration.
This seems to work for the client build, as 2 folders (fr
and en
are generated).
However, nowhere is there any mention of using SSR with i18n. So I'm ending up with one server.ts
.
Here are the scripts I use to build and run the project
angular.json
"serve:ssr": "node dist/myproject/server/main.js",
"build:ssr": "ng build -c production --localize && ng run myproject:server:production"
new server.ts
// The Express app is exported so that it can be used by serverless Functions.
export function app(port) {
const server = express();
const distFolder = join(process.cwd(), 'dist/myproject/browser/fr');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
Dist folder structure
- dist
- myproject
- browser
- fr
- index.html
- *.js
- en
- index.html
- *.js
- server
- main.js
Note: I did see a closed github issue describing this problem, but the solution is basically to go back the way it was before, i.e. have 2 builds per language and also 2 builds for server.ts
.
Surely there is another way?
TranslateHttpLoader
. In my AppServerModule I used the TranslateJsonLoader. No page reload required! – Mountebank