59

I am trying to set up angular 2 according the quickstart found at http://angular.io. I have copied every file exactly as described in the guide, but when I run npm start and a browser tab opens, I get the "Loading..." with the following error in the console:

Uncaught SyntaxError: Unexpected token <                        (program):1
     __exec @ system.src.js:1374
Uncaught SyntaxError: Unexpected token <          angular2-polyfills.js:138
    Evaluating http://localhost:3000/app/boot
    Error loading http://localhost:3000/app/boot

This is my app.component.ts:

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `<h1>My First Angular 2 App</h1>`
})
export class AppComponent {

}

My boot.ts:

import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';

bootstrap(AppComponent);

My index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular 2 Quick Start</title>

    <script src="node_modules/es6-shim/es6-shim.js"></script>
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

    <script>
    System.config({
        packages: {
            format: 'register',
            defaultExtension: 'js'
        }
    });

    System.import('app/boot')
        .then(null, console.error.bind(console));
    </script>
</head>
<body>
    <my-app>Loading...</my-app>
</body>
</html>

My package.json:

{
    "name": "angular2-quickstart",
    "version": "0.1.0",
    "scripts": {
        "tsc": "tsc",
        "tsc:w": "tsc -w",
        "lite": "lite-server",
        "start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
    },
    "license": "MIT",
    "dependencies": {
        "angular2": "2.0.0-beta.0",
        "systemjs": "0.19.6",
        "es6-promise": "^3.0.2",
        "es6-shim": "^0.33.3",
        "reflect-metadata": "0.1.2",
        "rxjs": "5.0.0-beta.0",
        "zone.js": "0.5.10"
    },
    "devDependencies": {
        "concurrently": "^1.0.0",
        "lite-server": "^1.3.1",
        "typescript": "^1.7.3"
    }
}

And finally my tsconfig.json:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "system",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false
    },
    "exclude": [
        "node_modules"
    ]
}
starball
  • 20,030
  • 7
  • 43
  • 238
muuk
  • 932
  • 1
  • 7
  • 15

14 Answers14

46

Try replacing this

System.config({
        packages: {
            format: 'register',
            defaultExtension: 'js'
        }
    });

with this

System.config({
        packages: {
            app: { // must match your folder name
                format: 'register',
                defaultExtension: 'js'
            }
        }
    });

I was trying to apply a slightly different folder structure to their quickstart and ran into the same issue. I found that the name of the property on the "packages" object had to match the parent folder.

Isaac
  • 484
  • 4
  • 2
  • 2
    Is it possible to create a package for the root dir? In short I have moved my `index.html` into the `app` dir and set `app` as the webroot. I need to load `./boot/` and not `./app/boot` – Shawn Northrop Feb 26 '16 at 07:37
  • Man... I don't know how many hours I spent trying to solve this problem. The documentation with this beta things here is something truly painful. You'll always be remembered. – Giacomo Cerquone Mar 20 '16 at 11:09
  • I know we're not supposed to leave "thanks" comments but I can't help it. I think I love you. This error message is so obscure! – user2428107 May 11 '16 at 08:08
  • 1
    For a newbie like myself this answer is not sufficiently clear. Are you saying enter the parent folder name after {//.... OR the app: is the folder name referred to. My system.config look like this: packages: { app: { main: './main.js', defaultExtension: 'js' }, ...no "format: "register". I have updated to angular 4.1.0 with the same result. Actual message: "Error: (SystemJS) Unexpected token <↵ SyntaxError: Unexpected token <↵ – MichaelE Apr 19 '17 at 17:05
  • What if I'm using webpack? – Nate Gardner Jul 20 '17 at 04:00
34

A tip for those who encounter the "Unexpected token <" error. For me, this happened when SystemJS attempted to retrieve a dependency (JavaScript file) and instead the web server returned an HTML page (hence the unexpected opening < in the html).

I was able to pinpoint this in Chrome's Dev Tools on the Network tab by looking through the downloaded JavaScript files one-by-one until I found the one where HTML was returned instead. This made it easy to resolve the issue with my import.

Hoping we may get a more meaningful error message at some point-

Ben Wells
  • 363
  • 3
  • 8
  • 2
    Is this a full answer? – Enamul Hassan Apr 29 '16 at 15:59
  • 2
    This should be higher up - If you are trying to change the behaviour of a node server, to let Angular handle the 404 errors, instead of node, this might be an issue. – Alex Szabo Jul 29 '16 at 21:34
  • 1
    Fixed with looking thru Network tab to find which one returned HTML as response. Thanks! – Edmond C Oct 28 '16 at 16:49
  • 1
    This can also happen if you have moved or renamed the directory of your Angular application so that it is no longer under **static resources** of the web server. Example: You decided to rename your `app_client` dir to `app` and you updated your web server (e.g. Express/Node) routes to serve `index.html` from the new `app` dir, but forgot to set that dir to be served as **static resources**. The web server then returns you an HTML saying *"You can't access that shit, bro"* – Bloke Jan 28 '17 at 21:11
  • I followed this suggestion and immediately found the dependency that was not being loaded correctly. – Aebsubis Mar 11 '17 at 23:05
  • @Aebsubis....could you explain to a newbie how you found the dependency? – MichaelE Apr 19 '17 at 17:08
  • @Ben Wells what did you do to fix it? – Flea Sep 08 '17 at 19:42
18

I've had similar issues with different node modules and came here from Google.

Usually, I would get the error after importing a package and then attempting to use it.

For example, I had the same issue when loading https://github.com/ngrx/store.

I checked my network tab and it turns out the file that was loaded for store.js (that module's main file) was not correct. It requested store.js, but got my index.html, which started with <!DOCTYPE html>, i.e. it started with a "<", which is not valid JavaScript.

It is not clear to me why my index.html was served in lieu of the actual JavaScript file. One explanation could be that SystemJS made a request that led nowhere and my server was configured to serve index.html as a default. I don't have enough data to prove this, though. Cum grano salis.

In any case, I fixed it by explicitly telling SystemJS where a package lives if it can't find it on its own. So, for example, to fix a failing import { Store } from '@ngrx/store';, you can do:

System.config({
  packages: {
    src: {
      format: 'register',
      defaultExtension: 'js'
    }
  },
  map: { '@ngrx/store' : '/node_modules/@ngrx/store/dist/store.js' } // <-- this!
});
System.import('src/boot')
      .then(null, console.error.bind(console));

Because the Store module lives in that file. This way, SystemJS finds it, and the module can be imported just fine.

Dennis Hackethal
  • 13,662
  • 12
  • 66
  • 115
  • 2
    In my case it was a simple `import {...} from './directory/`. I had to replace it by `import {...} from './directory/index'`. – ComFreek Mar 20 '16 at 21:40
  • I am getting the same kind of problem, can you help me with this question? [Inline Link](http://stackoverflow.com/questions/42325399/unable-to-load-ng2-fullpage-in-my-angular-2-quickstart-app) – thenakulchawla Feb 19 '17 at 10:16
  • finally after 4hrs i m able to resolve the error. Worked for me. #saviour – Noman Chali Apr 19 '17 at 13:33
  • @NomanChali Hi Norman, for a newbie like myself could you explain how you fixed it? – MichaelE Apr 19 '17 at 17:11
  • Yes, I have the same issue where my SystemJS can not find one of my packages and so it inserts my default 404 html page inside that javascript file. – Harry Apr 26 '17 at 06:29
  • NodeJS: `router.all('*', function (req, res) { res.render('index'); })` – Cody Jun 29 '17 at 05:22
4

I had a similar issue importing rx.js I ended up solving it by adding a path to the System.config()

System.config({
  defaultJSExtensions: true,
  paths: {
    'rx' : 'lib/rx.js'
  }
});
JRulle
  • 7,448
  • 6
  • 39
  • 61
  • 3
    Not sure why some libraries require you to explicitly set the path like this. I encountered the same issue with `moment.js` and this was the fix. – onetwothree Feb 05 '16 at 16:01
4

I had a similar issue, I had configured the IIS server to rewrite all paths to index.html in order to get the router working properly. (Page refresh was returning 404. Read details in this answer)

As user @dchacke points out, it's because System.js expects a .js file not a .html file. This indeed produces the strange message starting with SyntaxError: Unexpected token <. Temporarely disabling the URL rewriting allows me to see the real issue.

When importing child components into parent components System.js can get confused if paths are not declared properly.

For example parent.component.ts has the following import:

import { ChildComponent } from './childComponentFolder/childComponent';

Throws this error:

GET app/parentComponentFolder/childComponentFolder/childComponent.js 404 (Not Found)
Error: Error: XHR error (404 Not Found) loading app/parentComponentFolder/childComponentFolder/childComponent.js

Changing the import instruction path from relative to absolute path solves the issue:

import { ChildComponent } from 'app/childComponentFolder/childComponent';

Mapping the path in system.config.js could also do the trick, but I find it harder to maintain because it's not readily apparent why the import path works or not. Now I can uncomment the rewrite rules in Web.config and all works just fine.

Edit:

It seems that typescript transpiler is very picky about paths. Only relative paths pass without throwing errors:

Basically you need to step back up one folder from parentComponentFolder/ to app/ folder.

import { ChildComponent } from '../childComponentFolder/childComponent';

Community
  • 1
  • 1
Adrian Moisa
  • 3,923
  • 7
  • 41
  • 66
  • 1
    This did the trick for me! I've been getting that same kind of error when trying to initialize instances of a class such as *user = new AuthUser()* and by temporarily commenting out my path reqrite in Global.asax.cs, I got a more useful error message that lead to a solution! – Methodician Jul 30 '16 at 18:52
2

I ran into this same problem. I fixed it by implementing the following in my index.html (note: I put the angular2 js dependencies in 'lib' folder):

<html>

<head>
    <title>Desktop main</title>
</head>
<body>
<div>
    <my-app>Loading...</my-app>
</div>
   
    <script src="~/lib/anguar2/angular2-polyfills.js"></script>
    <script src="~/lib/es6-shim/es6-shim.js"></script>
    <script src="~/lib/systemjs/system.src.js"></script>
    <script>

    System.config({
        defaultJSExtensions: true

    });

    </script>
    <script src="~/lib/rxjs/rx.js"></script>
    <script src="~/lib/anguar2/angular2.dev.js"></script>
    <script>
    System.import('app/boot');
    </script>
</body>

</html>
app.component.ts looks like this:

import {Component} from "angular2/core";

@Component({
    selector: "my-app",
    template: "<h1>Hello Angular 2</h1>"
})
export class AppDesktopComponent {
    
    
}

Wish I could tell you why this works and the angular2 quickstart boilerplate doesn't.

brando
  • 8,215
  • 8
  • 40
  • 59
2

I was getting a similar problem:

Unexpected token ]

When starting the server. Turns out I had a trailing comma in my tsconfig.json:

...
  "files": [
    "app.ts",
    "typings.d.ts",
    "abc-vt/abc-vt",   <-Doh!
  ]

Lesson: Don't just assume it's an error in your source code -- check your config files as well.

vt5491
  • 2,254
  • 2
  • 22
  • 34
2

In my case, I'd inadvertently included the file extension on the import...

import {SomeComponent} from 'some.component.ts';

And (obviously!) it should have been...

import {SomeComponent} from 'some.component';
Steve S
  • 614
  • 9
  • 20
2

A trailing comma in your systemjs configuration will cause this.

Check the systemjs.config.ts file and make sure the json is valid.

jdewit
  • 966
  • 9
  • 10
2

I had a similar bug. I got:

Uncaught SyntaxError: Unexpected token =  (index):16

because I tossed a semicolon at the end of the @Input() in the hero-detail.component file.

Hope this helps somebody.

thor
  • 21,418
  • 31
  • 87
  • 173
Nayfin
  • 385
  • 3
  • 11
1

The primary cause of this issue is that the file you are trying to import is an html file, not a js file. You can see this by using the network tab in Chrome to have a look at the file it actually imported.

My issue wasn't solved by the methods above. For me, this happened because I had routed all default routes through to the index.html page, which is how I get Angular deep linking working in Visual Studio Enterprise. When I requested a file without the extension, and it couldn't find that file, it would serve the default index.html page, which would start with a < character, and fail.

The giveaway for me was that when I put the full path to the exact file, it would work.

Anyhow, to fix this, I had to add an Ignore route for the node_modules folder in my RouteConfig.cs file:

public static void RegisterRoutes(RouteCollection routes)
{
   routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
   routes.IgnoreRoute("node_modules/{*pathInfo}");

}
tone
  • 1,374
  • 20
  • 47
0

I had received the same error message. Similar to what other people mentioned, my case was caused by url rewrites, serving the html instead of the javascript expected by angular.

I am using lite-server/browser-sync to develop and host my app locally. To get the angular routing working properly, I was using

var history = require('connect-history-api-fallback')

to redirect relevant pushState navigation back to index.html. Ultimately, a misconfiguration in my typescript imports led to one request not being recognised as a js file and instead redirected to index.html. The difficulty was how to figure it out.

I found that you can enable verbose logging for the connect-history-api-fallback.

 middleware: [history({
        index: '/src/index.html',
        verbose: true
    })]

which then led me to find the culprit by scanning the log for redirected entries:

Not rewriting GET /node_modules/systemjs/dist/system.js because the path includes a dot (.) character.
Not rewriting GET /node_modules/core-js/client/shim.min.js because the path includes a dot (.) character.
Rewriting GET /src/culprit to /src/index.html
Ben
  • 1,537
  • 1
  • 17
  • 20
0

For those who read the whole thing and didn't found anything interesting, I may have another option for you.

I ran into the same problem because the website was deployed on more than 1 web server. The problem was related to different builds deployed on some servers.

Basically, you have 1 server with one version and another server with some other version. So, of course when you load balance you're likely to get 404 on some resources on some servers because the versions are different (remember the main.xxxxx.js where xxx is different at every build). And if you configured your webserver to return a 404 webpage - which happens a lot I guess - you get some HTML instead of the JS files then the unexpected token.

So, check your versions on each server !

vivien.destpern
  • 1,020
  • 1
  • 7
  • 14
-1

For me, this error was caused because I served my angular frontend with a simple node express server as such:

app.use('/*', (req, res) => {
    res.sendFile(path.join(__dirname,'index.html'));
});

but I had forgotten to specify that all static files should be served from the current directory with the line:

app.use(express.static(__dirname));

So every call for a static asset returned index.html. Woops. Once I added that line, everything was fine. Hope this can help someone down the line :)

MyrionSC2
  • 1,248
  • 1
  • 14
  • 24