Kurtis Jungersen
Kurtis Jungersen

Reputation: 2564

How can you structure an Angular library to have multiple import paths (like @angular/material), and what is the benefit of doing so?

When importing various modules from @angular/material each module is imported from a different package path, using the format of @organization/library/<module>, e.g.:

import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';

Questions:

  1. How can this be accomplished in a library?

    I have a similar folder structure with a directory for each module and its subsequent components/services/directives, and a public-api.ts exporting each of those members, but then a public-api.ts at the root level barrel exports everything. Then in the consuming applications, each module is imported:

import { FooModule, BarModule } from '@my-org/my-lib'

// instead of

import { FooModule } from '@my-org/my-lib/foo'
import { BarModule } from '@my-org/my-lib/bar'
  1. What is the benefit of doing this rather than just exporting all members from the root @my-org/my-lib path (if any)?

Upvotes: 5

Views: 2085

Answers (1)

Kurtis Jungersen
Kurtis Jungersen

Reputation: 2564

Secondary Entry Points

After some research, I found this can be accomplished using a concept called Secondary Entry Points. This is what the Angular team utilizes for the @angular/core and @angular/material libraries.

To answer my previous questions:

  1. Secondary Entry Points provide multiple smaller bundles within the library, allowing each entry point to be loaded individually rather than the library as a whole. Unique dependencies can be specified for each entry point as well, acting as a "mini-library" in essence, while still being distributed as part of a larger library.

  2. Smaller bundle sizes are the largest / most apparent benefit of doing this by better utilizing Angular's tree shaking of dependencies.

  • E.g. most users are only using a small subset of the @angular/material UI components, and by only importing the modules necessary for those UI components the styling / logic for other components don't need to be unnecessarily included in the final bundle for the app.
  • Additionally, you are only including dependencies for the selected entry points. So other [unneeded] dependencies aren't included in the final bundle for the app.

From the linked source below:

"Subentries offer us an excellent way to deliver our library in multiple chunks. Those chunks are tree shakeable during Angular's build optimization. With this approach, even wrongly packaged third party libraries only get included in the final bundle if they are used."

Source:

This Angular In Depth Article provides a thorough explanation of how to implement this in an Angular library and the benefits of doing so.

Upvotes: 5

Related Questions