238

I'm trying to find out how to load and render a basic HTML file so I don't have to write code like:

response.write('...<p>blahblahblah</p>...');
nyedidikeke
  • 6,899
  • 7
  • 44
  • 59
Just a guy
  • 5,812
  • 4
  • 21
  • 25

24 Answers24

271

I just found one way using the fs library. I'm not certain if it's the cleanest though.

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


fs.readFile('./index.html', function (err, html) {
    if (err) {
        throw err; 
    }       
    http.createServer(function(request, response) {  
        response.writeHeader(200, {"Content-Type": "text/html"});  
        response.write(html);  
        response.end();  
    }).listen(8000);
});

The basic concept is just raw file reading and dumping the contents. Still open to cleaner options, though!

Natan Streppel
  • 5,759
  • 6
  • 35
  • 43
Just a guy
  • 5,812
  • 4
  • 21
  • 25
  • 16
    you should use fs.readFileSync in your case, it would be bad for the page to come up as undefined. But yes, that's a good way to make a basic html server – generalhenry Jan 18 '11 at 06:30
  • Next you could add simple template caching, something like: cache['index'] = data; // Given var cache = {}; – TK-421 Jan 18 '11 at 12:42
  • 1
    `sys = require('util')` is not needed since nothing is printed to the console. – Bakudan Dec 09 '11 at 06:33
  • I think the response.close() must be changed to response.end() – Anand Sunderraman May 11 '12 at 08:47
  • 2
    This reads the whole file into memory, and on every request. You should really be streaming the file from disk rather than buffering it. Good quality libraries exist for this kind of thing, such as http://www.senchalabs.org/connect/ and https://github.com/cloudhead/node-static – Drew Noakes Aug 17 '12 at 14:16
  • 9
    I think it should be **writeHead(...)** not *writeHeader(...)*...[Node.js response.writeHead()](http://nodejs.org/api/http.html#http_response_writehead_statuscode_reasonphrase_headers) – Danny Bullis May 02 '13 at 16:51
  • 1
    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:34
  • 3
    @generalhenry Better yet, the call to `fs.readFile` could be placed inside the call to `http.createServer`, allowing the error to be handled. Use Stephen's answer with `if (err) { console.log('something bad'); return res.end('Oops! Something bad happened.');}` The `return` statement is the simple thing that new users might overlook. – eenblam Jun 16 '15 at 12:18
67

use app.get to get the html file. it's simple!

const express = require('express');
const app = express();

app.get('/', function(request, response){
    response.sendFile('absolutePathToYour/htmlPage.html');
});

its as simple as that. For this use express module. Install express: npm install -g express

Mehan Alavi
  • 278
  • 3
  • 17
Muhammed Neswine
  • 2,028
  • 1
  • 20
  • 20
46

You can echo files manually using the fs object, but I'd recommend using the ExpressJS framework to make your life much easier.

...But if you insist on doing it the hard way:

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

http.createServer(function(req, res){
    fs.readFile('test.html',function (err, data){
        res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
        res.write(data);
        res.end();
    });
}).listen(8000);
Stephen
  • 7,994
  • 9
  • 44
  • 73
  • 7
    Yeah, that's roughly the same thing I cam up with. Thanks for the Express suggestion too. It's pretty sweet, and I'm pretty sure I'll be using it for my next project. My goal was to kinda figure out how it's done under the hood before I let the framework do the heavy lifting for me. – Just a guy Jan 18 '11 at 22:39
  • 1
    firewall of anti virus can be disable this move – Mohammad Farahani Sep 02 '17 at 06:19
22

This would probably be some what better since you will be streaming the file(s) rather than loading it all into memory like fs.readFile.

var http = require('http');
var fs = require('fs');
var path = require('path');
var ext = /[\w\d_-]+\.[\w\d]+$/;

http.createServer(function(req, res){
    if (req.url === '/') {
        res.writeHead(200, {'Content-Type': 'text/html'});
        fs.createReadStream('index.html').pipe(res);
    } else if (ext.test(req.url)) {
        fs.exists(path.join(__dirname, req.url), function (exists) {
            if (exists) {
                res.writeHead(200, {'Content-Type': 'text/html'});
                fs.createReadStream('index.html').pipe(res);
            } else {
                res.writeHead(404, {'Content-Type': 'text/html'});
                fs.createReadStream('404.html').pipe(res);
        });
    } else {
        //  add a RESTful service
    }
}).listen(8000);
user2428926
  • 221
  • 2
  • 2
22

I know this is an old question, but as no one has mentioned it I thought it was worth adding:

If you literally want to serve static content (say an 'about' page, image, css, etc) you can use one of the static content serving modules, for example node-static. (There's others that may be better/worse - try search.npmjs.org.) With a little bit of pre-processing you can then filter dynamic pages from static and send them to the right request handler.

Paul
  • 1,874
  • 1
  • 19
  • 26
  • 1
    The answer doesn't load the js file correctly, using node-static solves my problem. – AZ. Mar 28 '12 at 04:31
18

It's more flexible and simple way to use pipe method.

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

http.createServer(function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  var file = fs.createReadStream('index.html');
  file.pipe(response);

}).listen(8080);

console.log('listening on port 8080...');
Devsullo
  • 864
  • 1
  • 9
  • 14
17

This is an update to Muhammed Neswine's answer

In Express 4.x, sendfile has been deprecated and sendFile function has to be used. The difference is sendfile takes relative path and sendFile takes absolute path. So, __dirname is used to avoid hardcoding the path.

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

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname + '/folder_name/filename.html'));
});
Community
  • 1
  • 1
