280 Angular 14 Library, Webpack 5, Internationalization - chempkovsky/CS82ANGULAR GitHub Wiki

Notes

  • start with a review article on @angular-architects/module-federation
  • Creating a new Dynamic Host application
  • our goal is to make sure that Internationalization will work correctly with the Angular 14 library, federation module on the dev bench.
    • we will create a couple of subprojects with type = remote
    • one subproject with type = shell
    • one library subproject
    • using generated service in the library we will send data from shell app to remote app
  • take a look at "nx"-tool
    • generate static host
    • converting to dynamic host manually
    • generate dynamic host
    • They wrote:
      • "When serving module federation apps in dev mode locally, there'll be an error output to the console, import.meta cannot be used outside of a module, and the script that is coming from is styles.js. It's a known error output, but it doesn't actually cause any breakages from as far as our testing has shown. It's because Angular compiler attaches the styles.js file to the index.html in a script tag with defer. It needs to be attached with type=module, but Angular can't make that change because it breaks HMR. They also provide no way of hooking into that process for us to patch it ourselves. The good news is that the error doesn't propagate to production, because styles are compiled to a CSS file , so there's no erroneous JS to log an error. It's worth stressing that there's been no actual errors or breakages noted from our tests."

Steps required to accomplish the task

Create Angular Mono Repository

  • run windows terminal, cd the drive and folder you like
    • our choice was E:\
  • run the command
ng new ang-monorepo --no-create-application
cd ang-monorepo

Create subprojects

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng generate library share-lib
ng generate application mfe1
ng generate application mfe2
ng generate application shell
  • for mfe1, mfe2 and shell subprojects
    • Angular routing = Yes
    • stylesheet = css

Create Home component for subprojects

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following command
ng generate component home0 --project shell
ng generate component home1 --project mfe1
ng generate component home2 --project mfe2

Create two modules for mfe1 subproject

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng generate module components/md11 --routing --project mfe1
ng generate module components/md12 --routing --project mfe1

Add two components to each module created in the mfe1 subproject

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng generate component components/md11/master11 --project mfe1
ng generate component components/md11/detail11 --project mfe1
ng generate component components/md12/master12 --project mfe1
ng generate component components/md12/detail12 --project mfe1

Create one module for mfe2 subproject

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng generate module components/md21 --routing --project mfe2

Add two components to module created in the mfe2 subproject

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng generate component components/md21/master21 --project mfe2
ng generate component components/md21/detail21 --project mfe2

RouterModule forChild for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\src\app\components\md11\md11-routing.module.ts file as follows
Click to show the code
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Detail11Component } from './detail11/detail11.component';
import { Master11Component } from './master11/master11.component';

