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_modules
folder across projects.
What are we going to accomplishββ
An important note before we proceed any further, each Angular Application is an individual / independent SPA.
That means admin-app
/ ticketing-app
should be build & deployed as separate applications. In local, ng serve admin-app
/ ng serve ticketing-app
should be used.
Pre-Requisites
- NodeJS
- Angular CLI
- Typescript
β³ Let's get our hands dirty code
Creating an empty workspace
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 ?
If
ng new main-app
is used, thesrc
folder contains the source code for default app. Andangular.json
contains a property calleddefaultProject
to customize our default project.
Creating application(s)
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 library
Creating new library within the main-app
workspace :
ng generate library logging-lib
Use
ng generate --help
to 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.json
file will have 3 project definition(s)-
admin-app
&ticketing-app
with "projectType" as application -
logging-lib
with "projectType" as library
-
- Main workspace package.json will have new devDependency added
ng-packagr
-
tsconfig.json
will have new entry paths, pointing to dist or build destination of library .
When we import an entity (component / service) from
library
, here it islogging-lib
, inside applications likeadmin-app
orticketing-app
, Angular will look up for requested imports within the application dir if not found then will look into build destination mapped to paths intsconfig.json
{
"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 is to create library
& 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, we can use our library
service inside application(s).
File Structure after library build
:
main-app
βββ dist/logging-lib
βββ node_modules/
βββ projects/
βββ angular.json
βββ package.json
βββ tsconfig.json
One super helpful command that i found in Angular CLI is to use generate
command with --dry-run
flag.
ng generate component <path-to-create-component> --project admin-app --dry-run
ng generate service <path-to-create-service> --project logging-lib --dry-run
--dry-run flag will not make any changes to file structure but will show where the new generated files are going to be added.
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
Library
code with otherApplications
If you are thinking of sharing one Application code in another, always use
Library
orIntegration Application
for that.
Top comments (5)
Awesome post will use this project implementation on a project i have in mind
Thanks. This is my first attempt, was the post easy to understand ?
Definitely easy for me. I'm well versed in Angular, I just didn't think of this type of file structure
We have an Angular workspace with two apps, one being main-app and the other app2, along with two libraries defined in it. Now, we want to use app2 inside main-app. My first question is, how can we do this? The second question is, how can we, for example, deliver only app2 to the client without having to build the entire code?