Angular 2 Quickstart: unexpected token <
JavascriptAngularJavascript Problem Overview
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"
]
}
Thanks in advance for any help.
Javascript Solutions
Solution 1 - Javascript
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.
Solution 2 - Javascript
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-
Solution 3 - Javascript
I've had similar issues with different node modules and came here from Google.
Usually, I would get the error after import
ing 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.
Solution 4 - Javascript
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'
}
});
Solution 5 - Javascript
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';
Solution 6 - Javascript
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.
Solution 7 - Javascript
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.
Solution 8 - Javascript
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';
Solution 9 - Javascript
A trailing comma in your systemjs configuration will cause this.
Check the systemjs.config.ts
file and make sure the json is valid.
Solution 10 - Javascript
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.
Solution 11 - Javascript
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}");
}
Solution 12 - Javascript
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
Solution 13 - Javascript
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 !
Solution 14 - Javascript
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 :)