const routes: Routes = [
  {
    path: 'detail11',
    component: Detail11Component
  },
  {
    path: '',
    component: Master11Component,
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class Md21RoutingModule { }
  • modify \ang-monorepo\projects\mfe1\src\app\components\md12\md12-routing.module.ts file as follows
Click to show the code
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Detail12Component } from './detail12/detail12.component';
import { Master12Component } from './master12/master12.component';

const routes: Routes = [
  {
    path: 'detail12',
    component: Detail12Component
  },
  {
    path: '',
    component: Master12Component,
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class Md12RoutingModule { }
  • modify \ang-monorepo\projects\mfe2\src\app\components\md21\md21-routing.module.ts file as follows
Click to show the code
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Detail21Component } from './detail21/detail21.component';
import { Master21Component } from './master21/master21.component';

const routes: Routes = [
  {
    path: 'detail21',
    component: Detail21Component
  },
  {
    path: '',
    component: Master21Component,
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class Md21RoutingModule { }

RouterModule forRoot for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\src\app\app-routing.module.ts file as follows
Click to show the code
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Home1Component } from './home1/home1.component';

const routes: Routes = [
  { 
    path: '', 
    component: Home1Component, 
    pathMatch: 'full'
 },
 { 
    path: 'master011', 
    loadChildren: () => import('./components/md11/md11.module')
        .then(m => m.Md11Module)
 },
 { 
   path: 'master012', 
   loadChildren: () => import('./components/md12/md12.module')
       .then(m => m.Md12Module)
 }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
  • modify \ang-monorepo\projects\mfe2\src\app\app-routing.module.ts file as follows
Click to show the code
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Home2Component } from './home2/home2.component';

const routes: Routes = [
  { 
    path: '', 
    component: Home2Component, 
    pathMatch: 'full'
 },
 { 
    path: 'master021', 
    loadChildren: () => import('./components/md21/md21.module')
        .then(m => m.Md21Module)
 }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

App Component Html for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\src\app\app.component.html file as follows
Click to show the code
<style> a { margin: 5px;  } </style>

<p>Mfe1 AppComponent works!</p>

<a routerLink="/">Go to home 1 component</a>
<a routerLink="/master011">Go to master 011</a>
<a routerLink="/master012">Go to master 012</a>

<router-outlet></router-outlet>
  • modify \ang-monorepo\projects\mfe2\src\app\app.component.html file as follows
Click to show the code
<style> a { margin: 5px;  } </style>

<p>Mfe2 AppComponent works!</p>

<a routerLink="/">Go to home 2 component</a>
<a routerLink="/master021">Go to master 021</a>

<router-outlet></router-outlet>

Master Html for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\src\app\components\md11\master11\master11.component.html file as follows
Click to show the code
<p>master11 works!</p>
<a routerLink="./detail11" >Go to detail 11</a>
  • modify \ang-monorepo\projects\mfe1\src\app\components\md12\master12\master12.component.html file as follows
Click to show the code
<p>master12 works!</p>
<a routerLink="./detail12" >Go to detail 12</a>
  • modify \ang-monorepo\projects\mfe2\src\app\components\md21\master21\master21.component.html file as follows
Click to show the code
<p>master21 works!</p>
<a routerLink="./detail21" >Go to detail 21</a>

Detail Html for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\src\app\components\md11\detail11\detail11.component.html file as follows
Click to show the code
<p>detail11 works!</p>
<a routerLink="../" >Go to master 11</a>
  • modify \ang-monorepo\projects\mfe1\src\app\components\md12\detail12\detail12.component.html file as follows
Click to show the code
<p>detail12 works!</p>
<a routerLink="../" >Go to master 12</a>
  • modify \ang-monorepo\projects\mfe2\src\app\components\md21\detail21\detail21.component.html file as follows
Click to show the code
<p>detail21 works!</p>
<a routerLink="../" >Go to master 21</a>

Test mfe1 and mfe2 subprojects

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following command
ng serve -o --project mfe1
  • make sure the navigation works as expected
Click to show the picture

project structure

  • run the following command
ng serve -o --project mfe2
  • make sure the navigation works as expected
Click to show the picture

project structure

Preliminary result

  • Both apps can be developed and tested independently
    • mfe1
    • mfe2

Add module federation support

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng add @angular-architects/module-federation --project mfe1 --port 4201 --type remote
ng add @angular-architects/module-federation --project mfe2 --port 4202 --type remote
ng add @angular-architects/module-federation --project shell --port 4200 --type dynamic-host

webpack config for mfe1 and mfe2 subprojects

  • modify \ang-monorepo\projects\mfe1\webpack.config.js file as follows
Click to show the code
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({

  name: 'mfe1',

  exposes: {
    './Themodule11': './projects/mfe1/src/app/components/md11/md11.module',
    './Themodule12': './projects/mfe1/src/app/components/md12/md12.module',
  },

  shared: {
    ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
  },

});
  • modify \ang-monorepo\projects\mfe2\webpack.config.js file as follows
Click to show the code
const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({

  name: 'mfe2',

  exposes: {
    './Themodule21': './projects/mfe2/src/app/components/md21/md21.module',
  },

  shared: {
    ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }),
  },

});

RouterModule forRoot for shell subproject

  • modify \ang-monorepo\projects\shell\src\app\app-routing.module.ts file as follows
Click to show the code
import { loadRemoteModule } from '@angular-architects/module-federation';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Home0Component } from './home0/home0.component';

const routes: Routes = [
  { 
    path: '', 
    component: Home0Component, 
    pathMatch: 'full'
 },
 {
  path: 'mfe011',
  loadChildren: () => loadRemoteModule({
      type: 'manifest',
      remoteName: 'mfe1',
      exposedModule: './Themodule11'
    })
    .then(m => m.Md11Module)
 },
 {
  path: 'mfe012',
  loadChildren: () => loadRemoteModule({
      type: 'manifest',
      remoteName: 'mfe1',
      exposedModule: './Themodule12'
    })
    .then(m => m.Md12Module)
 },
 {
  path: 'mfe021',
  loadChildren: () => loadRemoteModule({
      type: 'manifest',
      remoteName: 'mfe2',
      exposedModule: './Themodule21'
    })
    .then(m => m.Md21Module)
 },

  
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Master Html for shell subproject

  • modify \ang-monorepo\projects\shell\src\app\app.component.html file as follows
Click to show the code
<style> a { margin: 5px;  } </style>

<p>Shell AppComponent works!</p>

<a routerLink="/">Go to home 0 component</a>
<a routerLink="/mfe011">Go to master 011</a>
<a routerLink="/mfe012">Go to master 012</a>
<a routerLink="/mfe021">Go to master 021</a>

<router-outlet></router-outlet>

Test soluton

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng serve -o --project mfe1
  • in the second terminal
ng serve -o --project mfe2
  • in the third terminal
ng serve -o --project shell
  • make sure navigation to remote apps is working properly
    • stop all apps
Click to show the picture

project structure

Module federation Issue

  • Browser console shown the following error
Uncaught SyntaxError: Cannot use 'import.meta' outside a module (at styles.js:7831:29)  styles.js:7831
Click to show the picture

project structure

  • here is some details
Click to show the picture

project structure

  • here is the function
Click to show the code
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ 	var scriptUrl;
/******/ 	if (typeof import.meta.url === "string") scriptUrl = import.meta.url
/******/ 	// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
/******/ 	// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
/******/ 	if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
/******/ 	scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
/******/ 	__webpack_require__.p = scriptUrl;
/******/ })();

