问题
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:
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 in files
option of your ts configs:
tsconfig.browser.json
tsconfig.server.json
tsconfig.server.aot.json
"files": [
"./node_modules/@angular-universal-serverless/external-module/release/src/externalComponent/external.module.d.ts"
],
"include": [
"./src/main.browser.ts",
"./src/app/lazy/lazy.module.ts",
"./src/app/httpProxy/http-proxy.module.ts"
]
We can't add it to includes
array because typescript will exclude it
Files included using "include" can be filtered using the "exclude" property
See more details in the doc
2) Then
\node_modules\@angular-universal-serverless\external-module\release\package.json should has typings
field like:
"name": "@angular-universal-serverless/external-module",
"main": "./src/index.js",
"typings": "./src/externalComponent/external.module.d.ts", <=== this one
We have to use external.module.d.ts
because angular doesn't create ngfactory
file for index.d.ts
while @ngtools/webpack plugin creates map for ContextElementDependency:
const factoryPath = lazyRoute.replace(/(\.d)?\.ts$/, '.ngfactory.ts');
// where lazyRoute === .../external-module/release/src/externalComponent/external.module.d.ts
const lr = path.relative(this.basePath, factoryPath);
this._lazyRoutes[k + '.ngfactory'] = path.join(this.genDir, lr);
If you don't want to change package.json
then change loadChildren
field:
{
path: 'external',
loadChildren: '@angular-universal-serverless/external-module/release/src/externalComponent/external.module#ExternalModule'
}
回答2:
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 from node_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
来源:https://stackoverflow.com/questions/46774625/aot-compiler-include-lazy-loaded-external-module