22

Check the update on the bottom!

I have a service that throws an error while the app is bootstrapping. Cannot read property 'call' of undefined. I'm using ng2 2.4.2 and angular-cli 1.0.0-beta.24.

ERROR

Uncaught TypeError: Cannot read property 'call' of undefined at webpack_require (bootstrap 81b10f8…:52) at Object.621 (environment.ts:8) at webpack_require (bootstrap 81b10f8…:52) at Object.450 (src async:7) at webpack_require (bootstrap 81b10f8…:52) at Object.1057 (util.service.ts:35) at webpack_require (bootstrap 81b10f8…:52) at webpackJsonpCallback (bootstrap 81b10f8…:23) at main.bundle.js:1

As you can see it's a problem with the util service - this looks as follows:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Project } from '../datatypes/';
import { Response } from '@angular/http';


@Injectable()
export class UtilService {
    constructor(private router: Router) {}

    public redirectToProject(project: Project) {
        let query = project.ProjectName.split(' ')
            .join('-')
            .concat('-' + project.Id)
            .toLowerCase();
        this.router.navigate(['/project', query]);
    }

    public extractData(res: Response) {
        let body = res.json();
        return body || {};
    }
}

Strange: When inspecting the source file in chrome it has no syntax highlighting, which would suggest a syntax error - in my opinion there's none though.

Update January 20. 2017

I updated to ng2.4.4 and angular-cli 1.0.0-beta26. The problem is still the same. While playing around, Arjan found out that it works with beta 21. Will have to check the changes. The problem now isn't in the service above but in the environment.ts file (which has all the defaults).

HDJEMAI
  • 8,842
  • 44
  • 66
  • 88