Mit Mehta
  • 779
  • 8
  • 13
  • 1
    Can you check your use of `path.join` - should be `path.join(__dirname, 'folder_name', 'filename.html')` I think? – Peter Hull Mar 10 '22 at 21:41
13

Best way i learnt is using express with html files as express gives lots of advantage. Also you can extend it to a Heroku platform if you want..Just saying :)

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(3000);



console.log("Running at Port 3000");

Clean and best..!!!

Kaushik Ray
  • 555
  • 2
  • 8
  • 21
9

It's just really simple if you use pipe. The following is the server.js code snippet.

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

function onRequest(req, res){

    console.log("USER MADE A REQUEST. " +req.url);
    res.writeHead(200, {'Content-Type': 'text/html'});
    var readStream = fs.createReadStream(__dirname + '/index.html','utf8'); 
    
/*include your html file and directory name instead of <<__dirname + '/index.html'>>*/

    readStream.pipe(res);

}

http.createServer(onRequest).listen(7000);
console.log('Web Server is running...');
Abrar_11648
  • 368
  • 4
  • 7
  • In case anyone tries to extend this to returning arbitrary files in arbitrary nested directories, make sure you check that the directory your user passed doesn't include things like `../`. If were to do nothing but change `__dirname + "/index.html'` to something like `__dirname + requestedPageFromHeader`, I believe the resulting code would have this vulnerability. Directory pathing characters like `~` will be fine as long as you include the `__dirname +` - if the user can determine the start of the path will need to check for these as well. – Jon May 08 '20 at 18:59
7

The easy way to do is, put all your files including index.html or something with all resources such as CSS, JS etc. in a folder public or you can name it whatever you want and now you can use express js and just tell app to use the _dirname as :

In your server.js using express add these

var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));

and if you want to have seprate directory add new dir under public directory and use that path "/public/YourDirName"

SO what we are doing here exactly? we are creating express instance named app and we are giving the adress if the public directory to access all the resources. Hope this helps !

Muaaz salagar
  • 759
  • 7
  • 12
6
   var http = require('http');
   var fs = require('fs');

  http.createServer(function(request, response) {  
    response.writeHeader(200, {"Content-Type": "text/html"});  
    var readSream = fs.createReadStream('index.html','utf8')
    readSream.pipe(response);
  }).listen(3000);

 console.log("server is running on port number ");
Siddharth Shukla
  • 1,063
  • 15
  • 14
5

How about using express module?

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

    app.get('/',function(request,response){
       response.sendFile(__dirname+'/XXX.html');
    });

    app.listen('8000');

then, you can use browser to get /localhost:8000

李杰駿
  • 59
  • 1
  • 2
4

I think this would be a better option as it shows the URL running the server:

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

const hostname = '<your_machine_IP>';
const port = 3000;

const html=fs.readFile('./index.html', function (err, html) {
    if (err) {
        throw err; 
    }
        http.createServer(function(request, response) {  
        response.writeHeader(200, {"Content-Type": "text/html"});  
        response.write(html);  
        response.end();  
    }).listen(port, hostname, () => {
            console.log(`Server running at http://${hostname}:${port}/`);
        })
}); 
sghazagh
  • 41
  • 3
3

You could also use this snippet:

var app = require("express");
app.get('/', function(req,res){
   res.sendFile(__dirname+'./dir/yourfile.html')
});
app.listen(3000);
heyTanay
  • 51
  • 1
  • 6
2

I know this is an old question - here is a simple file server utility if you'd prefer to not use connect or express; but rather the http module.

var fileServer = require('./fileServer');
var http = require('http');
http.createServer(function(req, res) {
   var file = __dirname + req.url;
   if(req.url === '/') {
       // serve index.html on root 
       file = __dirname + 'index.html'
   }
   // serve all other files echoed by index.html e.g. style.css
   // callback is optional
   fileServer(file, req, res, callback);

})
module.exports = function(file, req, res, callback) {
    var fs = require('fs')
        , ext = require('path').extname(file)
        , type = ''
        , fileExtensions = {
            'html':'text/html',
            'css':'text/css',
            'js':'text/javascript',
            'json':'application/json',
            'png':'image/png',
            'jpg':'image/jpg',
            'wav':'audio/wav'
        }
    console.log('req    '+req.url)
    for(var i in fileExtensions) {
       if(ext === i) {    
          type = fileExtensions[i]
          break
       }
    }
    fs.exists(file, function(exists) {
       if(exists) {
          res.writeHead(200, { 'Content-Type': type })
          fs.createReadStream(file).pipe(res)
          console.log('served  '+req.url)
          if(callback !== undefined) callback()
       } else {
          console.log(file,'file dne')
         }  
    })
}
ThePixelPony
  • 721
  • 2
  • 8
  • 30
