Skip to content

Workspace - Use angular library without bundling #19018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
4 of 15 tasks
prabh-62 opened this issue Oct 9, 2020 · 6 comments
Closed
4 of 15 tasks

Workspace - Use angular library without bundling #19018

prabh-62 opened this issue Oct 9, 2020 · 6 comments
Assignees

Comments

@prabh-62
Copy link

prabh-62 commented Oct 9, 2020

🚀 Feature request

Angular CLI shouldn't require angular library to be built before being consumed in an angular application residing in the same angular workspace.

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • xi18n
  • run
  • config
  • help
  • version
  • doc

Description

Current Angular CLI (v11.0.0-next.6) requires that the angular library be built before it can be consumed in angular applications.

Steps

  • > npx @angular/cli@11.0.0-next.6 new agency-apps --strict true --createApplication false
  • > cd agency-apps
  • > yarn ng generate library @agency/auth
  • > yarn ng generate application admin-console --routing true --style css
  • Update projects/admin-console/src/app/app.component.ts
import { Component } from '@angular/core';
import { AuthService } from '@agency/auth';

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

  constructor(private readonly AuthService: AuthService) {
    console.log(this.AuthService);
  }
}
  • > yarn start --project admin-console. Angular CLI will error out since we didn't build library @agency/auth before starting admin-console application

ng_lib_build

Describe the solution you'd like

Angular workspaces should not require developers to build libraries before consuming them. Due to this behaviour, it is required that we, developers put a postinstall script which builds all angular libraries so CI doesn't error out while building angular applications. Ideally, angular libraries in workspace should work just like project references in dotnet ecosystem.

Describe alternatives you've considered

  • Update tsconfig.json from this code snippet
  "compilerOptions": {
    ...
    "paths": {
      "@agency/auth": [
        "dist/agency/auth/agency-auth",
        "dist/agency/auth"
      ]
    }
  }

to

"compilerOptions": {
    ...
    "paths": {
      "@agency/auth": ["projects/agency/auth/src/public-api.ts"]
    }
  }
  • > yarn start --project admin-console

ng_lib_reference

This approach doesn't require angular libraries to be built before consuming them in apps

@alan-agius4
Copy link
Collaborator

Hi @prabh-62,

There are some downsides to the above and for correctness sake we don't recommend that approach.

  • The library will need to be recompiled every-time you build the application.
  • The library and application uses 2 different pipelines, which in some cases might result in a different JS output when having the same input. Therefore when you include the library as part of the application sources via paths you might end up with a different behaviour.

This is also briefly mentioned at the end of our library guide: https://angular.io/guide/creating-libraries

The CLI build command uses a different builder and invokes a different build tool for libraries than it does for applications.

The build system for apps, @angular-devkit/build-angular, is based on webpack, and is included in all new Angular CLI projects.
The build system for libraries is based on ng-packagr. It is only added to your dependencies when you add a library using ng generate library my-lib.
The two build systems support different things, and even where they support the same things, they do those things differently. This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.

For this reason, an app that depends on a library should only use TypeScript path mappings that point to the built library. TypeScript path mappings should not point to the library source .ts files.

I do agree that we should provide a way to build a project and all it's dependencies. This is currently being tracked here: #11002

@prabh-62
Copy link
Author

prabh-62 commented Oct 9, 2020

Downsides

The library will need to be recompiled every-time you build the application.

  • That's true, I am fine with 1-2 additional seconds of compilation. If it takes 10 secs without library build, then 11 secs doesn't sound much overhead

The library and application uses 2 different pipelines, which in some cases might result in a different JS output when having the same input. Therefore when you include the library as part of the application sources via paths you might end up with a different behaviour.

  • I understand, that using paths is not the recommended approach however I never had any issues for last 6 months. We try not to reference any globals in our libraries and things just work

We use a monorepo for 10 different angular applications and we have few angular libraries that are referenced in each app

  • library for handling authentication
  • library for core infrastructure logic (global error handler, http correlation interceptor, etc)
  • library for common angular components

If we have to start 3 libraries in watch mode(on 3 different processes), it requires much more machine resources as well and there are more chances that one of the processes might crash and a dev would have to restart process or investigate.

Also, in the CI, we will need to build libraries first by invoking prebuild scripts and this becomes more maintenance overhead.

Not to forget debugging (this is the biggest issue), building libraries in separate processes prevents us from debugging and fixing code right in the ts file. (Debugger takes us to compiled javascript code)

Also, some developers could make the mistake of editing the library code, but forgetting to build the library, and then scratching their heads.

You may close this issue if #11002 closely resembles this issue

@alan-agius4
Copy link
Collaborator

Let me bring this up the rest of the team and see if we still stand by the decision that we favor correctness.

With regards to debugging, this should improve in version 11 as we added DTS sourcemaps for libraries, which allows go to def to jump to source directly. Also, you might not be enabling the vendor sourcemaps option.

"build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "sourceMap": {
      "styles": true,
      "scripts": true,
      "vendor": true
    },

@alan-agius4 alan-agius4 added the needs: discussion On the agenda for team meeting to determine next steps label Oct 12, 2020
@prabh-62
Copy link
Author

Agreed we can do "vendor": true but then we should only do it for libs inside the workspace.(#11305 (comment) )

The intent is to treat library code as part of the workspace and make code changes/fixes quickly and without any friction

@alan-agius4 alan-agius4 self-assigned this Oct 15, 2020
@alan-agius4
Copy link
Collaborator

Hi @prabh-62,

I'd like to thank you for all the input provided. We have discussed this during our team meeting and we mentioned some points:

  • Libraries in Angular are not the same as projects in .NET and don't share the same purpose. The main purpose of an Angular library is code reusability/sharing between multiple projects. In many cases unless you have multiple applications in a mono repo using the same library or you intend to publish the library on NPM, creating a library is an unnecessary overhead. If you are creating a library for the sole purpose of code organisation/domain cutting, we feel that create a feature folder under the application is a better alternative.
  • If in a mono-repo the library is consumed by multiple applications, when using path mappings this will need to be built by every consuming application.
  • A library can have different TypeScript configuration settings from that of the application, so again building this as part of the application may result in different build time experience such as not all compilation errors being reported.
  • Having ng build that builds projects based on the dependency graph is a better fit, therefore we shall continue tracking this in: Add option to exclude certain files from sourcemap. #11305
  • One can still do the change and reference the path mappings manually, but this is not something that we recommend, and therefore we shall not add this to our schematics.

@alan-agius4 alan-agius4 removed the needs: discussion On the agenda for team meeting to determine next steps label Oct 16, 2020
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants