Repository navigation
Lazy loading module from library package located in node_modules fails to build. #6373
Copy link
Copy link
Closed
Closed
Copy link
Milestone
Description
Bug Report or Feature Request (mark with an x)
- [x] bug report -> please search issues before submitting
- [ ] feature request
Versions.
@angular/cli: 1.0.4
node: 6.10.2
os: win32 x64
@angular/cli: 1.0.4
@angular/common: 4.1.3
@angular/compiler: 4.1.3
@angular/core: 4.1.3
@angular/forms: 4.1.3
@angular/http: 4.1.3
@angular/platform-browser: 4.1.3
@angular/platform-browser-dynamic: 4.1.3
@angular/router: 4.1.3
@angular/compiler-cli: 4.1.3
Repro steps.
I've modified the quick start library from @filipesilva and copied the output folder to my node_modules/quickstart-lib directory.
Modification includes a routing module to add a child route.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LibComponent } from './component/lib.component';
const childRoutes: Routes = [
{
path: '',
component: LibComponent
}
];
@NgModule({
imports: [
RouterModule.forChild(childRoutes)
],
exports: [
RouterModule
]
})
export class LibRoutingModule { }
which is then imported into the main LibModule file.
import { NgModule } from '@angular/core';
import { LibRoutingModule } from './lib-routing.module';
import { LibComponent } from './component/lib.component';
import { LibService } from './service/lib.service';
@NgModule({
declarations: [LibComponent],
imports: [LibRoutingModule],
providers: [LibService],
exports: [LibComponent]
})
export class LibModule { }
In my host application, I created a simple route to lazy load the module from the library
const routes: Routes = [
{
path: 'quickstart',
loadChildren: 'quickstart-lib#LibModule'
},
{
path: 'preferences',
loadChildren: 'app/preferences#PreferencesModule'
},
...HomeRoutes
];
The log given by the failure.
PS C:\Workspace\scratch\Ng4Starter\host> ng serve
** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200 **
11% building modules 14/23 modules 9 active ...gular\platform-browser-dynamic.es5.js(node:19124) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic,
see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
11% building modules 15/23 modules 8 active ...gular\platform-browser-dynamic.es5.js(node:19124) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic,
see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
Hash: c46342c7aafb5ce0f53e
Time: 14214ms
chunk {0} 0.chunk.js, 0.chunk.js.map 20.5 kB {3} [rendered]
chunk {1} 1.chunk.js, 1.chunk.js.map 793 bytes {0} {3} [rendered]
chunk {2} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 157 kB {7} [initial] [rendered]
chunk {3} main.bundle.js, main.bundle.js.map (main) 72.5 kB {6} [initial] [rendered]
chunk {4} styles.bundle.js, styles.bundle.js.map (styles) 229 kB {7} [initial] [rendered]
chunk {5} scripts.bundle.js, scripts.bundle.js.map (scripts) 162 kB {7} [initial] [rendered]
chunk {6} vendor.bundle.js, vendor.bundle.js.map (vendor) 3.36 MB [initial] [rendered]
chunk {7} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered]
ERROR in ./~/quickstart-lib/quickstart-lib.d.ts
Module build failed: Error: Debug Failure. False expression: Output generation failed:=>C:/Workspace/scratch/Ng4Starter/host/node_modules/quickstart-lib/quickstart-lib.d.ts
at Object.assert (C:\Workspace\scratch\Ng4Starter\host\node_modules\typescript\lib\typescript.js:3259:23)
at Object.transpileModule (C:\Workspace\scratch\Ng4Starter\host\node_modules\typescript\lib\typescript.js:76181:18)
at TypeScriptFileRefactor.transpile (C:\Workspace\scratch\Ng4Starter\host\node_modules\@ngtools\webpack\src\refactor.js:161:27)
at Promise.resolve.then.then.then.then (C:\Workspace\scratch\Ng4Starter\host\node_modules\@ngtools\webpack\src\loader.js:361:37)
at process._tickCallback (internal/process/next_tick.js:109:7)
@ ./src async
@ ./~/@angular/core/@angular/core.es5.js
@ ./src/main.ts
@ multi webpack-dev-server/client?http://localhost:4200 ./src/main.ts
webpack: Failed to compile.
Desired functionality.
I would like to distribute my code as an NPM library and have the CLI support lazy loading the module that is located in the 'node_modules' directory.
Modules located in the same application directory are lazy loaded just fine.
Mention any other details that might be useful.
Reactions are currently unavailable
Activity
[-]Lazy loading module from library package located in node_modules fails.[/-][+]Lazy loading module from library package located in node_modules fails to build.[/+]mdewaelebe commentedon May 19, 2017
I'm having the same issue with version:
Hopefully this can be fixed soon, I'll continue by using --no-aot for the moment.
thekhoi commentedon May 19, 2017
@mdewaelebe doesn't the CLI default to JIT? This error happens for me even if I use --aot false. I don't see a --no-aot option.
mdewaelebe commentedon May 22, 2017
@thekhoi I tried the approach described in #5153.
It seems you're right, the --no-aot option is not found anywhere, but it does the trick for me.
I did no further investigation on why or how this works.
thekhoi commentedon May 25, 2017
@mdewaelebe I think that is a different issue. I get the same error for a lazy route that happens to be local to my project directory or not.
thekhoi commentedon May 30, 2017
I was able to track down the issue. It appears that the AoT plugin discovers lazy routes and passes them to the angular compiler language service to resolve the file name of a given route string. Assuming your library is following the angular package format, this resolves to a definition file, e.g. c:...\node_modules\lib-name\lib-name.d.ts.
The file @ngtools\webpack\src\loader.js then uses this path to transpile the source code to es2015 which fails. I modified this file to check for the *.d.ts extension. If there is a match I just use the contents of the pre-compiled .js and .map files for the library. This lets me get past the compilation error in the CLI and when watching the network traffic, I can see the module is loaded on demand.
However, this is another hickup, the library is already bundled in the vendor.js file since the webpack configuration simply bundles everything in the node_modules directory into a the vendors file.
The only way to get around this, is to eject out of the CLI to exclude the library from the common vendor chunk.
All these fixes seem to be a hack, hopefully the cli team can come up with something more elegant.
fix(@angular/cli): Lazy loading module from library package located i…
filipesilva commentedon Jun 26, 2017
#6755 contains a nice repro of this issue.
Chabane commentedon Jul 20, 2017
Hello @filipesilva, I have the same issue. Is there any news about a workaround?
Thanks,
@angular/cli@1.1.0
typescript@~2.3.3
81 remaining items
alan-agius4 commentedon Jan 10, 2019
Hi all,
This thread was opened a while ago. Having so comments makes it hard for people to find information in anything but the latest comments. But on the other hand I don't think most people would go through all of the comments anyway. New users that see this thread mostly read the first and latest comments and lose things said in between.
So for the reasons stated above (high volume of comments, hidden comments, hard to report and inform people) I'm locking this issue to prevent this comment from being lost as new comments come in.
Thank you to everyone that reported and helped diagnose the problems and provided workarounds.
Our recommended approach to lazy load a library within an angular workspace or node modules, is to use a proxy/wrapper module. With this approach lazy loading will works in both JIT and AOT mode. There are other solutions that work solely in AOT mode such as tsconfig
importshowever for a better development experience we don't encourage this.Below find an example of the recommended approach;
lazy/lazy.module.ts
app.module.ts
alan-agius4 commentedon Sep 19, 2019
Hi all,
I am going to close this as following a convo with @alxhub. Lazy loading should happen at an application and not a library level. Hence the above approach is the recommended and the supported way to lazy load a library module in your application.
Related to: angular/angular#31893 (comment)