I am trying to include external module (hosted in git/npm repository) as lazy-loaded module in my Angular application.
I am compiling my external module with ngc compiler:
node_modules/.bin/ngc -p tsconfig-aot.json
This is how my compiler config looks:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"baseUrl": "src",
"declaration": true,
"outDir": "./release/src"
},
"files": [
"./src/index.ts"
],
"angularCompilerOptions": {
"genDir": "release",
"skipTemplateCodegen": true,
"entryModule": "index#ExternalModule",
"skipMetadataEmit": false,
"strictMetadataEmit": true
}
}
And in my main app I am lazy loading given module:
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full'},
{ path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule'},
{ path: 'external', loadChildren: '@angular-universal-serverless/external-module/release#ExternalModule'}
])
For compilation purposes I am using @ngtools/webpack plugin.
The JIT compilation works without any problems, but AOT compilation gives me error:
ERROR in ./src/ngfactory lazy
Module not found: Error: Can't resolve '/path/to/my/project/angular-universal-serverless/src/ngfactory/node_modules/@angular-universal-serverless/external-module/release/src/index.js' in '/Users/mtreder/Documents/private/work/angular-universal-serverless/src/ngfactory'
@ ./src/ngfactory lazy
@ ./~/@angular/core/@angular/core.es5.js
@ ./src/main.server.aot.ts
So I decided to check what is the output from ngc
compiler (whic is called under the hood by the webpack plugin):
node_modules/.bin/ngc -p tsconfig.server.aot.json
And in fact, my module is missing in the /path/to/my/project/angular-universal-serverless/src/ngfactory/node_modules
catalog.
ls src/ngfactory/node_modules/
@angular @nguniversal @types idb ng-http-sw-proxy rxjs typescript-collections
How can I force ngc to place given modules in the ngfactory
output directory?
My main application can be found here: https://github.com/maciejtreder/angular-universal-serverless/tree/externalModule
And external module here: https://github.com/maciejtreder/angular-external-module
1) The first problem here is that AOT compiler doesn't compile your module(
node_modules
folder is excluded by default), so you have to include it infiles
option of your ts configs:tsconfig.browser.json
tsconfig.server.json
tsconfig.server.aot.json
We can't add it to
includes
array because typescript will exclude itSee more details in the doc
2) Then \node_modules\@angular-universal-serverless\external-module\release\package.json should has
typings
field like:We have to use
external.module.d.ts
because angular doesn't createngfactory
file forindex.d.ts
while @ngtools/webpack plugin creates map for ContextElementDependency:If you don't want to change
package.json
then changeloadChildren
field:maybe it's too late, but I hope this could help someone.
I wrote a very simple node script to be run right after
npm install
. It is indeed a post install script. It copies source files fromnode_modules
into a folder under the main project. It then updates references to lazy loaded modules in the main routes file.It worked perfectly for my team and we increased app performances very much.
The script is short and well documented, please check it out
https://gist.github.com/insanediv/8b4ebba06824a3eb8233e10287a1cdcd