x)- [X] bug report -> please search issues before submitting
- [ ] feature request
- [X] devkit
- [ ] schematics
node v8.11.2
npm version 5.6.0 (tho I use yarn 1.7.0)
MacOS High Sierra
Repro case with instructions here:
https://github.com/wiltzius/ng-toolkit/tree/angular_and_webpack_demystified_step3
app.js:861 Uncaught Error: No NgModule metadata found for 'class{}'.
at e.resolve (app.js:861)
at e.getNgModuleMetadata (app.js:839)
at e._loadModules (app.js:1065)
at e._compileModuleAndComponents (app.js:1065)
at e.compileModuleAsync (app.js:1065)
at e.compileModuleAsync (app.js:1365)
at e.bootstrapModule (app.js:220)
at Module.
at n (app.js:1)
at app.js:1
The @ngtools/webpack plugin doesn't produce any runtime errors?
This is roughly the same issue that's described in issue #8798 however that issue has a lot of different complaints in it and has been closed, so I thought it would be cleaner as a new one.
You wrote in your tsconfig.json
"angularCompilerOptions": {
"mainPath": "./app/main.ts"
}
I could be wrong but seems there is no such option here. Anyway your path is incorrect. It should be ./src/main.ts
If you open webpack.config.json you can specify mainPath there.
new AngularCompilerPlugin({
tsConfigPath: './tsconfig.json',
mainPath: './src/main.ts', <==== this line
sourceMap: true
})
Also you should inject your scripts in body instead of head when use HtmlWebpackPlugin otherwise angular won't find my-app element when bootstrapping app.
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
output: __dirname + '/dist',
inject: 'body' <=== this line
}),
Another way to solve your issue is use angularCompilerOptions.entryModule option like:
"angularCompilerOptions": {
"entryModule": "src/app/app.module#AppModule"
}
Ah, yes I see -- the angularCompilerOptions are not the same as the AngularCompilerPlugin options, and the mainPath can only be set in the latter not in the former. That does indeed explain it, thank you for the help! Sorry this wasn't a real bug.
Hmm, I think there's still something going on here that doesn't quite work. The minimal test case I originally came up with did indeed have the problems you pointed out, thank you. We're still having trouble in our real app trying to use AngularCompilerPlugin.
It seems related to the fact that it's a hybrid AngularJS and Angular 6 app. Here's another repro, slightly more complicated than the original but incorporating the fixes that you originally pointed out:
https://github.com/wiltzius/ng-toolkit/tree/example-breakage-2
I've tried both the entryModule approach and the mainPath approach but they both seem to have the same problem.
Is there some specific way that AngularCompilerPlugin needs to be set up to work with a hybrid AngularJS + Angular app?
Thank you again.
@wiltzius Hey again
You should go through the following steps:
1) Open webpack.config.js
https://github.com/wiltzius/ng-toolkit/blob/5785dfa4fd61faaa7da3b745c80f1ddc910a1f4a/webpack.config.js#L38
2) Replace './src/app/app.module.ts#AppModule' with './src/app/app.module#AppModule'
Note i removed .ts
3) Open main.ts
https://github.com/wiltzius/ng-toolkit/blob/5785dfa4fd61faaa7da3b745c80f1ddc910a1f4a/src/main.ts#L16-L17
4) Replace
const platformRef = platformBrowserDynamic();
return platformRef.bootstrapModule(AppModule);
with
return platformBrowserDynamic().bootstrapModule(AppModule);
Don't ask me why is it so :)))
Now it's time to get the following error :)
app.js:formatted:43405 Unhandled Promise rejection: StaticInjectorError(Dr)[$injector]:
StaticInjectorError(Platform: core)[$injector]:
NullInjectorError: No provider for $injector!
Wow! Thank you, once again. That's pretty unexpected haha.
I copied that line of code about platformRef bootstrapping directly from the Angular docs:
https://angular.io/guide/upgrade-performance#specifying-a-factory-for-the-angular-module
So if a specific invocation of platformRef bootstrapping is required by @ngtools/webpack, I wonder if maybe it should be mentioned somewhere in the @ngtools/webpack docs?
I would like the following code in my main.ts file work with AOT - currently it breaks:
if (environment.isCordova) {
let onDeviceReady = () => {
window.open = cordova.InAppBrowser.open;
platformBrowserDynamic().bootstrapModule(ApplicationModule);
};
document.addEventListener("deviceready", onDeviceReady, false);
} else {
platformBrowserDynamic().bootstrapModule(ApplicationModule);
}
I know I can do replace the main.ts when compiling to cordova, but the above still doesn't work in cordova due to the fact that it is ran inside the onDeviveReady method...
Any suggestions how to solve this?
@HarelM Will this work for you?
if (environment.isCordova) {
let onDeviceReady = () => {
window.open = cordova.InAppBrowser.open;
bootstrapFn();
};
document.addEventListener("deviceready", onDeviceReady, false);
} else {
bootstrapFn();
}
function bootstrapFn() {
platformBrowserDynamic().bootstrapModule(ApplicationModule);
}
@alexzuza Thanks for the tip!
I have tested it and it works.
Never the less, there's a bug here.
I solve the issue, in the file main.ts, I remove this part .catch(err => console.error(err)); and the final line is just: platformBrowserDynamic().bootstrapModule(AppModule);
I solve the issue, in the file main.ts, I remove this part .catch(err => console.error(err)); and the final line is just: platformBrowserDynamic().bootstrapModule(AppModule);
I think that's not great solution for this error...You need to add
"files": [
"../src/app/app.module.ts"
]
in your tsconfig.app.json file...
I am facing the same issue and I tried by adding the below line to my tsconfig.app.json file but it didn't work:
"files": [ "../src/app/app.module.ts" ]
Can someone please help me with this?
@alexeagle I think I found the root cause in my case I was having a custom builder and by using it I was getting this error and if I switched to cli one it works totally fine after some debugging if found that compile cli try to read class declaration https://github.com/angular/angular/blob/5332b04f35e60ddb2567b2288efd561e25a2a23b/packages/compiler-cli/src/metadata/collector.ts#L299
but ts.SyntaxKind.ClassDeclaration kind (240,244) is different between typescript versions for example (3.7 and 3.3)
so in my case, my builder was not an external dependency I was trying something in angular project
apps/builder and in angular.json "builder": "./builder:todo" and this folder was a package with different ts version
I hope it helps someone else short answer make sure typescript version is consistent between your packages and maybe global ng
if nothing else works try following to create the ngmodule offline
if (environment.production) {
// there is no need of this if block, angular internally creates following code structure when it sees --prod
// but at the time of writting this code, else block was not working in the production mode and NgModule metadata
// not found for AppModule error was coming at run time, added follow code to fix that, it can be removed probably
// when angular is upgraded to latest version or if it start working automatically. :)
// we could also avoid else block but building without --prod saves time in building app locally.
platformBrowser(extraProviders).bootstrapModuleFactory(<any>AppModuleNgFactory);
} else {
platformBrowserDynamic(extraProviders).bootstrapModule(AppModule);
}
@HarelM Will this work for you?
if (environment.isCordova) { let onDeviceReady = () => { window.open = cordova.InAppBrowser.open; bootstrapFn(); }; document.addEventListener("deviceready", onDeviceReady, false); } else { bootstrapFn(); } function bootstrapFn() { platformBrowserDynamic().bootstrapModule(ApplicationModule); }
Thanks! @alexzuza But why this work in AOT????
Might be helpful for someone. Earlier (few months ago) I turned on npm config set link true to reduce the node_modules size, but now understood it has consequences like this. For me resetting the npm config npm config edit or particularly npm config set link false worked for me. I almost wasted 3 days for this.
Most helpful comment
I solve the issue, in the file main.ts, I remove this part .catch(err => console.error(err)); and the final line is just: platformBrowserDynamic().bootstrapModule(AppModule);