Angular Module vs. Library vs. Application vs. Workspace

Last modified: March 10, 2019

The Angular CLI is a powerful tool for quickly generating Angular projects. Using the CLI, you can quickly generate components, services, directives etc. from the command line. The CLI also provides convenient commands for building, testing, and deploying your Angular apps.

With the release of Angular 6, the CLI introduced the concept of a workspace. A workspace is a collection of projects. These projects can be classified as either a "library" or an "application"....

But wait...doesn't the Angular CLI always generate applications? What makes a workspace different from an application? How is a library different from an application? Isn't an application just a module?

These are the questions many developers ask themselves when exploring the more recent versions of Angular CLI. Let's answer these questions in more detail....

What is an Angular workspace?

Angular 6 introduced the concept of a workspace. A workspace is really just a collection of different projects. The ng new command creates a new workspace...

ng new myworkspace

This will create a new workspace named myworkspace.

A WORKSPACE IS NOT AN APPLICATION

By default, ng new generates an application at the root of the workspace under the src/ folder.

This causes many to assume a workspace is an application. This is not the case! If you run...

ng new myworkspace --create-application=false

this will generate a new workspace without the src/ folder. By specifying --create-application=false, Angular CLI omits this default application from being generated.

So what's the point? Why would you generate a workspace that you can't deploy via some standalone application?

The concept of a workspace is really just an organizational thing. A workspace allows for multiple projects to be defined under a single angular.json configuration...

Why multiple projects? The Angular team realized that sometimes components, services, etc. can apply to multiple applications. To more easily share code across different apps, the concept of an Angular library was born...

What is an Angular Library?

A library is a collection of components, services, directives etc. that can be shared across different Angular projects.

You generate a new library just like you would a component, service or anything else:

ng g library mylibrary

This will generate a new library mylibrary under the projects folder of your workspace.

FYI, if we wanted to create an application, we could also run:

ng g application myapp

This will generate a new application mylibrary under THE SAME projects folder of your workspace.

Angular Library vs Application

Unlike an application, a library doesn't generate index.html, styles.css, polyfills.ts, main.ts. These files are specific to deploying an application in the browser. Since a library is simply a collection of reusable components, it doesn't need these files.

Additionally, a library generates a few files that an application doesn't. Let's look at these in more detail...

public_api.ts

This is the main entry file for your library. It defines what parts of the library are visible externally.

Whenever you add a new component, service, etc. to your library, you also want to add it to this file so it can be exported at the class level. While exporting a new component in your library's .module.ts file will make it visible externally, adding to this file makes it possible to reference the class instance itself like..

myLibComponent: MyLibComponent;

ng-package.json

This file is the configuration for ng-packagr, a library for packaging Angular projects into a distribution-ready npm package. The Angular CLI utilizes ng-packagr for packaging and publishing your library as an npm package.

package.json

This file is specific to your library and represents the package.json file that will be included with your packaged library. This file tells ng-packagr what dependencies should be included with the package.json file for the packaged library.

Understanding the difference - angular.json

Remember that a workspace generates a single angular.json file. When you add either applications or libraries, their configuration gets added to the projects section of this file.

If you generate both a library and an application, you can compare the differences in their configurations. You'll notice an application has a lot more configuration for browser specific properties like index file location etc.

If you check out the architect' section for a library, you'll notice a build step definition that looks something like this...


"build": {
  "builder": "@angular-devkit/build-ng-packagr:build",
  "options": {
    "tsConfig": "projects/mylib/tsconfig.lib.json",
    "project": "projects/mylib/ng-package.json"
  }
},

Conversely, an application's build step looks something like this...


"build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "outputPath": "dist/myapp",
    "index": "projects/myapp/src/index.html",
    "main": "projects/myapp/src/main.ts",
    "polyfills": "projects/myapp/src/polyfills.ts",
    "tsConfig": "projects/myapp/tsconfig.app.json",
    "assets": [
      "projects/myapp/src/favicon.ico",
      "projects/myapp/src/assets"
    ],
    .
    .
    .

Look specifically at the "builder" attribute for these


//mylib
"builder": "@angular-devkit/build-ng-packagr:build",

//myapp
"builder": "@angular-devkit/build-angular:browser",

This points to the major difference between a library and an application. While applications build projects for the browser, libraries build projects with ng-packagr, making them reusable across projects.

It should be mentioned that simply building a library does not make it package ready. Running ng build on a library builds the project and compiles the output to a the dist/ folder.

To actually package the library, you would run something like this...

ng build my-lib
cd dist/my-lib
npm publish

What is an Angular Module?

You'll probably notice that both libraries and applications generate a @NgModule class defined in .module.ts file.

So what's the difference? Are both considered modules? What IS a module in Angular exactly?

A module is simply a way of organizing pieces of functionality together. While libraries and apps have their differences, they both represent collections of components, services, directives. A module is simply a way of defining how these elements work both internally and externally.

Modules both import and export functionality.

So why not just import modules to share functionality across apps? Why the need for libraries in the first place?

You aren't wrong by saying you can use modules to share components across projects.

Libraries just make this easier and more convenient, especially for packaging projects as "publishable" packages.

Also remember the KEY difference that a library also exposes functionality at the class level as per the public_api.ts file. To use a regular Angular application in the same way, you would manually need to define exports in a .ts file so external modules can reference the class object.

Wrapping up...

Understanding that a workspace is a collection of projects makes working with the CLI a lot easier. Since a workspace may have any combination of libraries/apps defined in the projects/ folder, it's important to specify projects when generating components, services, directives etc from the command line...

ng g c --project myapp
ng g c --project mylib

By specifying the --project option, you tell the CLI which project to generate a new component for.

Conclusion

A workspace is a collection of projects. Projects can be either libraries or applications.

Both libraries and applications are modules a the end of the day. Their main difference is how they are built and deployed. A library can be packaged and published for easier reuse across projects. An application includes browser specific files for deploying and running in the browser.

For more information, check out Todd Palmer's amazing series on creating Angular libraries.

You might also like: