If you want to manage multiple Angular Sub-Projects in one Main Project then Angular Workspace (a.k.a Mono-repo Pattern) is what you are looking for.
What's the use ? π€
You can create multiple projects that share the same workspace instead of having one workspace for each project, that would mean having one
node_modulesfolder across projects.
What are we going to accomplishββ
An important note before we proceed any further, each Angular Application is an individual / independent SPA
Pre-Requisites
- NodeJS
- Angular CLI
- Typescript
β³ Let's get our hands dirty code
Create an Angular application with NO scaffolded files.
ng new main-app --create-application=false
main-app serves as a place holder for other Sub-Projects, without any actual code in it.
What value did --create-application=false add ?
Creating 2 independent Angular application's within the main-app workspace
ng generate application admin-app --routing=false --style=scss
ng generate application ticketing-app --routing=false --style=scss
Creating new library within the main-app workspace :
ng generate library logging-lib
Use
ng generate --helpto know what other option(s) are available.
All application(s) and libraries created inside the workspace will be added under projects folder, by default. Which can be overridden during the creation process :
ng generate application ticketing-app --project-root=custom-proj-root
Below are the changes added to main-app workspace :
-
angular.jsonfile will have 3 project definition(s)-
admin-app&ticketing-appwith "projectType" as application -
logging-libwith "projectType" as library
-
- Main workspace package.json will have new devDependency added
ng-packagr -
tsconfig.jsonwill have new entry paths. \ \ > When we use import statements inside applications likeadmin-apporticketing-app, Angular will look up for requested imports within the application dir then under directories mapped to paths intsconfig.jsonand at-last look up will move tonode_modules
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"paths": {
"logging-lib": [
"dist/logging-lib"
]
}
}
}
With the help of Angular CLI we have added a workspace, a library & 2 Single Page application(s)
Now lets take a look at some important files under projects/logging-lib
main-app
βββ projects/
β βββ logging-lib/
β βββ src/
β β βββ lib/ # (1)
β β β βββ logging-lib.component.ts
β β β βββ logging-lib.module.ts
β β β βββ logging-lib.service.ts
β β βββ public-api.ts # (2)
β βββ ng-package.json # (3)
β βββ package.json # (4)
βββ angular.json
βββ package.json
βββ tsconfig.json
Now let's go into details of some files:
Library Code (1)
This folders contains the code of the library, currently a module, component and service. This is the main and only entry point of our library right now.Public API (2)
The file contains the public API of the library. It exports all members that should be available to the outside world. That's the Angular Module, component and service inside the src/lib/ folder.ng-package.json (3)
The file contains the configuration for ng-packagr. It specifies the path of the build output and the entry file which points to public-api.ts.package.json (4)
This is the package.json of your library (not to be confused with the package.json of our Angular workspace in the root folder). Here you specify the name, version and dependencies of your library.
Our objective of creating library is to use it across application(s)
As the name indicates we shall create a simple logger service & try to use it across application(s)
New library structure after cleaning up :
main-app
βββ projects/
β βββ logging-lib/
β βββ src/
β β βββ lib/
β β β βββ logger.service.ts
β β β βββ logging-lib.module.ts
β β βββ public-api.ts
β βββ ng-package.json
β βββ package.json
βββ angular.json
βββ package.json
βββ tsconfig.json
// File Name : logger.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
constructor() { }
log(value: string) {
console.log(`Logging from Logger Service`);
console.log(value);
}
}
// File Name : public-api.ts
/*
* Public API Surface of logging-lib
*/
export * from './lib/logger-service';
export * from './lib/logging-lib.module';
Lets build logging-lib project, using below command :
ng build logging-lib --watch
If the build is through without any errors, then time to use our library service inside application.
File Structure after library build :
main-app
βββ dist/logging-lib
βββ node_modules/
βββ projects/
βββ angular.json
βββ package.json
βββ tsconfig.json
Now let's make final change to consume our library service inside application
main-app
βββ projects/
β βββ admin-app/
β βββ src/
β β βββ app/
β β β βββ app.component.ts
βββ angular.json
βββ package.json
βββ tsconfig.json
// File Name : app.component.ts
import { Component, OnInit } from '@angular/core';
import { LoggerService } from 'logging-lib';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
title = 'admin-app';
constructor(private loggerService: LoggerService) {}
ngOnInit(): void {
this.loggerService.log(this.title);
}
}
ng serve admin-app
If you are still around, you should see following output in Browser Console :
Key Takeaways π
- Creating Angular Workspace with
Applications&Library - Sharing
Librarycode with otherApplications
If you are thinking of sharing one Application code in another, always use
LibraryorIntegration Applicationfor that.

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.







Top comments (1)
Great post!