30

I will make my Angular 2 question very precise.

1. I am using:

Angular 2, angular-cli: 1.0.0-beta.15, ( webpack building ) node: 6.4.0, os: linux x64

2. What I want to achieve:

I want to build my project in a way that after the build ( ng build project-name ) I get static files of my Angular 2 application, which I can run directly from chrome without using ng serve or the node server. I just want to double click index.html and run the app locally.

3. Meanwhile, what I get in the chrome browser console output when I double click the generated index.html is:

file:///inline.js Failed to load resource: net::ERR_FILE_NOT_FOUND file:///styles.b52d2076048963e7cbfd.bundle.js Failed to load resource: net::ERR_FILE_NOT_FOUND file:///main.c45bb457f14bdc0f5b96.bundle.js Failed to load resource: net::ERR_FILE_NOT_FOUND file:///favicon.ico Failed to load resource: net::ERR_FILE_NOT_FOUND

  1. As I understand this is related to paths. The built and bundled application cannot find the right paths. So my question is where and how I should change the paths in my app or in any build configuration files in order for my app to work like I would like it to work in the way I have described in point number 2

  2. Thank you in advance for a direct and full answer on that topic, because other topics are not explaining the full scope on that subject.

BartB
  • 413
  • 1
  • 5
  • 9
  • I think the problem is using the `file://` URL. I'm pretty sure this disables some JS features (like XHR) because of security concerns. What's wrong with using a server? – Paul Samsotha Sep 29 '16 at 13:28
  • I can't run in it on a server. I need static files that is why. I am not gonna run the application on a PC or MAC. I need to run it using only a browser like Chrome, without any server. – BartB Sep 29 '16 at 13:44

10 Answers10

32

First Step:

Run the command

ng build

or

ng build -prod (then it will compact all files for production version)

Second Step:

Change in index.html

<base href="/"> to <base href="./">

Third Step:

Put all files into server(may be htdocs in localhost or any server)

Hopefully it will work.

sabuz
  • 829
  • 8
  • 10
  • second step does the magic. but why? why dot needs to be added manually – Khaleel Jul 12 '17 at 18:11
  • 2
    @Khaleel because to make sure your file paths are relative to the current directory rather than relative to the root directory we have to add `.` – Pardeep Jain Aug 26 '17 at 06:33
  • 1
    @Khaleel You can add the dot to your main index.html file and it will carry over to the production version so you don't have to add it manually each time. – Michael Fulton Jan 01 '20 at 03:13
29

Solution without server:

First Step:

Change in index.html:

remove <base href="/">

Second Step:

Change in app.module.ts:

import { CommonModule, APP_BASE_HREF, LocationStrategy, HashLocationStrategy} from '@angular/common';

@NgModule({
   providers: [
       { provide: APP_BASE_HREF, useValue: '/' },
       { provide: LocationStrategy, useClass: HashLocationStrategy }
   ]
})

Third Step:

Run the command

ng build

or

ng build -prod

Doubleclick dist/index.html to see the result.

clami219
  • 2,958
  • 1
  • 31
  • 45
Jakša Bašić
  • 291
  • 3
  • 4
  • This was the only one that worked for me. If the base tag was left in the index.html (even if it were set to ./ or . or whatever) caused the page to try to attempt to push state, which was not supported on file/// – chrismarx Sep 04 '17 at 18:46
  • 1
    This worked for me, thanks! @Bartb, would you mind accepting this as the answer? – Kenny Sep 15 '17 at 00:15
  • It really works, but the problem is. Application runs at : 'file:///C:/Users/000000/Desktop/assignment1/index.html#/login' but looking for json files at: 'file:///C:/Users/assets/json/userStory.json' where as it should have been 'file:///C:/Users/000000/Desktop/assignment1/assets/json/userStory.json' . Please help. – JEET ADHIKARI Feb 01 '19 at 21:53
  • This worked for me. However, I created a font-family in my app using the font files which I load from the assets folder. It worked correctly with the ng serve command but doesn't work this way. Why ? – Saurabh Tiwari Jun 30 '19 at 18:06
11

If you're using Angular-Cli you don't need to amend index.html after building the project. As per Angular-CLi github document https://github.com/angular/angular-cli#base-tag-handling-in-indexhtml you can simply modify argument while you're building the project:

    Example: ng build --prod --base-href .

The actual Usage is:

