Search code examples
node.jsstatic-fileshapi.js

Hapi.js - Unable to serve static file in SPA


I have just attempted to make a SPA but i am not able to resolve index.html dependencies (like including associated css, js files). All the js and css file are not able to load into browser and show 404 error in dev console.

/root
|
|__public
|      └── spa
|          ├── controllers
|          ├── css
|          ├── html
|          ├── js-self
|          ├── js-vendor
|          └── services
|_____________ index.html

Route declaration

var assets = function(){
    return {
        method: 'GET',
        path: '/{param*}',
        handler: {
            directory :{
                path : 'public',
                index: false
            }
        }
    }
}

Order of all routes

  info: ================Registered routes=============
info: Route:    GET /employee
info: Route:    POST    /employee
info: Route:    PUT /employee
info: Route:    DELETE  /employee
info: Route:    POST    /signin
info: Route:    POST    /signup
info: Route:    POST    /signout
info: Route:    GET /{param*}
info: Route:    GET /
info: =============================================

Html file

<!DOCTYPE html>
<!-- saved from url=(0058)http://getbootstrap.com/examples/starter-template/#contact -->
<html lang="en" ng-app="ibs">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Starter Template for Bootstrap</title>
    <script src="./public/spa/js-vendor/jquery-2.1.3.min.js"></script>
    <script src="./public/spa/js-vendor/angular-1.3.14.js"></script>
    <script src="./public/spa/js-vendor/angular-route.js"></script>
    <script src="./public/spa/app.js"></script>
    <link href="./public/spa/css/signin.css" rel="stylesheet">
    <link href="./public/spa/css/bootstrap.min.css" rel="stylesheet">
    <link href="./public/spa/css/starter-template.css" rel="stylesheet">

    <style type="text/css" media="screen">
        .appbkg {
          background: #303F9F
        }
    </style>
  </head>

  <body class="appbkg">
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="http://getbootstrap.com/examples/starter-template/#">Project name</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="http://getbootstrap.com/examples/starter-template/#">Home</a></li>
            <li><a href="http://getbootstrap.com/examples/starter-template/#about">About</a></li>
            <li><a href="./Starter Template for Bootstrap_files/Starter Template for Bootstrap.html">Contact</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

    <div class="container" ng-view>
    </div><!-- /.container -->


    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="./public/spa/js-vendor/bootstrap.js"></script>
</body></html>

Solution

  • I made it work with this little edit:

    var assets = function(){
    return {
        method: 'GET',
        path: '/{param*}',
        handler: {
            directory :{
                path : './',
                index: false
            }
        }
    }
    }
    

    the ./ path is actually relative to where you are when you run node app.js.

    So make sure you are in the root folder when you run it. As node ../app.js doesn't work !!

    Since that's not very clean, avoid using paths that way and stick to using path.join(__dirname, 'path/to/folder') with __dirname as a reference. Here is a cleaner solution for you

    var assets = function(){
    return {
        method: 'GET',
        path: '/{param*}',
        handler: {
            directory :{
                path : path.join(__dirname, '../..'),
                index: false
            }
        }
    }
    }
    

    Note from node's docs

    __dirname is :

    The name of the directory that the currently executing script resides in.