Internationalization

angular localize

  • we continue with the current folder
    • in our case it is e:\ang-monorepo
  • run the following commands
ng add @angular/localize
  • here is a response
E:\ang-monorepo>ng add @angular/localize
i Using package manager: npm
√ Found compatible package version: @angular/[email protected].
√ Package information loaded.

The package @angular/[email protected] will be installed and executed.
Would you like to proceed? Yes
√ Packages successfully installed.
Option "name" is required.

E:\ang-monorepo>

modify master component ts

  • modify \ang-monorepo\projects\mfe1\src\app\components\md11\master11\master11.component.ts file as follows
Click to show the code
import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-master11',
  templateUrl: './master11.component.html',
  styleUrls: ['./master11.component.css']
})
export class Master11Component implements OnInit {
  additionaltitle: string = '';
  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@Master11Component.title-to-translate:Here is a title to translate`,
  };
  constructor() { 
    this.additionaltitle = this.frases['additionaltitle'];
  }
  ngOnInit(): void {
  }
}
  • modify \ang-monorepo\projects\mfe1\src\app\components\md12\master12\master12.component.ts file as follows
Click to show the code
import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-master12',
  templateUrl: './master12.component.html',
  styleUrls: ['./master12.component.css']
})
export class Master12Component implements OnInit {
  additionaltitle: string = '';
  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@Master12Component.title-to-translate:Here is a title to translate`,
  };
  constructor() { 
    this.additionaltitle = this.frases['additionaltitle'];
  }
  ngOnInit(): void {
  }
}
  • modify \ang-monorepo\projects\mfe2\src\app\components\md21\master21\master21.component.ts file as follows
Click to show the code
import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-master21',
  templateUrl: './master21.component.html',
  styleUrls: ['./master21.component.css']
})
export class Master21Component implements OnInit {
  additionaltitle: string = '';
  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@Master21Component.title-to-translate:Here is a title to translate`,
  };
  constructor() { 
    this.additionaltitle = this.frases['additionaltitle'];
  }
  ngOnInit(): void {
  }
}
  • modify \ang-monorepo\projects\shell\src\app\app.component.ts file as follows
Click to show the code
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'shell';

  additionaltitle: string = '';

  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@AppComponent.title-to-translate:Here is a title to translate`,
  };

  constructor() { 
    this.additionaltitle = this.frases['additionaltitle'];
  }

}

modify master component html

  • in the following files
    • \ang-monorepo\projects\shell\src\app\app.component.html
    • \ang-monorepo\projects\mfe1\src\app\components\md11\master11\master11.component.html
    • \ang-monorepo\projects\mfe1\src\app\components\md12\master12\master12.component.html
    • \ang-monorepo\projects\mfe2\src\app\components\md21\master21\master21.component.html
  • we add html as below
<p>{{additionaltitle}}</p>

Cannot find name localize

  • try to start the app with the command
ng serve -o --project mfe2
  • The error will be shown