ng build --base-href <base>

you can simply introduce a specific url instead of base. In this example we use . (dot) as an argument

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
Nelly Sattari
  • 2,613
  • 1
  • 12
  • 14
11

A simple solution: Change your base href when you build.

ng build --prod --base-href .

Now you can double click the index.html file and it will work.

Here is an example of this working: https://mattspaulding.github.io/angular-material-starter/

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
Matt
  • 33,328
  • 25
  • 83
  • 97
7

You must serve the /dist folder using an HTTP server. You can't get around this because loading files locally doesn't allow code execution for security reasons.

The server doesn't have to be something heavy like Express or even a highly featured minimalist one like HapiJS. The built in Node http-server will do just fine. If you've already got Apache, nginx, or IIS set up you can also use them to serve your app.

EDIT: I did some moral searching and decided to offer up a solution I personally wouldn't use, but may be a good fit for you: Web Server for Chrome Extension

gelliott181
  • 1,008
  • 11
  • 19
  • Thank you very much :) But I need this bundle to work on a mobile device which uses webkit but not Android or iOS but Tizen. Inside there is webkit, so I can't rely direclty on Google Chrome. But thank you for your research. – BartB Sep 29 '16 at 13:50
  • Tizen? That's some important info that belongs in your post! – gelliott181 Sep 29 '16 at 13:55
  • Also, your best option is to just implement a NodeJS HTTP server that serves your `/dist`. It's less than 50 lines max, and the CLI already has dependencies on it. – gelliott181 Sep 29 '16 at 14:03
  • Yes. Tizen is running on webkit. Since a lot of people don't know what Tizen is and I know Tizen very good, then I asked about webkit. Answer for webkit would solve the problem on Tizen. But thank you for your reply :). – BartB Sep 29 '16 at 14:41
  • 3
    +1 for the only answer which explains why loading index.html from /dist directory does not work. However, still to find more details on why angular produced static html with referenced javascript files are a security threat. And why that works when I just write a simple html with javascript files in the same folder. – iCrus Dec 11 '16 at 16:34
  • 1
    The threat is cross site scripting and the reason things don't work is part of Cross Origin Request Sharing. Your requests must originate from the same location and/or all pre-flight checks must be responded to properly. When you don't have a server to respond to your `OPTIONS` pre-flight the browser goes "NOPE" and rejects responses because they don't match the allowed headers, methods, or some other tiny little bit of the CORS puzzle. – gelliott181 Dec 12 '16 at 19:32
3

All you need is to build your app using this one line of code:

ng build --prod --base-href ./
1

I recommend use Expressjs, why servers how xampp, laragon, etc... the routes not work well, I did it like that: I created new folder with name server, inside copied an file index.js, the route would be "src/assets/server/index.js" ,

Index.js content

var express = require('express'),
    path = require('path'),
    fs = require('fs');

var app = express();
var staticRoot = __dirname + '/../../';

app.set('port', (process.env.PORT || 80));

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

app.use(function(req, res, next){
    var accept = req.accepts('html', 'json', 'xml');
    if(accept !== 'html'){
        return next();
    }
    var ext = path.extname(req.path);
    if (ext !== ''){
        return next();
    }
    fs.createReadStream(staticRoot + 'index.html').pipe(res);

});
app.listen(app.get('port'), function() {
    console.log('app running on port', app.get('port'));
});

In package.json, inside the root of project

{
    "dependencies": {
        "express": "4.13.4"
    }
}

later, run in console command ng build prod and run

node dist/assets/server/

this command execute an express server, indicating the direction of file config our server, on this occasion, the file index.js preconfigured

p.s: sorry for my bad english, I am learning

1

Removing <base href="/"> from index.html worked for me.

achola
  • 511
  • 4
  • 4
0

You can achieve something like this using nw.js for example (or electron). I created an app myself that uses angular 2 locally with nw.js and it works like a charm ;)

nwjs.io

kristóf baján
  • 473
  • 1
  • 5
  • 15
  • No, at least at the moment not. But you didn't mention that you needed mobile support. – kristóf baján Sep 29 '16 at 13:54
  • Nevertheless I will try to run it on Tizen. It is the same like running on webkit. If it runs on webkit and does need any server then it must run on Tizen. Thank you for your answer :). – BartB Sep 29 '16 at 14:43
0

use ng serve --open to build the application and start a web server