sandrooco
  • 6,584
  • 7
  • 39
  • 78
  • Did you meanwhile solve this? – Arjan Jan 18 '17 at 07:20
  • Nope, are you having the same problem? @Arjan – sandrooco Jan 18 '17 at 07:35
  • Yes, and I thought I resolved it by fixing an erroneous `export` in `src/app/index.ts`, but while writing that as an answer, a few minutes later it was broken again...! And so far I failed to get it working. To be continued, I hope... – Arjan Jan 18 '17 at 12:15
  • Ugh ok then.. Can you give an update here when there's news? I will do so too. – sandrooco Jan 18 '17 at 12:17
  • Minor update: all works fine in angular-cli 1.0.0-beta.21, and starts to complain in 22. The weird thing is that with version 22, when also playing around with bootstrapping multiple app modules, I also run into https://github.com/angular/angular-cli/issues/2887 while I'm not explicitly trying to use AOT at all. Maybe some defaults in the angular-cli config changed, but I fail to find the differences. (I've gone through `ng init` to see all differences.) – Arjan Jan 19 '17 at 16:15
  • Ok cool, got it working too with 1.0.0-beta.21. Did you already try with beta.26? @Arjan – sandrooco Jan 20 '17 at 08:02
  • What do you mean with _"The problem now [is] in the `environment.ts` file (which has all the defaults)"_? Does that mean you still see errors in beta 21? (In 25 and 26 I also see a reference in the error to the closing brace of `environment.ts`; I just assumed it was not really related to any real cause.) – Arjan Jan 24 '17 at 09:29
  • @Arjan That's the same error I'm having too, but only with 22+. That was a bit unclear. – sandrooco Jan 24 '17 at 10:00
  • Are you using a regular `index.html` with just an ``, into which a ` – Arjan Jan 24 '17 at 11:51
  • No, I don't have them automatically injected. – sandrooco Jan 24 '17 at 12:07
  • That's the culprit. Solution might be on its way, depending on how you have the scripts defined then... – Arjan Jan 24 '17 at 12:13
  • What does that mean? :D @Arjan – sandrooco Jan 24 '17 at 12:17
  • If you don't have them inserted automatically, then you're somehow explicitly loading `inline.bundle.js`, `styles.bundle.js`, `vendor.bundle.js` and `main.bundle.js`, right? Did you include `vendor.bundle.js`? (That was not used previously.) And if you did: are you loading them using some script? Then the execution order is undefined. (I hope to post an answer soonish now...) – Arjan Jan 24 '17 at 12:23

6 Answers6

28

I think it happens when you make changes to module imports during run time.

Run the application again using ng serve and it fixed the issue for me.

It may also occur when you try to use components of lazy loaded modules in other modules before the lazy module getting loaded or such similar scenarios.

Franklin Pious
  • 3,360
  • 3
  • 23
  • 29
  • I dont know why this fixed my issue but it really fixed. – Ulrich Dohou Sep 14 '18 at 17:29
  • Same thing for me, it is usually due to changing files (e.g. renaming/deleting) (v5) – Michael Oct 29 '18 at 04:38
  • @Franklin Pious as you said i have added lazy and suspense in react components then build it ., now ended with this error any suggesstions . it was working fine., after added lazy stuff its throwing this error ``` bundle.js:22 TypeError: Cannot read property 'call' of undefined ``` – SakthiSureshAnand Oct 22 '20 at 06:32
  • @SakthiSureshAnand you should make sure that components from the lazyloaded module are not used without loading the lazy module. If that is the case, maybe you should change your import structure – Franklin Pious Oct 22 '20 at 08:55
12

For me, this was caused by using our own client-side JavaScript to dynamically load the webpack-generated bundles. That was easily fixed in our own loader script.

When using webpack, a regular Angular 2 index.html does not include any <style> or <script> elements, but just <app-root></app-root>. When running ng serve or ng build, the file is enhanced server-side to add something like the following to the end of the file:

<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="polyfills.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>

...or, for ng build --prod:

<link href="styles.d41d8cd98f00b204e980.bundle.css" rel="stylesheet"/>
...
<script type="text/javascript" src="inline.66e3ead788094772ecc4.bundle.js"></script>
<script type="text/javascript" src="polyfills.477266e3ead78809ecc4.bundle.js"></script>
<script type="text/javascript" src="vendor.18c581546c015d1bfc6e.bundle.js"></script>
<script type="text/javascript" src="main.9a5c1002f220245829cd.bundle.js"></script>

The resulting server-side HTML file is sent to the browser. And browsers will run <script> elements already present in the HTML in the order in which they are encountered.

But that's different when adding those <script> elements client-side, dynamically at runtime, which by default will be executed asynchronously. See the notes on "parser-inserted scripts" and "script-inserted scripts" on MDN's script page.

In our case we're including the Angular 2 application into pages in our CMS. To avoid having to change the CMS page whenever we release a new version (which will change the hashes in the names of the generated bundles), we're adding the bundles using our own JavaScript code. For a browser these are "script-inserted scripts". To ensure these are executed in the correct order, just set async to false (setting defer did not do the trick for me):

var script = document.createElement('script');
script.async = false;
script.src = ...

Or, when using document.write, ensure it includes the async="false" attribute:

document.write(unescape('%3Cscript async="false" src="..." %3E%3C/script%3E'));

(Fun fact: beware that Chrome 55 and later might skip these blocking scripts on slow connections, if they are hosted on a different domain.)

Without this, things most often were fine up to angular-cli 1.0.0-beta.21, though we did see an occasional "Can't find variable: webpackJsonp". For later versions different errors might show, depending on which script is executed first, and which browser is used. Like:

Cannot read property 'call' of undefined
TypeError: modules[moduleId] is undefined
ReferenceError: Can't find variable: webpackJsonp
TypeError: undefined is not an object (evaluating modules[moduleId].call')
Unable to get property 'call' of undefined or null reference

Also note that vendor.bundle.js and polyfills.bundle.js were not used in older versions. And the scripts might need to be inserted somewhere below the <app-root> element.

Arjan
  • 21,528
  • 11
  • 59
  • 70
  • So basically there's no solution? :/ Thanks for the explanations. – sandrooco Jan 24 '17 at 14:07
  • Er, the above `script.async = false` solved it for me, @Sandrooco (and solved the occasional _"Can't find variable: webpackJsonp"_ as well; all related to the order in which the scripts are executed). And you wrote you're not having the script tags inserted automatically either? So, then *how* do you insert them? – Arjan Jan 24 '17 at 14:21
  • Oh ok I see. So you have these 4 scripts in your document? – sandrooco Jan 24 '17 at 15:06
  • No. We're embedding the Angular application into existing pages in a CMS, and don't want to change those CMS pages whenever we build a new version of our Angular app. Instead, we only make the pages include our own JavaScript file, and that file loads the latest versions of the 4 webpack generated files. – Arjan Jan 24 '17 at 15:11
  • So, @Sandrooco, how do you insert the script tags? – Arjan Jan 26 '17 at 09:39
  • A bit embarassing, but we started with a .NET MVC project and then decided to use ng2. So we return an index view where the angular app is located - with manual script "injection". We definitely have to change this right now! – sandrooco Jan 26 '17 at 09:55
  • So, @Sandrooco, these scripts are not in the server-side HTML when the browser loads the page, but are "script-inserted scripts" added by client-side JavaScript at runtime? Then I think that setting `script.async = false` should really fix it for you, just like it did for me. (Or, when using `document.write`, just ensure the attribute is in the generated `` element.) And regardless if they are in the HTML on page load, ensure that the order is correct, and that they are added _after_ the ``. Easy fixes. (See edited answer.) – Arjan Jan 26 '17 at 11:40
  • Nope. :( I upvoted for your efforts - thanks so much! – sandrooco Feb 03 '17 at 11:09
  • I still don't understand how you're including the scripts, @Sandrooco (just in case that's the cause for you as well). Are the scripts in the HTML when loaded by the browser? (If yes: in the right order, and including `vendor.bundle.js`?) – Arjan Feb 03 '17 at 11:33
  • AWESOME answer regarding `script.async = false` ! Thank you – Romain Bruckert Jun 19 '17 at 13:31
  • This helped me find my answer. I was getting this error message, and in the end the problem is that I hadn't directly copied over the index.html file from the angular build. When I reproduced it in our production system I accidentally changed the order of the scripts. It's a new project, and obviously our final deployment process will take care of these things for us, but for an hour there I was very confused... – Conor Mancone Jul 13 '17 at 13:05
  • We embedded Angular into AngularJS and for some reason AngularJS changes the script.async to true on all of the scripts. So you need to run: – Pistolpete . Apr 11 '18 at 11:29
1

Finally I found the answer - works with beta.32.3. We have to use these files:

<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="scripts.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>

It's also important to update the local and the global package. Updating globally is described well on their github page. Updating locally is easy too - simply update the dependency in your package.json.

Important: Since beta.29 angular cli is the package @angular/cli, not angular-cli anymore..

sandrooco
  • 6,584
  • 7
  • 39
  • 78
1

In my case, I needed to make sure that I had the script tags in the right order.

  <script type="text/javascript" src="inline.bundle.js"></script>
  <script type="text/javascript" src="polyfills.bundle.js"></script>
  <script type="text/javascript" src="styles.bundle.js"></script>
  <script type="text/javascript" src="scripts.bundle.js"></script>
  <script type="text/javascript" src="vendor.bundle.js"></script>
  <script type="text/javascript" src="main.bundle.js"></script>
Amadeus Sánchez
  • 2,115
  • 1
  • 22
  • 30
0

I had a similar issue. I updated to @angular-cli (1.0.0-rc.2) and @angular/core(2.4.9) and followed Sandrooco's solution. However, there is an additional file polyfills.bundle.js required to work.

<script type="text/javascript" src="inline.bundle.js"></script>
<script type="text/javascript" src="polyfills.bundle.js"></script>
<script type="text/javascript" src="styles.bundle.js"></script>
<script type="text/javascript" src="vendor.bundle.js"></script>
<script type="text/javascript" src="main.bundle.js"></script>

I hope it helps.

G...... T......
  • 139
  • 1
  • 3
0

Changing the port for some reason solved this for me ng serve --port 4300

Omar
  • 2,494
  • 2
  • 28
  • 54