Search code examples
angularshared-librariesangular-clilibrariesworkspace

Angular Library outside the Angular Cli Workspace


Is it possible to have a library outside the workspace of angular cli?

Traditional scheme:

my-workspace/
  ...             (workspace-wide config files)
  projects/       (generated applications and libraries)
    my-first-app/ --(an explicitly generated application)
      ...         --(application-specific config)
      e2e/        ----(corresponding e2e tests)
         src/     ----(e2e tests source)
         ...      ----(e2e-specific config)
      src/        --(source and support files for application)
    my-lib/       --(a generated library)
      ...         --(library-specific config)
      src/        --source and support files for library)

Now, I have a library: my-lib2 that reside in another directory, not inside the projects directory. I put the configuration of my-lib2 in angular.json file of my-workspace, with relative path, but, when I compile this: ng build my-lib2, inside the workspace, I have this errors:

Building Angular Package

** It is not recommended to publish Ivy libraries to NPM repositories **

------------------------------------------------------------------------------
Building entry point 'my-lib2'
------------------------------------------------------------------------------
Compiling TypeScript sources through ngc
ERROR: ../my-lib2/src/lib/my-lib2.component.ts(1,35): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.module.ts(1,26): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.service.ts(1,28): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.service.ts(3,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.

An unhandled exception occurred: ../my-lib2/src/lib/my-lib2.component.ts(1,35): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.module.ts(1,26): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.service.ts(1,28): error TS2307: Cannot find module '@angular/core'.
../my-lib2/src/lib/my-lib2.service.ts(3,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.

See "/tmp/ng-bt10hE/angular-errors.log" for further details.

Schema

my-lib2/       
      ...         
      src/


my-workspace/
  ...             
  projects/       
    my-first-app/ 
      ...         
      e2e/        
         src/     
         ...      
      src/        
    my-lib/       
      ...         
      src/ 

Configuration of angular.json inside of workspace:

...
   ...
   "my-lib2": {
      "projectType": "library",
      "root": "projects/../../my-lib2/",
      "sourceRoot": "projects/../../my-lib2/src",
      "prefix": "lib",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": {
            "tsConfig": "projects/../../my-lib2/tsconfig.lib.json",
            "project": "projects/../../my-lib2/ng-package.json"
          },
          "configurations": {
            "production": {
              "tsConfig": "projects/../../my-lib2/tsconfig.lib.prod.json"
            }
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "projects/../../my-lib2/src/test.ts",
            "tsConfig": "projects/../../my-lib2/tsconfig.spec.json",
            "karmaConfig": "projects/../../my-lib2/karma.conf.js"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "projects/../../my-lib2/tsconfig.lib.json",
              "projects/../../my-lib2/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }},
    ...
    ...

tsconfig.lib.ts (configuration file of my-lib2)

{
  "extends": "../my-workspace/tsconfig.json",
  "compilerOptions": {
    "outDir": "../my-workspace/out-tsc/lib",
    "target": "es2015",
    "declaration": true,
    "inlineSources": true,
    "types": [],
    "lib": [
      "dom",
      "es2018"
    ]
  },
  "angularCompilerOptions": {
    "skipTemplateCodegen": true,
    "strictMetadataEmit": true,
    "enableResourceInlining": true
  },
  "exclude": [
    "src/test.ts",
    "**/*.spec.ts"
  ]
}

As can be seen, all paths are relative ...

Any idea how I can configure the entries in angular.json of the workspace to take the library out of the projects path?


Solution

  • The solution was the correct configuration of the tsconfig.lib.ts file of the library.

    Schema of directory:

    my-lib2/       
          ...         
          src/
    
    
    my-workspace/
      ...             
      projects/       
        my-first-app/ 
          ...         
          e2e/        
             src/     
             ...      
          src/        
        my-lib/       
          ...         
          src/ 
    

    my-lib2 entry in the angular.json file in the workspace:

    "my-lib2": {
          "projectType": "library",
          "root": "../my-lib2",
          "sourceRoot": "../my-lib2/src",
          "prefix": "lib",
          "architect": {
            "build": {
              "builder": "@angular-devkit/build-ng-packagr:build",
              "options": {
                "tsConfig": "../my-lib2/tsconfig.lib.json",
                "project": "../my-lib2/ng-package.json"
              },
              "configurations": {
                "production": {
                  "tsConfig": "../my-lib2/tsconfig.lib.prod.json"
                }
              }
            },
            "test": {
              "builder": "@angular-devkit/build-angular:karma",
              "options": {
                "main": "../my-lib2/src/test.ts",
                "tsConfig": "../my-lib2/tsconfig.spec.json",
                "karmaConfig": "../my-lib2/karma.conf.js"
              }
            },
            "lint": {
              "builder": "@angular-devkit/build-angular:tslint",
              "options": {
                "tsConfig": [
                  "../my-lib2/tsconfig.lib.json",
                  "../my-lib2/tsconfig.spec.json"
                ],
                "exclude": [
                  "**/node_modules/**"
                ]
              }
            }
          }
        }},
    

    tsconfig.lib.ts file configuration in my-lib2 directory:

    {
      "extends": "../my-workspace/tsconfig.json",
      "compilerOptions": {
        "outDir": "../my-workspace/out-tsc/lib",
        "target": "es2015",
        "declaration": true,
        "inlineSources": true,
        "types": [],
        "lib": [
          "dom",
          "es2018"
        ],
        "baseUrl": "../my-workspace/",
        "paths": {
          "*": ["../my-workspace/node_modules/*"]
        }
      },
      "angularCompilerOptions": {
        "skipTemplateCodegen": true,
        "strictMetadataEmit": true,
        "enableResourceInlining": true
      },
      "exclude": [
        "src/test.ts",
        "**/*.spec.ts"
      ]
    }
    

    This is the important part in the configuration:

     ...
     "baseUrl": "../my-workspace/",
     "paths": {
           "*": ["../my-workspace/node_modules/*"]
     }
     ...
    

    Run compilation:

    Building Angular Package
    
    ** It is not recommended to publish Ivy libraries to NPM repositories **
    
    ------------------------------------------------------------------------------
    Building entry point 'my-lib2'
    ------------------------------------------------------------------------------
    Compiling TypeScript sources through ngc
    Bundling to FESM2015
    Bundling to FESM5
    Bundling to UMD
    Minifying UMD bundle
    Copying declaration files
    Writing package metadata
    Built my-lib2
    
    ------------------------------------------------------------------------------
    Built Angular Package!
     - from: /home/usuario/my-project/my-lib2
     - to:   /home/usuario/my-project/my-workspace/dist/my-lib2
    ------------------------------------------------------------------------------