Error: projects/mfe2/src/app/components/md21/master21/master21.component.ts:13:24 - error TS2304: Cannot find name '$localize'.
13     'additionaltitle': $localize`:Here is a title to translate@@Master21Component.title-to-translate:Here is a title to translate`,
                          ~~~~~~~~~
** Angular Live Development Server is listening on localhost:4202, open your browser on http://localhost:4202/ **
× Failed to compile.

Fixing a localization issue

import '@angular/localize/init';
  • Note: We can start each app but we took lots of exceptions
    • here are a couple of them
Click to show the code
Uncaught Error: Shared module is not available for eager consumption: 7017
    at __webpack_require__.m.<computed> (consumes:148:1)
    at __webpack_require__ (bootstrap:19:1)
    at 9321 (init.mjs:18:1)
    at __webpack_require__ (bootstrap:19:1)
    at 6344 (zone.js:2778:1)
    at __webpack_require__ (bootstrap:19:1)
    at 425 (polyfills.js:12:80)
    at __webpack_require__ (bootstrap:19:1)
    at startup:5:1

core.mjs:6406 
        
       ERROR Error: Uncaught (in promise): Error: It looks like your application or one of its dependencies is using i18n.
Angular 9 introduced a global `$localize()` function that needs to be loaded.
Please run `ng add @angular/localize` from the Angular CLI.
(For non-CLI projects, add `import '@angular/localize/init';` to your `polyfills.ts` file.
For server-side rendering applications add the import to your `main.server.ts` file.)
Error: It looks like your application or one of its dependencies is using i18n.
Angular 9 introduced a global `$localize()` function that needs to be loaded.
Please run `ng add @angular/localize` from the Angular CLI.
(For non-CLI projects, add `import '@angular/localize/init';` to your `polyfills.ts` file.
For server-side rendering applications add the import to your `main.server.ts` file.)
    at _global.$localize (core.mjs:29876:15)
    at new Master11Component (master11.component.ts:12:33)
    at NodeInjectorFactory.Master11Component_Factory [as factory] (master11.component.ts:18:4)
    at getNodeInjectable (core.mjs:3618:44)
    at instantiateRootComponent (core.mjs:12424:23)
    at createRootComponent (core.mjs:13982:23)
    at ComponentFactory.create (core.mjs:22303:25)
    at ViewContainerRef.createComponent (core.mjs:23574:47)
    at RouterOutlet.activateWith (router.mjs:2326:39)
    at ActivateRoutes.activateRoutes (router.mjs:2752:40)
    at resolvePromise (zone.js:1211:31)
    at resolvePromise (zone.js:1165:17)
    at zone.js:1278:17
    at _ZoneDelegate.invokeTask (zone.js:406:31)
    at Object.onInvokeTask (core.mjs:26510:33)
    at _ZoneDelegate.invokeTask (zone.js:405:60)
    at Zone.runTask (zone.js:178:47)
    at drainMicroTaskQueue (zone.js:585:35)
  • our next step is to modify \ang-monorepo\angular.json file for localize.
    • we need to repeat all the steps of the article Modify angular json for our three subprojects.

Prepare angular json

  • open \ang-monorepo\angular.json file and make the following changes

1. In the sections

  • projects:mfe1
  • projects:mfe2
  • projects:shell
  • and json fragment
Click to show the code for projects:mfe1
			"i18n": {
				"sourceLocale": {
					"code": "en",
					"baseHref": ""
				},				
				"locales": {
				  "ru": {
					"translation": "projects/mfe1/src/locale/messages.ru.xlf",
					"baseHref": ""
				  }
				}
			}
Click to show the code for projects:mfe2
			"i18n": {
				"sourceLocale": {
					"code": "en",
					"baseHref": ""
				},				
				"locales": {
				  "ru": {
					"translation": "projects/mfe2/src/locale/messages.ru.xlf",
					"baseHref": ""
				  }
				}
			}
Click to show the code for projects:shell
			"i18n": {
				"sourceLocale": {
					"code": "en",
					"baseHref": ""
				},				
				"locales": {
				  "ru": {
					"translation": "projects/shell/src/locale/messages.ru.xlf",
					"baseHref": ""
				  }
				}
			}
  • Note: messages.ru.xlf file we will create later

2. In the sections

  • projects:mfe1:architect:build:options
  • projects:mfe2:architect:build:options
  • projects:shell:architect:build:options
  • and json fragment
"localize": true,
"aot": true,

3. In the sections

  • projects:mfe1:architect:build:configurations:development
  • projects:mfe2:architect:build:configurations:development
  • projects:shell:architect:build:configurations:development
  • and json fragment
"localize": false,

4. In the sections

  • projects:mfe1:architect:build:configurations
  • projects:mfe2:architect:build:configurations
  • projects:shell:architect:build:configurations
  • and json fragment
            "ru": {
              "localize": ["ru"]
            },
            "en": {
              "localize": ["en"]
            }            

5. In the sections

  • projects:mfe1:architect:serve:configurations
    • and json fragment
Click to show the code
            "ru": {
              "browserTarget": "mfe1:build:development,ru"
            },
            "en": {
              "browserTarget": "mfe1:build:development,en"
            }
  • projects:mfe2:architect:serve:configurations
    • and json fragment
Click to show the code
            "ru": {
              "browserTarget": "mfe2:build:development,ru"
            },
            "en": {
              "browserTarget": "mfe2:build:development,en"
            }
  • projects:shell:architect:serve:configurations
    • and json fragment
Click to show the code
            "ru": {
              "browserTarget": "shell:build:development,ru"
            },
            "en": {
              "browserTarget": "shell:build:development,en"
            }

Run the test

  • run the commands (You need to use three terminals for this)
ng serve -o --project mfe1 --configuration=en
ng serve -o --project mfe2 --configuration=en
ng serve -o --project shell --configuration=en
Click to show the responce
Uncaught SyntaxError: Cannot use 'import.meta' outside a module  styles.js:7831
index.js:551 [webpack-dev-server] Live Reloading enabled.
index.js:551 [webpack-dev-server] Live Reloading enabled.
core.mjs:25867 Angular is running in development mode. Call enableProdMode() to enable production mode.
index.js:551 [webpack-dev-server] Live Reloading enabled.
index.js:551 [webpack-dev-server] Live Reloading enabled.

extract i18n

  • run the commands
ng extract-i18n --project mfe1 --output-path projects/mfe1/src/locale
ng extract-i18n --project mfe2 --output-path projects/mfe2/src/locale
ng extract-i18n --project shell --output-path projects/shell/src/locale

translate i18n

  • install the tool
npm install -g xlf-auto-translate
  • run the commands
xlf-auto-translate -i projects/mfe1/src/locale/messages.xlf -o projects/mfe1/src/locale/messages.ru.xlf -f en -t ru
xlf-auto-translate -i projects/mfe2/src/locale/messages.xlf -o projects/mfe2/src/locale/messages.ru.xlf -f en -t ru
xlf-auto-translate -i projects/shell/src/locale/messages.xlf -o projects/shell/src/locale/messages.ru.xlf -f en -t ru

Run the test for i18n

  • run the commands (You need to use three terminals for this)
ng serve -o --project mfe1 --configuration=ru
ng serve -o --project mfe2 --configuration=ru
ng serve -o --project shell --configuration=ru
  • It works
    • here is a result:
Click to show the picture

project structure

Uncaught SyntaxError: Cannot use 'import.meta' outside a module

Shared lib

Modify Shared service

  • modify the body of the \ang-monorepo\projects\share-lib\src\lib\share-lib.service.ts file as shown below
Click to show the code
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ShareLibService {

  frases: {[key:string]: string}  = {
    'thisIsText': $localize`:This is the text from share servive@@ShareLibService.This-is-the-text:This is the text from share servive`,
  };


  constructor() { }
  public getText(): string {
    return this.frases['thisIsText'];
  }

  protected commonData: string = '';
  public GetCommonData(): string {
    return this.commonData;
  }
  public SetCommonData(s: string): void {
    this.commonData = s;
  }

}

Try to build share lib

  • run the command
ng build --project share-lib
  • we took an error
Click to show the response
PS E:\ang-monorepo> ng build --project share-lib
Building Angular Package
------------------------------------------------------------------------------
Building entry point 'share-lib'
------------------------------------------------------------------------------
✖ Compiling with Angular sources in Ivy partial compilation mode.
projects/share-lib/src/lib/share-lib.service.ts:9:19 - error TS2304: Cannot find name '$localize'.

9     'thisIsText': $localize`:This is the text from share servive@@ShareLibService.This-is-the-text:This is the text from share servive`,
                    ~~~~~~~~~
PS E:\ang-monorepo>
- [ Modify Shared service

Fixing share lib build error

  • we have no polyfills.ts file in the share-lib
    • instead we use public-api.ts.
  • Open the \ang-monorepo\projects\share-lib\src\public-api.ts file and modify as follows
/*
 * Public API Surface of share-lib
 */

import '@angular/localize/init';

export * from './lib/share-lib.service';
export * from './lib/share-lib.component';
export * from './lib/share-lib.module';
  • save and run the command
ng build --project share-lib

Modify AppComponent ts of the shell project

  • modify \ang-monorepo\projects\shell\src\app\app.component.ts as follows
Click to show the code
import { Component } from '@angular/core';
import { ShareLibService } from 'share-lib';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'shell';

  additionaltitle: string = '';

  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@AppComponent.title-to-translate:Here is a title to translate`,
  };

  constructor(protected srv: ShareLibService) { 
    srv.SetCommonData('the string is added in the AppComponent');
    this.additionaltitle = this.frases['additionaltitle'] + ' ::: ' + srv.getText();
  }

}

Modify Master ts of the mfe1 project

modify the \ang-monorepo\projects\mfe1\src\app\components\md11\master11\master11.component.ts file

Click to show the code
import { Component, OnInit } from '@angular/core';
import { ShareLibService } from 'share-lib';

@Component({
  selector: 'app-master11',
  templateUrl: './master11.component.html',
  styleUrls: ['./master11.component.css']
})
export class Master11Component implements OnInit {

  additionaltitle: string = '';
  frases: {[key:string]: string}  = {
    'additionaltitle': $localize`:Here is a title to translate@@Master11Component.title-to-translate:Here is a title to translate`,
  };
  constructor(protected srv: ShareLibService) { 
    this.additionaltitle = this.frases['additionaltitle'] + ' ::: ' + srv.getText() + ' ::: ' + srv.GetCommonData();
  }
  ngOnInit(): void {
  }
}

extract i18n and translate

  • run the commands
ng extract-i18n --project mfe1 --output-path projects/mfe1/src/locale
ng extract-i18n --project mfe2 --output-path projects/mfe2/src/locale
ng extract-i18n --project shell --output-path projects/shell/src/locale

xlf-auto-translate -i projects/mfe1/src/locale/messages.xlf -o projects/mfe1/src/locale/messages.ru.xlf -f en -t ru
xlf-auto-translate -i projects/mfe2/src/locale/messages.xlf -o projects/mfe2/src/locale/messages.ru.xlf -f en -t ru
xlf-auto-translate -i projects/shell/src/locale/messages.xlf -o projects/shell/src/locale/messages.ru.xlf -f en -t ru

Run the test for share lib

  • run the commands
ng serve -o --project mfe1 --configuration=ru
ng serve -o --project mfe2 --configuration=ru
ng serve -o --project shell --configuration=ru
  • navigate to master01
  • it works
    • here is a result
Click to show the picture

project structure

Uncaught SyntaxError: Cannot use 'import.meta' outside a module

Build the projects

Try to build

  • run the command
ng build --project mfe1
  • The following build error will be shown
PS E:\ang-monorepo> ng build --project mfe1   
✔ Browser application bundle generation complete.
✖ Localized bundle generation failed: Cannot assign to read only property 'message' of object 'SyntaxError: import.meta may appear only with 'sourceType: "module"' (1:3681)        
An error occurred inlining file "main.af7a6c95807649d3.js"
PS E:\ang-monorepo> 
  • we are not first

Fix build time error

  • read the article High Level libraries
  • for each project (mfe1, mfe2, shell) we changed the tsconfig.app.json file
    • we replaced "target": "es2020" with "target": "ES2019"
  • all final files are as follows:
Click to show the picture
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "../../out-tsc/app",
    "types": [],
    "target": "ES2019"
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}
  • after that we have no error at build time with the commands
ng build --project mfe1   
ng build --project mfe2
ng build --project shell
  • Note: after replacing "target": "es2020" with "target": "ES2019" apps works in dev mode
    • we mean: apps started with a commands
ng serve -o --project mfe1 --configuration=ru
ng serve -o --project mfe2 --configuration=ru
ng serve -o --project shell --configuration=ru
  • Note: after replacing "target": "es2020" with "target": "ES2019"
Uncaught SyntaxError: Cannot use 'import.meta' outside a module
⚠️ **GitHub.com Fallback** ⚠️