user548
  • 31
  • 1
  • 6
2

This is a pretty old question...but if your use case here is to simply send a particular HTML page to the browser on an ad hoc basis, I would use something simple like this:

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

var server = http.createServer(function(req, res){
  var stream = fs.createReadStream('test.html');
  stream.pipe(res);
});
server.listen(7000);
granmoe
  • 312
  • 1
  • 11
2

use ejs instead of jade

npm install ejs

app.js

app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

./routes/index.js

exports.index = function(req, res){
res.render('index', { title: 'ejs' });};
Saurabh Chandra Patel
  • 12,712
  • 6
  • 88
  • 78
2

You can load HTML directly in end method

response.end('...<p>blahblahblah</p>...')

It's the same as

response.write('...<p>blahblahblah</p>...')
response.end()
mecdeality
  • 405
  • 4
  • 13
2

You can use Express to load and render basic HTML files with Node. This takes about 10 minutes to get going. It's tied to the http.createServer() so your still in the land of Node and can remove it with ease.

// app.js
const path = require('path');
const express = require('express');

const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', express.static('index.html'));
app.use('/test', express.static('test.html'));

module.exports = app;

// server.js
const http = require('http');
const PORT = process.env.PORT || 3000;

const appServer = require('./app');
const httpServer = http.createServer(appServer);

httpServer.listen(PORT);
console.log(`Listening on port ${PORT}...`);

Kevin Genus
  • 260
  • 2
  • 7
1

Adding another option - based on the excepted answer.

For Typescript:

import { Injectable } from '@nestjs/common';
import { parse } from 'node-html-parser';
import * as fs from 'fs';
import * as path from 'path'


@Injectable()
export class HtmlParserService {


  getDocument(id: string): string {

      const htmlRAW = fs.readFileSync(
          path.join(__dirname, "../assets/files/some_file.html"),
          "utf8"
      );


      const parsedHtml = parse(htmlRAW);
      const className  = '.'+id;
      
      //Debug
      //console.log(parsedHtml.querySelectorAll(className));

      return parsedHtml.querySelectorAll(className).toString();
  }
}

(*) Example above is using with nestjs and node-html-parser.

Rot-man
  • 18,045
  • 12
  • 118
  • 124
1

try this one:

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

http.createServer((req, res) => {
    fs.readFile('./' + req.url, (err, data) => {
        if (!err) {
            var dotoffset = req.url.lastIndexOf('.');
            var mimetype = dotoffset == -1 ? 'text/plaint' : {
                '.html': 'text/html',
                '.css': 'text/css',
                '.js': 'text/javascript',
                '.jpg': 'image/jpeg',
                '.png': 'image/png',
                '.ico': 'image/x-icon',
                '.gif': 'image/gif'
            }[ req.url.substr(dotoffset) ];
            res.setHeader('Content-Type', mimetype);
            res.end(data);
            console.log(req.url, mimetype);
        } else {
            console.log('File not fount: ' + req.url);
            res.writeHead(404, "Not Found");
            res.end();
        }
    });
 }).listen(PORT);

With this, you can include js, css source-codes when linking them and you can load icons, imgs, gifs. And if you want, you can add more if you need.

1
var http = require('http');
var fs = require('fs');            //required to readfile

http.createServer(function(req, response){
    fs.readFile('index.html',function (err, data){
        response.writeHead(200);
        response.write(data);
        response.end();
    });
}).listen(8000);
//   #just use express lol

index.html is the name of your html file

Someone
  • 21
  • 4
0

we can load the html document with connect frame work. I have placed my html document and the related images in the public folder of my project where the below code and node modules present.

//server.js
var http=require('http');
var connect=require('connect');

var app = connect()
  .use(connect.logger('dev'))
  .use(connect.static('public'))
  .use(function(req, res){
   res.end('hello world\n');
 })

http.createServer(app).listen(3000);

I have tried the readFile() method of fs, but it fails to load the images, that's why i have used the connect framework.

Balayesu Chilakalapudi
  • 1,386
  • 3
  • 19
  • 43
0

https://gist.github.com/xgqfrms-GitHub/7697d5975bdffe8d474ac19ef906e906

Here is my simple demo codes for host static HTML files by using Express server!

hope it helps for you!

// simple express server for HTML pages!
// ES6 style

const express = require('express');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 3000;
const app = express();

let cache = [];// Array is OK!
cache[0] = fs.readFileSync( __dirname + '/index.html');
cache[1] = fs.readFileSync( __dirname + '/views/testview.html');

app.get('/', (req, res) => {
    res.setHeader('Content-Type', 'text/html');
    res.send( cache[0] );
});

app.get('/test', (req, res) => {
    res.setHeader('Content-Type', 'text/html');
    res.send( cache[1] );
});

app.listen(port, () => {
    console.log(`
        Server is running at http://${hostname}:${port}/ 
        Server hostname ${hostname} is listening on port ${port}!
    `);
});
xgqfrms
  • 10,077
  • 1
  • 69
  • 68