Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to build SSR with multi-lang (i18n) with Angular 9 #1497

Closed
keserwan opened this issue Feb 10, 2020 · 5 comments
Closed

How to build SSR with multi-lang (i18n) with Angular 9 #1497

keserwan opened this issue Feb 10, 2020 · 5 comments

Comments

@keserwan
Copy link

How to build SSR with i18n with Angular 9?

With the new angular version, documentation is not clear to me how to build angular 9 SSR with i18n.
Previously in version 8, I was doing the following commands:

  1. ng build --configuration=production-ar && ng build --configuration=production-en && ng run website:server:production-en && ng run website:server:production-ar
  2. then webpack --config apps/website/webpack.server.config.js --progress --colors
    you can check my implementation in this demo repo: https://github.com/keserwan/testAngularPrerender
    The output in the "dist" folder was the following:
    dist>Website>
  -server.js
  -server
     -ar
     -en
  -client
    -ar
    -en

Currently, I am lost how to build multi-lang without webpack.server.config.js .
Is there any template project for such requirements? I didn't find it in the documentation.

here is my current angular.json
image

here is my server.ts (I modified line 14 to read from /website/ar/browser)
image

How to make server.ts file work for both languages?
Should I have 2 instances of the server (line 44 in the image above)? one for 'en' and one for 'ar'?
What changes should I do to server.ts to do these 2 calls? Should I create 2 server.ts?
ng run website:server:production-en && ng run website:server:production-ar

🌍 Your Environment


@angular-devkit/architect          0.900.1
@angular-devkit/build-angular      0.900.1
@angular-devkit/build-ng-packagr   0.900.1
@angular-devkit/build-optimizer    0.900.1
@angular-devkit/build-webpack      0.900.1
@angular-devkit/core               8.3.23
@angular-devkit/schematics         8.3.23
@angular/cli                       9.0.1
@angular/http                      7.2.16
@ngtools/webpack                   9.0.1
@nguniversal/builders              9.0.0
@nguniversal/common                9.0.0
@nguniversal/express-engine        9.0.0
@schematics/angular                8.3.23
@schematics/update                 0.900.1
ng-packagr                         9.0.0
rxjs                               6.5.4
typescript                         3.7.5
webpack                            4.41.2

@keserwan
Copy link
Author

I am not able to configure SSR with i18n.
Previously everything was working fine with Webpack.server.config.js.

@alan-agius4
Copy link
Collaborator

Hi, let continue tracking this here #1497

@alan-agius4 alan-agius4 pinned this issue Feb 10, 2020
@alan-agius4 alan-agius4 unpinned this issue Feb 10, 2020
@alan-agius4
Copy link
Collaborator

Wrong link angular/angular-cli#25726

@keserwan
Copy link
Author

I was able to let it work by creating 2 server.ts files (server.ar.ts) and (server.en.ts)
With this implementation, I need to run 2 express engines (port 4000 & port 4001) on the server.

  1. add these two files (server.ar.ts & server.en.ts) to tsconfig.server.json
    "files": [ "src/main.server.ts", "server.ar.ts", "server.en.ts" ],

  2. server.en.ts looks like the following:

import 'zone.js/dist/zone-node';

import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';

import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';

// The Express app is exported so that it can be used by serverless Functions.
export function app() {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/website/');

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', join(distFolder, 'browser'));

  // Example Express Rest API endpoints
  // app.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get('/en/*.*', express.static(join(distFolder, 'browser'), { maxAge: '1y' }));
  server.get('*.*', express.static(join(distFolder, 'browser', 'en'), { maxAge: '1y' }));

  const indexHtml = join(distFolder, 'browser', 'en', 'index.html');

  // All regular routes use the Universal engine
  server.get('/en/*', (req, res) => {
    res.render('en/index', { req, res });
  });
  server.get('*', (req, res) => {
    res.render('en/index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });

  return server;
}

function run() {
  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}`);
  });
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
  run();
}

export * from './src/main.server';

  1. add this to package.json
    "build:website:ssr": "ng build --configuration=production-ar && ng build --configuration=production-en ng run website:server:production-ar && ng run website:server:production-en"

  2. update angular angular.json build and server
    image
    image

with this implementation my dist folder will be like the following:

-website
  -browser
    -en
    -ar
  -server
    -en
    -ar

If you are deploying to apache 2.4 you can configure the virtual host as follows

<VirtualHost *:80>
	ServerName mywebsite.com
	ProxyPreserveHost On
	
	ProxyPassMatch "^/api.*$" http://127.0.0.1:5000
	ProxyPassReverse "^/api.*$" http://127.0.0.1:5000
		
	ProxyPass /en http://127.0.0.1:4001/
	ProxyPassReverse /en http://127.0.0.1:4001/
	
	ProxyPass /ar http://127.0.0.1:4001/
	ProxyPassReverse /ar http://127.0.0.1:4001/	

	ProxyPass / http://127.0.0.1:4000/
	ProxyPassReverse / http://127.0.0.1:4000/

	
	RewriteEngine On
	RewriteCond %{HTTP:X-Forwarded-Proto} =http
	RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]
	#ServerAlias *.localhost
	ErrorLog mywebsite-ssr-error.log
	CustomLog mywebsite-ssr-access.log common
</VirtualHost>

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants