1172

I want to run a very simple HTTP server. Every GET request to example.com should get index.html served to it but as a regular HTML page (i.e., same experience as when you read normal web pages).

Using the code below, I can read the content of index.html. How do I serve index.html as a regular web page?

var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end(index);
}).listen(9615);

One suggestion below is complicated and requires me to write a get line for each resource (CSS, JavaScript, images) file I want to use.

How can I serve a single HTML page with some images, CSS and JavaScript?

Damjan Pavlica
  • 21,431
  • 6
  • 55
  • 65
idophir
  • 13,229
  • 5
  • 22
  • 20
  • 21
    Have a look at the npm module "connect". It provides such basic functionality and is the basis of many setups and other packages. – Mörre May 21 '11 at 20:53
  • 6
    You should put your solution as an answer and mark it correct. – graham.reeds Jun 02 '11 at 09:04
  • 8
    I was able to find a perfect solution by Eric B. Sowell called [Serving static files from node js](http://thecodinghumanist.com/blog/archives/2011/5/6/serving-static-files-from-node-js). Read the whole thing. Highly recommended. – idophir Jun 06 '11 at 06:38
  • 1
    Have a look at a module I wrote called Cachemere. It also automatically caches all your resources. https://github.com/topcloud/cachemere – Jon Nov 25 '13 at 05:07
  • 1
    [local-web-server](https://github.com/75lb/local-web-server) is a good example to look at – Lloyd May 10 '14 at 14:45
  • Um, doesn't your code already serve the file as a "regular webpage"? Change it to port 80 if you want to use the default port. Otherwise, you don't need anything else. – B T Oct 14 '14 at 06:49
  • I also have the requirement so I wrote one, it's a web server using one javascript file: http://github.com/supnate/single . It doesn't require any other library. – supNate Nov 10 '14 at 06:09
  • just change your content type to `text/html` – Hank W May 23 '21 at 19:49

33 Answers33

1057

Simplest Node.js server is just:

$ npm install http-server -g

Now you can run a server via the following commands:

$ cd MyApp

$ http-server

If you're using NPM 5.2.0 or newer, you can use http-server without installing it with npx. This isn't recommended for use in production but is a great way to quickly get a server running on localhost.

$ npx http-server

Or, you can try this, which opens your web browser and enables CORS requests:

$ http-server -o --cors

For more options, check out the documentation for http-server on GitHub, or run:

$ http-server --help

Lots of other nice features and brain-dead-simple deployment to NodeJitsu.

Feature Forks

Of course, you can easily top up the features with your own fork. You might find it's already been done in one of the existing 800+ forks of this project:

Light Server: An Auto Refreshing Alternative

A nice alternative to http-server is light-server. It supports file watching and auto-refreshing and many other features.

$ npm install -g light-server 
$ light-server

Add to your directory context menu in Windows Explorer

 reg.exe add HKCR\Directory\shell\LightServer\command /ve /t REG_EXPAND_SZ /f /d "\"C:\nodejs\light-server.cmd\" \"-o\" \"-s\" \"%V\""

Simple JSON REST server

If you need to create a simple REST server for a prototype project then json-server might be what you're looking for.

Auto Refreshing Editors

Most web page editors and IDE tools now include a web server that will watch your source files and auto refresh your web page when they change.

I use Live Server with Visual Studio Code.

The open source text editor Brackets also includes a NodeJS static web server. Just open any HTML file in Brackets, press "Live Preview" and it starts a static server and opens your browser at the page. The browser will auto refresh whenever you edit and save the HTML file. This especially useful when testing adaptive web sites. Open your HTML page on multiple browsers/window sizes/devices. Save your HTML page and instantly see if your adaptive stuff is working as they all auto refresh.

Web / SPA / PWA / Mobile / Desktop / Browser Ext Web Developers

Some SPA frameworks include a built in version of the Webpack DevServer that can detect source file changes and trigger an incremental rebuild and patch (called hot reloading) of your SPA or PWA web app. Here's a few popular SPA frameworks that can do this.

VueJS Developers

For VueJS developers, a favorite is Quasar Framework that includes the Webpack DevServer out of the box with switches to support server-side rendering (SSR) and proxy rules to cure your CORS issues. It includes a large number of optimized components designed to adapt for both Mobile and Desktop. These allows you to build one app for ALL platforms (SPA, SPA+SSR, PWA, PWA+SSR, Cordova and Capacitor Mobile AppStore apps, Electron Desktop Node+VueJS apps and even Browser extensions).

Another popular one is NuxtJS that also supports static HTML/CSS code generation as well as SSR or no-SSR build modes with plugins for other UI component suites.

React Framework Developers

ReactJS developers can also setup hot reloading.

Cordova/Capacitor + Ionic Framework Developers

Iconic is a mobile only hybrid component framework that now supports VueJS, React and Angular development. A local server with auto refresh features is baked into the ionic tool. Just run ionic serve from your app folder. Even better ... ionic serve --lab to view auto-refreshing side by side views of both iOS and Android.

Tony O'Hagan
  • 19,136
  • 3
  • 58
  • 65
  • 11
    `npm install live-server -g` if you want the same thing, but with auto-reload when it detects a file change –  May 14 '15 at 14:18
  • 3
    One little "gotcha" --. http-server defaults to serving the site at 0.0.0.0. Therefore, you MUST specify an IP address to have it work properly as a local test servier: `http-server -a localhost` – JESii Jun 11 '15 at 12:02
  • 1
    Yes ... 0.0.0.0 will make it bind to ALL IPs of all your IP networked devices (WiFi, Cable, Bluetooth) which is a bad idea on any public network as you may potentially get hacked. It's not so bad if you just wanted to demo your app inside a safe fire walled network to show others or connect it to your mobile device on the same network. – Tony O'Hagan Jun 12 '15 at 02:20
  • Really useful little tool. I have lots of Node apps running on my server, so I add a "-p" option to choose a port other than 8080. For example: nohup http-server -p 60080 & (starts it in background and lets you disconnect from the shell session.) You should make sure the port is open to the world, e.g.: iptables -I INPUT 1 -p tcp --dport 60090 -j ACCEPT (on many Linux systems) – Blisterpeanuts Dec 11 '17 at 22:57
  • How to run it as service, so I can use it even by closing the command prompt. Is there any tool provides this kind if not this. – Sandeep sandy Aug 09 '19 at 07:59
  • Depends on your platform. For production I'd use I'd recommend learning PM2 http://pm2.keymetrics.io/ – Tony O'Hagan Aug 11 '19 at 04:29
  • If you're wanting to deploy to the cloud ... you might also have a look at other options like: netlify, firebase (serverless). tons more. – Tony O'Hagan Aug 11 '19 at 04:31
1007

Note: This answer is from 2011. However, it is still valid.

You can use Connect and ServeStatic with Node.js for this:

  1. Install connect and serve-static with NPM

     $ npm install connect serve-static
    
  2. Create server.js file with this content:

     var connect = require('connect');
     var serveStatic = require('serve-static');
    
     connect()
         .use(serveStatic(__dirname))
         .listen(8080, () => console.log('Server running on 8080...'));
    
  3. Run with Node.js

     $ node server.js
    

You can now go to http://localhost:8080/yourfile.html

SE_net4 the downvoter
  • 21,043
  • 11
  • 69
  • 107
Gian Marco
  • 18,932
  • 8
  • 49
  • 43
  • 26
    The idea was to not use an existing library, for educational reasons, but I think using Express is a better advice than its lower level version, Connect. – idophir Dec 08 '11 at 14:33
  • 139
    The part of Express that serves static file is just Connect, so i don't see the reason to use Express for serving static files. But yes, also Express will do the job. – Gian Marco Dec 09 '11 at 08:57
  • 7
    Excellent advice. The steps above worked for my purposes very well. Thanks to Gian, Here is the link to Express where it reveals it is built on Connect, http://expressjs.com/ Here is how to use Express: http://expressjs.com/guide.html – Jack Stone Jun 25 '12 at 03:04
  • 10
    Not working for me, result Cannot GET /test.html. Should I replace __dirname with a directory name? – Timo Oct 26 '13 at 10:04
  • 1
    @Timo, is test.html under the directory you're starting `node` from? You don't have to change [`__dirname`](http://nodejs.org/docs/latest/api/globals.html#globals_dirname). – nymo Mar 02 '14 at 22:50
  • Perhaps this answer is obsolete, because all I can get is `TypeError: Object function createServer() {...} has no method 'static'` Apparently `static` is now a "middleware" for `connect`, but I don't know how to install it – JLDiaz May 30 '14 at 19:03
  • @JLDiaz `static` is replaced by [`serve-static`](https://github.com/expressjs/serve-static) in connect 3.0. A `npm install serve-static` should do the trick. – miqh May 31 '14 at 04:21
  • At this time, the "current" version of connect is 2.19.4, and the code is working on that version. When connect v3 will become the current one, i will update the answer – Gian Marco Jun 07 '14 at 07:33
  • 3
    Now, connect has changed to version 3. Therefore, one has to use serve-static as miqid described. I posted another answer with full code for connect v3. – tomet Jun 20 '14 at 17:38
  • What is up with these answers? Just tell him to `res.write(index)`. Is that really so hard? You don't need connect or express AT ALL – B T Oct 14 '14 at 06:48
  • Can anyone tell me why I am getting the html code itself and not the actual html after rendering? Tried different methods (the above one, the express, tried adding content-type for the response, nothing works. – MikeL Dec 19 '14 at 12:32
  • 1
    As of latest version of Express, serve-static has become a separate middleware. Use this to serve: `require('http').createServer(require('serve-static')('.')).listen(3000)`. Install `serve-static` first. – Devs love ZenUML May 26 '15 at 12:14
168

Check out this gist. I'm reproducing it here for reference, but the gist has been regularly updated.

Node.JS static file web server. Put it in your path to fire up servers in any directory, takes an optional port argument.

var http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs"),
    port = process.argv[2] || 8888;

http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

  fs.exists(filename, function(exists) {
    if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) filename += '/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      if(err) {        
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }

      response.writeHead(200);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");

Update

The gist does handle css and js files. I've used it myself. Using read/write in "binary" mode isn't a problem. That just means that the file isn't interpreted as text by the file library and is unrelated to content-type returned in the response.

The problem with your code is you're always returning a content-type of "text/plain". The above code does not return any content-type, but if you're just using it for HTML, CSS, and JS, a browser can infer those just fine. No content-type is better than a wrong one.

Normally the content-type is a configuration of your web server. So I'm sorry if this doesn't solve your problem, but it worked for me as a simple development server and thought it might help some other people. If you do need correct content-types in the response, you either need to explicitly define them as joeytwiddle has or use a library like Connect that has sensible defaults. The nice thing about this is that it's simple and self-contained (no dependencies).

But I do feel your issue. So here is the combined solution.

var http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs")
    port = process.argv[2] || 8888;

http.createServer(function(request, response) {

  var uri = url.parse(request.url).pathname
    , filename = path.join(process.cwd(), uri);

  var contentTypesByExtension = {
    '.html': "text/html",
    '.css':  "text/css",
    '.js':   "text/javascript"
  };

  fs.exists(filename, function(exists) {
    if(!exists) {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) filename += '/index.html';

    fs.readFile(filename, "binary", function(err, file) {
      if(err) {        
        response.writeHead(500, {"Content-Type": "text/plain"});
        response.write(err + "\n");
        response.end();
        return;
      }

      var headers = {};
      var contentType = contentTypesByExtension[path.extname(filename)];
      if (contentType) headers["Content-Type"] = contentType;
      response.writeHead(200, headers);
      response.write(file, "binary");
      response.end();
    });
  });
}).listen(parseInt(port, 10));

console.log("Static file server running at\n  => http://localhost:" + port + "/\nCTRL + C to shutdown");
Mike Laren
  • 7,388
  • 17
  • 46
  • 67
Jonathan Tran
  • 14,594
  • 9
  • 57
  • 64
  • 3
    This doesn't really solves the "problem". You return index.html as a binary file and you don't handle css and js. – idophir Nov 30 '12 at 04:58
  • 4
    It does handle css and js. It does not return index.html as a binary file. It simply copies data off of disk in whatever format it's in. Please see updates for more explanation. – Jonathan Tran Nov 30 '12 at 16:56
  • one issue with the code, it's case-sensitive, on unix for certain files, it gives 404 – Pradeep Nov 15 '13 at 09:47
  • 2
    Note that "path.exists and path.existsSync are now deprecated. Please use fs.exists and fs.existsSync." http://stackoverflow.com/a/5008295/259 – David Sykes Apr 03 '15 at 14:26
  • Far the best answers off all given here. Pure node.js and yet simple solution – Sergei Panfilov Apr 14 '16 at 08:16
  • 3
    Note that `fs.exists()` is also deprecated now. Catch the error on the `fs.stat()` rather than creating a race condition. – Matt Feb 01 '17 at 05:26
  • Also you may use mime.getType(filename) to detect content type – lexa-b Feb 20 '18 at 00:45
  • Thanks. I published **[simplatic-http-server](https://www.npmjs.com/package/simplatic-http-server)** based on the solution that has been provided in this answer (in addition to some changes and improvements). – Mir-Ismaili Jul 13 '19 at 20:38
  • its work very well. also css and js. we can also use switch for diffrent files. – zahra_shokri Feb 08 '21 at 10:40
108

You don't need express. You don't need connect. Node.js does http NATIVELY. All you need to do is return a file dependent on the request:

var http = require('http')
var url = require('url')
var fs = require('fs')

http.createServer(function (request, response) {
    var requestUrl = url.parse(request.url)    
    response.writeHead(200)
    fs.createReadStream(requestUrl.pathname).pipe(response)  // do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync) 
}).listen(9615)    

A more full example that ensures requests can't access files underneath a base-directory, and does proper error handling:

var http = require('http')
var url = require('url')
var fs = require('fs')
var path = require('path')
var baseDirectory = __dirname   // or whatever base directory you want

var port = 9615

http.createServer(function (request, response) {
    try {
        var requestUrl = url.parse(request.url)

        // need to use path.normalize so people can't access directories underneath baseDirectory
        var fsPath = baseDirectory+path.normalize(requestUrl.pathname)

        var fileStream = fs.createReadStream(fsPath)
        fileStream.pipe(response)
        fileStream.on('open', function() {
             response.writeHead(200)
        })
        fileStream.on('error',function(e) {
             response.writeHead(404)     // assume the file doesn't exist
             response.end()
        })
   } catch(e) {
        response.writeHead(500)
        response.end()     // end the response so browsers don't hang
        console.log(e.stack)
   }
}).listen(port)

console.log("listening on port "+port)
Ole Haugset
  • 3,552
  • 3
  • 19
  • 41
B T
  • 46,771
  • 31
  • 164
  • 191
  • 3
    If I'm not mistaken this solution doesn't take care of the encoding type so requests for HTML pages and images will get the same encoding. Isn't it? – idophir Oct 14 '14 at 12:06
  • 2
    @idophir Most often the encoding doesn't matter, browsers infer it based on the html tags used, or other information, or they guess really well. Like someone above mentioned, no MIME type is better than a wrong one. You can certainly use something like node-mime to figure out the mime types of files, but a fully web compliant http server is out of the scope for this question. – B T Oct 14 '14 at 18:07
  • @BT so to run this continuously would you just do something like `nohup node thisfile.js` or is there a better approach? – Rooster Mar 17 '15 at 22:11
  • 1
    @Rooster You shouldn't need anything special - simply `node thisfile.js`. It'll run, listening for new connections and returning new results, until either A. its closed by a signal, or B. some crazy error somehow causes program termination. – B T Mar 18 '15 at 01:32
  • @BT indeed. but if you wanted to close your terminal but keep node running, is there an alternative to nohupping it? perhaps some daemon that handles node servers? – Rooster Mar 18 '15 at 02:31
  • Oh I see. Those are called daemonizers. I'm not sure if nohup works for that. Forever is a popular one, and the one I currently use, tho I found I don't like it. Not sure if there are good alternatives, but forever certainly would do it for you. – B T Mar 18 '15 at 02:44
  • 1
    @Rooster Another daemonizer of some repute is found at https://github.com/Unitech/pm2 – Travelling Man May 09 '15 at 16:32
  • @Rooster - you might also want to check out systemd which is standard on all major variants of linux these days. You not only get the benefit of restarting your app in the case of a fatal application crash, but also on reboot of your system. https://rocketeer.be/articles/deploying-node-js-with-systemd/ – B T May 13 '15 at 02:12
  • Why calling `response.end()` synchronously? With the code above I always receive empty body. But if I call `response.end` on 'finish' event, then all works as expected: `response.on('finish', response.end)`. – Maxim Apr 12 '16 at 07:56
  • @Maxim Ah yeah, i see what you're saying. That does look like a logic error. But calling `response.end` on finish of the response is redundant - if you get the finish event, its already ended right? I fixed my answer, thanks! – B T Apr 12 '16 at 21:42
  • @zeel Hey, i realized that neither your '.' solution nor my baseDirectory solution actually fixed the problem. Normalizing the path does fix the problem tho - so I added it in my updated answer. – B T Apr 12 '16 at 22:21
  • `// do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync)` Why? Is this still true in 2016? – cat May 02 '16 at 01:00
  • @cat This will always be true. The reason is that any use of synchronous functions stops your thread until the operation is complete. This kills the performance of programs with multiple asynchronous continuations (like any web server). If you want synchronous-looking code without the huge performance hit, look into node fibers. – B T May 04 '16 at 01:26
  • 1
    I like this answer the best, but there are two issues: 1) It returns 200 when it should return 404; to fix I call writeHead(200) inside an 'open' callback. 2) If there is an error, the socket is left open; to fix I call response.destroy() in the 'error' callback. – Paul Brannan Aug 14 '17 at 21:03
  • @PaulBrannan Fixed 1. For 2, does `response.end()` not cover closing the socket? – B T Aug 14 '17 at 21:12
  • In earlier testing response.end() seemed to not close the socket. I tried again today and it does; I must have been doing something wrong before. – Paul Brannan Sep 06 '17 at 15:41
  • _"do NOT use fs's sync methods ANYWHERE on production (e.g readFileSync)"_ unless of course you need to and understand the consequences. :) – Madbreaks Dec 07 '17 at 00:26
  • Note that if you want an even more lightweight test you can just return a HTML page in the form of a string rather than loading it from file. Also you can keep a program running even if the terminal quits by running it using [screen](https://linux.die.net/man/1/screen) in Linux, start a terminal using `screen`, then type your command, then do Ctrl+a *followed by* Ctrl+d to detach, your program will continue to run. Note that this isn't suitable for production because if power goes out / the system reboots your program won't restart automatically. – jrh May 26 '19 at 19:25
73

I think the part you're missing right now is that you're sending:

Content-Type: text/plain

If you want a web browser to render the HTML, you should change this to:

Content-Type: text/html
clee
  • 10,355
  • 6
  • 34
  • 28
  • Thanks for the quick reply. The page now loads but without the CSS. How can I get a standard html page with the CSS and JS loaded? – idophir May 21 '11 at 21:22
  • 20
    You need to start extending that server. Right now it only knows how to serve up index.html - you need to teach it how to serve foo.css and foo.js now, with their own appropriate MIME types. – clee May 21 '11 at 22:06
  • 1
    If you don't want to serve static files, you can drop your css into a ` – Keith Mar 28 '16 at 23:25
  • 2
    After nine years, this really should be accepted as the correct answer. – rooch84 Apr 14 '20 at 08:39
47

Step1 (inside command prompt [I hope you cd TO YOUR FOLDER]) : npm install express

Step 2: Create a file server.js

var fs = require("fs");
var host = "127.0.0.1";
var port = 1337;
var express = require("express");

var app = express();
app.use(express.static(__dirname + "/public")); //use static files in ROOT/public folder

app.get("/", function(request, response){ //root dir
    response.send("Hello!!");
});

app.listen(port, host);

Please note, you should add WATCHFILE (or use nodemon) too. Above code is only for a simple connection server.

STEP 3: node server.js or nodemon server.js

There is now more easy method if you just want host simple HTTP server. npm install -g http-server

and open our directory and type http-server

https://www.npmjs.org/package/http-server

Community
  • 1
  • 1
STEEL
  • 5,589
  • 8
  • 52
  • 73
  • @STEEL, is there any way to start node server automatically. I mean without go to the directory path and then type nodeserver then only it will start. i want to start the node server like IIS. can you tell me – Vinoth Jul 05 '17 at 11:38
  • @Vinoth yes there are many ways. Whats your exact purpose or target, I may help you – STEEL Jul 06 '17 at 03:10
  • @steel i want to start server automatically without giving node server in the command promt. this is my requirement is it possible can you tell me some example – Vinoth Jul 06 '17 at 05:54
  • You will need to use Some tool like ThoughtWorks GO, which can execute Terminal commands from a click from the browser. – STEEL Jul 06 '17 at 07:09
35

The fast way:

var express = require('express');
var app = express();
app.use('/', express.static(__dirname + '/../public')); // ← adjust
app.listen(3000, function() { console.log('listening'); });

Your way:

var http = require('http');
var fs = require('fs');

http.createServer(function (req, res) {
    console.dir(req.url);

    // will get you  '/' or 'index.html' or 'css/styles.css' ...
    // • you need to isolate extension
    // • have a small mimetype lookup array/object
    // • only there and then reading the file
    // •  delivering it after setting the right content type

    res.writeHead(200, {'Content-Type': 'text/html'});

    res.end('ok');
}).listen(3001);
Benny Neugebauer
  • 40,817
  • 21
  • 196
  • 177
Frank Nocke
  • 7,493
  • 3
  • 58
  • 89
20

Rather than dealing with a switch statement, I think it's neater to lookup the content type from a dictionary:

var contentTypesByExtension = {
    'html': "text/html",
    'js':   "text/javascript"
};

...

    var contentType = contentTypesByExtension[fileExtension] || 'text/plain';
joeytwiddle
  • 24,338
  • 11
  • 107
  • 91
  • Yes, looks much more elegant than the "switch" solution used by Eric B. Sowell (see selected answer). Thanks. – idophir Dec 08 '11 at 14:30
  • This answer is totally out of context... It refers to this link within this comment -http://stackoverflow.com/questions/6084360/using-node-js-as-a-simple-web-server/8262493#comment21664337_6084360 (yeah, whatever, internet is broken) – Mars Robertson Sep 14 '15 at 12:37
15

This is basically an updated version of the accepted answer for connect version 3:

var connect = require('connect');
var serveStatic = require('serve-static');

var app = connect();

app.use(serveStatic(__dirname, {'index': ['index.html']}));
app.listen(3000);

I also added a default option so that index.html is served as a default.

tomet
  • 2,256
  • 3
  • 27
  • 42
15

You don't need to use any NPM modules to run a simple server, there's a very tiny library called "NPM Free Server" for Node:

50 lines of code, outputs if you are requesting a file or a folder and gives it a red or green color if it failed for worked. Less than 1KB in size (minified).

Jaredcheeda
  • 742
  • 7
  • 9
  • Excellent choice. Serves html, css, js, and images. Great for debugging. Just substitute this code as is for your server.js. – pollaris Aug 26 '17 at 12:34
  • 2
    I wish I could add more upvotes! This is great! I made on small change `var filename = path.join(process.cwd() + '/dist/', uri);` to server from the **dist** folder. I put the code into `server.js` and it *just works* when I type `npm start` – John Henckel Jul 10 '18 at 20:35
  • How to run it as service, so I can use it even by closing the command prompt. Is there any tool provides this kind if not this. – Sandeep sandy Aug 09 '19 at 07:57
13

if you have node installed on you PC probably you have the NPM, if you don't need NodeJS stuff, you can use the serve package for this:

1 - Install the package on your PC:

npm install -g serve

2 - Serve your static folder:

serve <path> 
d:> serve d:\StaticSite

It will show you which port your static folder is being served, just navigate to the host like:

http://localhost:3000
Diego Mendes
  • 8,767
  • 1
  • 28
  • 35
  • How to run it as service, so I can use it even by closing the command prompt. Is there any tool provides this kind if not this. – Sandeep sandy Aug 09 '19 at 07:51
  • This should be the accepted answer. Because its most easiest, and it works out of the box. Thus if you run only serve without the path, it will run server from the current folder (the one where you have CD-ed previously). – Игор Рајачић Oct 08 '19 at 09:43
11

You can just type those in your shell

npx serve

Repo: https://github.com/zeit/serve.

Geng Jiawen
  • 7,297
  • 2
  • 39
  • 36
  • Providing option `-s` or `--single`, the server rewrites all not-found requests to `index.html`. So `npx serve -s` works just like the OP wanted it. – z80crew Jan 13 '21 at 13:26
10

I found a interesting library on npm that might be of some use to you. It's called mime(npm install mime or https://github.com/broofa/node-mime) and it can determine the mime type of a file. Here's an example of a webserver I wrote using it:

var mime = require("mime"),http = require("http"),fs = require("fs");
http.createServer(function (req, resp) {
path  = unescape(__dirname + req.url)
var code = 200
 if(fs.existsSync(path)) {
    if(fs.lstatSync(path).isDirectory()) {
        if(fs.existsSync(path+"index.html")) {
        path += "index.html"
        } else {
            code = 403
            resp.writeHead(code, {"Content-Type": "text/plain"});
            resp.end(code+" "+http.STATUS_CODES[code]+" "+req.url);
        }
    }
    resp.writeHead(code, {"Content-Type": mime.lookup(path)})
    fs.readFile(path, function (e, r) {
    resp.end(r);

})
} else {
    code = 404
    resp.writeHead(code, {"Content-Type":"text/plain"});
    resp.end(code+" "+http.STATUS_CODES[code]+" "+req.url);
}
console.log("GET "+code+" "+http.STATUS_CODES[code]+" "+req.url)
}).listen(9000,"localhost");
console.log("Listening at http://localhost:9000")

This will serve any regular text or image file (.html, .css, .js, .pdf, .jpg, .png, .m4a and .mp3 are the extensions I've tested, but it theory it should work for everything)

Developer Notes

Here is an example of output that I got with it:

Listening at http://localhost:9000
GET 200 OK /cloud
GET 404 Not Found /cloud/favicon.ico
GET 200 OK /cloud/icon.png
GET 200 OK /
GET 200 OK /501.png
GET 200 OK /cloud/manifest.json
GET 200 OK /config.log
GET 200 OK /export1.png
GET 200 OK /Chrome3DGlasses.pdf
GET 200 OK /cloud
GET 200 OK /-1
GET 200 OK /Delta-Vs_for_inner_Solar_System.svg

Notice the unescape function in the path construction. This is to allow for filenames with spaces and encoded characters.

MayorMonty
  • 3,963
  • 2
  • 23
  • 40
9

Edit:

Node.js sample app Node Chat has the functionality you want.
In it's README.textfile
3. Step is what you are looking for.

step1

  • create a server that responds with hello world on port 8002

step2

  • create an index.html and serve it

step3

  • introduce util.js
  • change the logic so that any static file is served
  • show 404 in case no file is found

step4

  • add jquery-1.4.2.js
  • add client.js
  • change index.html to prompt user for nickname

Here is the server.js

Here is the util.js

Kerem Baydoğan
  • 9,716
  • 1
  • 37
  • 49
  • 5
    I don't care. I only have index.html. I just want to get the html+css+js loaded. Thanks! – idophir May 21 '11 at 21:23
  • 16
    -1 for `.readFileSync` in a callback. With node.js we use non blocking IO. Please do not recommend `Sync` commands. – Raynos May 21 '11 at 22:22
  • Hi @krmby, thanks for trying to help. I am really new at this. I downloaded both server.js and util.js. When I run "node server.js" and try to access the page using a browser, I get this error: TypeError: Object # has no method 'close' at /var/www/hppy-site/util.js:67:8 at /var/www/hppy-site/util.js:56:4 at [object Object]. (fs.js:107:5) at [object Object].emit (events.js:61:17) at afterRead (fs.js:970:12) at wrapper (fs.js:245:17) Any ideas? BTW - same is happening when I download your project and run it. – idophir May 22 '11 at 18:31
  • 1
    Sorry. I was using a new version. Replaced res.close() with res.end() – idophir May 22 '11 at 19:05
8

The way I do it is to first of all install node static server globally via

npm install node-static -g

then navigate to the directory that contains your html files and start the static server with static.

Go to the browser and type localhost:8080/"yourHtmlFile".

Benjamin W.
  • 33,075
  • 16
  • 78
  • 86
Samba
  • 157
  • 1
  • 4
7

Basically copying the accepted answer, but avoiding creating a js file.

$ node
> var connect = require('connect'); connect().use(static('.')).listen(8000);

Found it very convinient.

Update

As of latest version of Express, serve-static has become a separate middleware. Use this to serve:

require('http').createServer(require('serve-static')('.')).listen(3000)

Install serve-static first.

Community
  • 1
  • 1
Devs love ZenUML
  • 9,490
  • 7
  • 41
  • 55
7
var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    // change the to 'text/plain' to 'text/html' it will work as your index page
    res.end(index);
}).listen(9615);

I think you where searching for this. In your index.html, simply fill it with normal html code - whatever you want to render on it, like:

<html>
    <h1>Hello world</h1>
</html>
alex
  • 4,689
  • 8
  • 43
  • 83
Ashish Ranjan
  • 1,119
  • 1
  • 8
  • 8
6

I use below code to start a simple web server which render default html file if no file mentioned in Url.

var http = require('http'),
fs = require('fs'),
url = require('url'),
rootFolder = '/views/',
defaultFileName = '/views/5 Tips on improving Programming Logic   Geek Files.htm';


http.createServer(function(req, res){

    var fileName = url.parse(req.url).pathname;
    // If no file name in Url, use default file name
    fileName = (fileName == "/") ? defaultFileName : rootFolder + fileName;

    fs.readFile(__dirname + decodeURIComponent(fileName), 'binary',function(err, content){
        if (content != null && content != '' ){
            res.writeHead(200,{'Content-Length':content.length});
            res.write(content);
        }
        res.end();
    });

}).listen(8800);

It will render all js, css and image file, along with all html content.

Agree on statement "No content-type is better than a wrong one"

Sachin303
  • 76
  • 1
  • 3
6

from w3schools

it is pretty easy to create a node server to serve any file that is requested, and you dont need to install any packages for it

var http = require('http');
var url = require('url');
var fs = require('fs');

http.createServer(function (req, res) {
  var q = url.parse(req.url, true);
  var filename = "." + q.pathname;
  fs.readFile(filename, function(err, data) {
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'});
      return res.end("404 Not Found");
    }  
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(data);
    return res.end();
  });
}).listen(8080);

http://localhost:8080/file.html

will serve file.html from disk

Ahmed M. Matar
  • 401
  • 1
  • 5
  • 12
5

I'm not sure if this is exactly what you wanted, however, you can try changing:

{'Content-Type': 'text/plain'}

to this:

{'Content-Type': 'text/html'}

This will have the browser client display the file as html instead of plain text.

Xenry
  • 96
  • 1
  • 8
  • 1
    Isn't this the same as [this existing answer](http://stackoverflow.com/questions/6084360/using-node-js-as-a-simple-web-server/6084469#6084469)? – Pang Aug 31 '15 at 01:26
5

Express function sendFile does exactly what you need, and since you want web server functionality from node, express comes as natural choice and then serving static files becomes as easy as :

res.sendFile('/path_to_your/index.html')

read more here : https://expressjs.com/en/api.html#res.sendFile

A small example with express web server for node:

var express = require('express');
var app = express();
var path = require('path');

app.get('/', function(req, res) {
    res.sendFile(path.join(__dirname + '/index.html'));
});

app.listen(8080);

run this, and navigate to http://localhost:8080

To expand on this to allow you to serve static files like css and images, here's another example :

var express = require('express');
var app = express();
var path = require('path');

app.use(express.static(__dirname + '/css'));

app.get('/', function(req, res) {
    res.sendFile(path.join(__dirname + '/index.html'));
});

app.listen(8080);

so create a subfolder called css, put your static content in it, and it will be available to your index.html for easy reference like :

<link type="text/css" rel="stylesheet" href="/css/style.css" />

Notice relative path in href!

voila!

Mladen Oršolić
  • 1,282
  • 3
  • 20
  • 35
4
var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'html'});
res.end(index);
}).listen(9615);

//Just Change The CONTENT TYPE to 'html'
  • 6
    The `Content-Type` should be `text/html`, as it is defined that way: [`Content-Type := type "/" subtype *[";" parameter]`](http://www.w3.org/Protocols/rfc1341/4_Content-Type.html). – t.niese Mar 15 '14 at 21:45
  • 1
    this seems to turn all my files in that folder into html type, even if it's js... – ahnbizcad Jun 05 '16 at 07:39
4

A slightly more verbose express 4.x version but that provides directory listing, compression, caching and requests logging in a minimal number of lines

var express = require('express');
var compress = require('compression');
var directory = require('serve-index');
var morgan = require('morgan'); //logging for express

var app = express();

var oneDay = 86400000;

app.use(compress());
app.use(morgan());
app.use(express.static('filesdir', { maxAge: oneDay }));
app.use(directory('filesdir', {'icons': true}))

app.listen(process.env.PORT || 8000);

console.log("Ready To serve files !")
Bruno Grieder
  • 22,490
  • 7
  • 57
  • 88
4

Crazy amount of complicated answers here. If you don't intend to process nodeJS files/database but just want to serve static html/css/js/images as your question suggest then simply install the pushstate-server module or similar;

Here's a "one liner" that will create and launch a mini site. Simply paste that entire block in your terminal in the appropriate directory.

mkdir mysite; \
cd mysite; \
npm install pushstate-server --save; \
mkdir app; \
touch app/index.html; \
echo '<h1>Hello World</h1>' > app/index.html; \
touch server.js; \
echo "var server = require('pushstate-server');server.start({ port: 3000, directory: './app' });" > server.js; \
node server.js

Open browser and go to http://localhost:3000. Done.

The server will use the app dir as the root to serve files from. To add additional assets just place them inside that directory.

cyberwombat
  • 31,246
  • 30
  • 143
  • 210
  • 2
    If you already have statics, you can just use the following: `npm install pushstate-server --save; touch server.js; echo "var server = require('pushstate-server');server.start({ port: 3000, directory: './' });" > server.js; node server.js` – Swivel Aug 28 '15 at 07:13
4

There are already some great solutions for a simple nodejs server. There is a one more solution if you need live-reloading as you made changes to your files.

npm install lite-server -g

navigate your directory and do

lite-server

it will open browser for you with live-reloading.

lokeshjain2008
  • 1,791
  • 1
  • 20
  • 33
3

Most of the answers above describe very nicely how contents are being served. What I was looking as additional was listing of the directory so that other contents of the directory can be browsed. Here is my solution for further readers:

'use strict';

var finalhandler = require('finalhandler');
var http = require('http');
var serveIndex = require('serve-index');
var serveStatic = require('serve-static');
var appRootDir = require('app-root-dir').get();
var log = require(appRootDir + '/log/bunyan.js');

var PORT = process.env.port || 8097;

// Serve directory indexes for reports folder (with icons)
var index = serveIndex('reports/', {'icons': true});

// Serve up files under the folder
var serve = serveStatic('reports/');

// Create server
var server = http.createServer(function onRequest(req, res){
    var done = finalhandler(req, res);
    serve(req, res, function onNext(err) {
    if (err)
        return done(err);
    index(req, res, done);
    })
});


server.listen(PORT, log.info('Server listening on: ', PORT));
Abu Shumon
  • 1,378
  • 16
  • 30
3

The simpler version which I've came across is as following. For education purposes, it is best, because it does not use any abstract libraries.

var http = require('http'),
url = require('url'),
path = require('path'),
fs = require('fs');

var mimeTypes = {
  "html": "text/html",
  "mp3":"audio/mpeg",
  "mp4":"video/mp4",
  "jpeg": "image/jpeg",
  "jpg": "image/jpeg",
  "png": "image/png",
  "js": "text/javascript",
  "css": "text/css"};

http.createServer(function(req, res) {
    var uri = url.parse(req.url).pathname;
    var filename = path.join(process.cwd(), uri);
    fs.exists(filename, function(exists) {
        if(!exists) {
            console.log("not exists: " + filename);
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.write('404 Not Found\n');
            res.end();
            return;
        }
        var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
        res.writeHead(200, {'Content-Type':mimeType});

        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);

    }); //end path.exists
}).listen(1337);

Now go to browser and open following:

http://127.0.0.1/image.jpg

Here image.jpg should be in same directory as this file. Hope this helps someone :)

Kaushal28
  • 4,823
  • 4
  • 30
  • 57
3

local-web-server is definitely worth a look! Here's an excerpt from the readme:

local-web-server

A lean, modular web server for rapid full-stack development.

  • Supports HTTP, HTTPS and HTTP2.
  • Small and 100% personalisable. Load and use only the behaviour required by your project.
  • Attach a custom view to personalise how activity is visualised.
  • Programmatic and command-line interfaces.

Use this tool to:

  • Build any type of front-end web application (static, dynamic, Single Page App, Progessive Web App, React etc).
  • Prototype a back-end service (REST API, microservice, websocket, Server Sent Events service etc).
  • Monitor activity, analyse performance, experiment with caching strategy etc.

Local-web-server is a distribution of lws bundled with a "starter pack" of useful middleware.

Synopsis

This package installs the ws command-line tool (take a look at the usage guide).

Static web site

Running ws without any arguments will host the current directory as a static web site. Navigating to the server will render a directory listing or your index.html, if that file exists.

$ ws
Listening on http://mbp.local:8000, http://127.0.0.1:8000, http://192.168.0.100:8000

Static files tutorial.

This clip demonstrates static hosting plus a couple of log output formats - dev and stats.

Single Page Application

Serving a Single Page Application (an app with client-side routing, e.g. a React or Angular app) is as trivial as specifying the name of your single page:

$ ws --spa index.html

With a static site, requests for typical SPA paths (e.g. /user/1, /login) would return 404 Not Found as a file at that location does not exist. However, by marking index.html as the SPA you create this rule:

If a static file is requested (e.g. /css/style.css) then serve it, if not (e.g. /login) then serve the specified SPA and handle the route client-side.

SPA tutorial.

URL rewriting and proxied requests

Another common use case is to forward certain requests to a remote server.

The following command proxies blog post requests from any path beginning with /posts/ to https://jsonplaceholder.typicode.com/posts/. For example, a request for /posts/1 would be proxied to https://jsonplaceholder.typicode.com/posts/1.

$ ws --rewrite '/posts/(.*) -> https://jsonplaceholder.typicode.com/posts/$1'

Rewrite tutorial.

This clip demonstrates the above plus use of --static.extensions to specify a default file extension and --verbose to monitor activity.

HTTPS and HTTP2

For HTTPS or HTTP2, pass the --https or --http2 flags respectively. See the wiki for further configuration options and a guide on how to get the "green padlock" in your browser.

$ lws --http2
Listening at https://mba4.local:8000, https://127.0.0.1:8000, https://192.168.0.200:8000
Lloyd
  • 7,498
  • 2
  • 31
  • 52
3

Node.js webserver from scratch


No 3rd-party frameworks; Allows query string; Adds trailing slash; Handles 404


Create a public_html subfolder and place all of your content in it.


Gist: https://gist.github.com/veganaize/fc3b9aa393ca688a284c54caf43a3fc3

var fs = require('fs');

require('http').createServer(function(request, response) {
  var path = 'public_html'+ request.url.slice(0,
      (request.url.indexOf('?')+1 || request.url.length+1) - 1);
      
  fs.stat(path, function(bad_path, path_stat) {
    if (bad_path) respond(404);
    else if (path_stat.isDirectory() && path.slice(-1) !== '/') {
      response.setHeader('Location', path.slice(11)+'/');
      respond(301);
    } else fs.readFile(path.slice(-1)==='/' ? path+'index.html' : path,
          function(bad_file, file_content) {
      if (bad_file) respond(404);
      else respond(200, file_content);
    });
  });
 
  function respond(status, content) {
    response.statusCode = status;
    response.end(content);
  }
}).listen(80, function(){console.log('Server running on port 80...')});
veganaiZe
  • 491
  • 5
  • 12
2

This is one of the fastest solutions i use to quickly see web pages

sudo npm install ripple-emulator -g

From then on just enter the directory of your html files and run

ripple emulate

then change the device to Nexus 7 landscape.

Post Impatica
  • 10,585
  • 5
  • 48
  • 61
1

I can also recommend SugoiJS, it is very easy to set up and gives an option to start writing fast and has great features.

Take a look here to get started: http://demo.sugoijs.com/ , documentation: https://wiki.sugoijs.com/

It has request handling decorators, request policies and authorization policies decorators.

For example:

import {Controller,Response,HttpGet,RequestParam} from "@sugoi/server";
​
@Controller('/dashboard')
export class CoreController{
    constructor(){}
​
    @HttpGet("/:role")
    test(@RequestParam('role') role:string,
         @RequestHeader("role") headerRole:string){
        if(role === headerRole )
            return "authorized";
        else{
            throw new Error("unauthorized")
        }
    }
}
Gen4ik
  • 330
  • 1
  • 8
1

Is very easy with the tons of libraries presents today. Answers here are functional. If you want another version for start faster and simple

Of course first install node.js. Later:

> # module with zero dependencies
> npm install -g @kawix/core@latest 
> # change /path/to/static with your folder or empty for current
> kwcore "https://raw.githubusercontent.com/voxsoftware/kawix-core/master/example/npmrequire/express-static.js" /path/to/static

Here the content of "https://raw.githubusercontent.com/voxsoftware/kawix-core/master/example/npmrequire/express-static.js" (you don't need download it, i posted for understand how works behind)

// you can use like this:
// kwcore "https://raw.githubusercontent.com/voxsoftware/kawix-core/master/example/npmrequire/express.js" /path/to/static
// kwcore "https://raw.githubusercontent.com/voxsoftware/kawix-core/master/example/npmrequire/express.js" 

// this will download the npm module and make a local cache
import express from 'npm://express@^4.16.4'
import Path from 'path'

var folder= process.argv[2] || "."
folder= Path.resolve(process.cwd(), folder)
console.log("Using folder as public: " + folder)

var app = express() 
app.use(express.static(folder)) 
app.listen(8181)
console.log("Listening on 8181")
0

Create a Simple Node.js Web Server and Asynchronously Serve an HTML Page From a File

Creating my first node.js server, I found a simple and efficient way to do this.

Instead of loading the HTML for every request, we can load it once at the beginning. Then return the data we loaded at startup.

const host = "localhost";
const port = 5000;
const http = require("HTTP");
const fs = require("fs").promises;

let htmlFile;
const reqListenerFunc = function (req, resp) {
    resp.setHeader("Content-Type", "text/html");
    resp.writeHead(200);
    resp.end(htmlFile);
};
const simpleServer = http.createServer(reqListenerFunc);

// // Using Arrow function directly
// const simpleServer = http.createServer( (req, resp) => {
//     resp.setHeader("Content-Type", "text/html");
//     resp.writeHead(200);
//     resp.end(htmlFile);
// });

fs.readFile(__dirname + "/index.html")
    .then(content => {
        htmlFile = content;
        simpleServer.listen(port, host, () => {
            console.log(`Node.js web server is running on http://${host}:${port}`);
        });
    })
    .catch(err => {
        console.error(`Cannot read index.html file. <br> Error: ${err}`);
        process.exit(1);
    });

Read more: https://www.digitalocean.com/community/tutorials/how-to-create-a-web-server-in-node-js-with-the-http-module