Render basic HTML view?

499,424

Solution 1

You can have jade include a plain HTML page:

in views/index.jade

include plain.html

in views/plain.html

<!DOCTYPE html>
...

and app.js can still just render jade:

res.render(index)

Solution 2

Many of these answers are out of date.

Using express 3.0.0 and 3.1.0, the following works:

app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);

See the comments below for alternative syntax and caveats for express 3.4+:

app.set('view engine', 'ejs');

Then you can do something like:

app.get('/about', function (req, res)
{
    res.render('about.html');
});

This assumes you have your views in the views subfolder, and that you have installed the ejs node module. If not, run the following on a Node console:

npm install ejs --save

Solution 3

From the Express.js Guide: View Rendering

View filenames take the form Express.ENGINE, where ENGINE is the name of the module that will be required. For example the view layout.ejs will tell the view system to require('ejs'), the module being loaded must export the method exports.render(str, options) to comply with Express, however app.register() can be used to map engines to file extensions, so that for example foo.html can be rendered by jade.

So either you create your own simple renderer or you just use jade:

 app.register('.html', require('jade'));

More about app.register.

Note that in Express 3, this method is renamed app.engine

Solution 4

You could also read the HTML file and send it:

app.get('/', (req, res) => {
    fs.readFile(__dirname + '/public/index.html', 'utf8', (err, text) => {
        res.send(text);
    });
});

Solution 5

try this. it works for me.

app.configure(function(){

  .....

  // disable layout
  app.set("view options", {layout: false});

  // make a custom html template
  app.register('.html', {
    compile: function(str, options){
      return function(locals){
        return str;
      };
    }
  });
});

....

app.get('/', function(req, res){
  res.render("index.html");
});
Share:
499,424

Related videos on Youtube

aherrick
Author by

aherrick

http://twitter.com/andrew_herrick http://andrewherrick.com Run, code, slick.

Updated on December 24, 2020

Comments

  • aherrick
    aherrick over 3 years

    I have a basic node.js app that I am trying to get off the ground using Express framework. I have a views folder where I have an index.html file. But I receive the following error when loading the web browser.

    Error: Cannot find module 'html'

    Below is my code.

    var express = require('express');
    var app = express.createServer();
    
    app.use(express.staticProvider(__dirname + '/public'));
    
    app.get('/', function(req, res) {
        res.render('index.html');
    });
    
    app.listen(8080, '127.0.0.1')
    

    What am I missing here?

  • Teo Choong Ping
    Teo Choong Ping over 12 years
    sendfile is not cache in production mode so this is not a good solution.
  • Bijou Trouvaille
    Bijou Trouvaille over 12 years
    had trouble with the exact configuration above, so I removed the dot from ".html" and added this: app.set('view engine', 'html'); app.set('views', __dirname + '/views'); for a perfect render
  • enyo
    enyo about 12 years
    This is a bit weird... you should serve html as static files. This also gives you the benefit of better caching. Creating a custom "html compiler" seems wrong. If you need to send a file from within a route (which you very rarely need to do) just read and send it. Otherwise just redirect to the static html.
  • Kyeotic
    Kyeotic almost 12 years
    @Enyo this comment seems odd, considering HOW TO do what you are saying should be done is THE QUESTION BEING ASKED, and your answer is to just do it. How do you serve a static html with caching?
  • enyo
    enyo almost 12 years
    @Tyrsius, well not really. I'm saying that you shouldn't just render an html file. If you really really have to send it from within a route you could read the file with fs and then send the plain text. What I suggest doing is redirecting to the html file instead of trying to directly render it inside the route.
  • S.D.
    S.D. almost 12 years
    Note- app.register has been renamed app.engine in Express 3.
  • Drew Noakes
    Drew Noakes almost 12 years
    I see an error on app.register. Perhaps it's been deprecated in express 3.0.0.rc3? TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'register'
  • Drew Noakes
    Drew Noakes almost 12 years
    Do you have to install ejs globally?
  • Marcel Falliere
    Marcel Falliere over 11 years
    this solution is bad because no caching of the files ; it is read for every request.
  • Naman Goel
    Naman Goel over 11 years
    its potentially pretty easy to cache it manually. Just store the read file a variable, and only read again, if that variable is blank. You could also use a JS object and store various files in various variables, with timestamps. Sure its more work than most people would do, but it's good with people new to node. It's easy to understand
  • sma
    sma over 11 years
    This suggestion worked for me. All others seemed to either render the view showing the markup on screen or gave me errors in the node console. This was the only one that truly rendered the correct HTML.
  • MetaGuru
    MetaGuru over 11 years
    it's tell me it can't find the 'index.html' file
  • Diosney
    Diosney over 11 years
    Just to note that what I want was to serve only one .html file because my app was single page ;)
  • fatuhoku
    fatuhoku about 11 years
    Why do you repeat app.use(express.static(__dirname + '/public')); after you start the server with app.listen?
  • David Betz
    David Betz almost 11 years
    @enyo, you missed the point of the steamlined architecture. When the pattern is controller/view (or /processor/view, whatever your specific architecture is), you can't deviate from that with with the obsolete model of extensions. You need to treat your HTML as rendered content like everything else. Keep it DRY, dude.
  • David Betz
    David Betz almost 11 years
    Yikes. This defeats the entire point of convention-oriented, streamlined architectures (like MVC).
  • David Betz
    David Betz almost 11 years
    See answer from Andrew Homeyer. It is the actual answer.
  • Transcendence
    Transcendence almost 11 years
    why does the res.render require the .html extension in this case but not in the default case with jade. with the boilerplate code, it just calls res.render('index', { title: 'Express' }); but here, it's : res.render('about.html');
  • Drew Noakes
    Drew Noakes almost 11 years
    @Transcendence, I'm not sure exactly. Perhaps you should open a new question.
  • roland
    roland over 10 years
    With Express 3.4.2: app.set('view engine', 'ejs');
  • Tom Teman
    Tom Teman about 10 years
    You should use the command 'npm install ejs --save' to update your package.json
  • paulcpederson
    paulcpederson about 10 years
    This answer is excellent. Note you can also keep using layout and just put the include inside the content block.
  • Tyler
    Tyler about 10 years
    @roland app.set('view engine', 'ejs'); only worked for me (express 3.5.1) when running from within same directory. To run, e.g. via startup script, I still had to do app.set('views', __dirname + '/views');. Just mentioning in case others have this issue.
  • user3398326
    user3398326 almost 10 years
    Can We included multiple HTML/JS pages with this method ?
  • Benny Schmidt
    Benny Schmidt about 9 years
    @MarcelFalliere You're assuming that he wants to cache the file, or that he doesn't want to use a custom caching solution. Thank you keegan3d for the answer.
  • CrazyPyro
    CrazyPyro about 9 years
    From some other answer, for Express 4 I ended up using app.engine('.html', require('ejs').renderFile);
  • Lygub Org
    Lygub Org almost 9 years
    it gives me the following error "Error: Cannot find module 'ejs' at Function.Module._resolveFilename (module.js:338:15) at Function.Module._load (module.js:280:25) at Module.require (module.js:364:17) at require (module.js:380:17) "
  • Daniel Huang
    Daniel Huang over 8 years
    In express 4, you could also use: app.set('view engine', 'jade');
  • A1rPun
    A1rPun over 8 years
    @LygubOrg run npm install ejs --save in your working directory.
  • PositiveGuy
    PositiveGuy about 8 years
    shouldn't you be able to render that html page without a jade template just for initial testing of express?
  • PositiveGuy
    PositiveGuy about 8 years
    what's the diff of serving the html page as static vs. just loading it non-static with express?
  • PositiveGuy
    PositiveGuy about 8 years
    why do you need ejs?
  • KhoPhi
    KhoPhi about 8 years
    @SeymourCakes Kindly correct me if I'm wrong, but I think sendFile now supports caching: devdocs.io/express/index#res.sendFile
  • xgqfrms
    xgqfrms over 7 years
  • Chris - Jr
    Chris - Jr over 6 years
    So do we have to create a jade template for each of our HTML files?
  • JCarlosR
    JCarlosR over 6 years
    is it necessary to add a dependency only to serv a html file?
  • JCarlosR
    JCarlosR over 6 years
    I currently have app.set('view engine', 'hbs'); should I attach another dependency (ejs)?
  • JCarlosR
    JCarlosR over 6 years
    @MarcelFalliere Then, what is the right solution? I see other answers that requiere new dependencies. Is it necessary just for serve html files?
  • Ozil
    Ozil over 6 years
    More of a hack rather than a solution.
  • Marcel Falliere
    Marcel Falliere over 6 years
    @benny @JCarlos the right solution IIMO is to use the static middleware of express.
  • harshad
    harshad over 5 years
    This solution worked for me. Although I tried static option too. Can you explain the mechanism behind it. Thanks!
  • Robert Daraż
    Robert Daraż over 4 years
    Everything works but remember about correct path. For me works app.set('views', '../public/views'); because I have server.js and app.js in different location.
  • vighnesh153
    vighnesh153 over 4 years
    What is this mess?
  • Vlado
    Vlado about 4 years
    Hi, how you pass locals to the view in this case? For example how you handle in 'index.html' this locals.title?: router.get('/', function(req, res){ res.render('index', {locals: {title: 'Welcome!'}}); }); I tried ${title} and <%= title%?> but no success.
  • Tony
    Tony almost 4 years
    As suggested above, this answer only works when using Jade template system. It doesn't work with e.g. handlebars.
  • Tony
    Tony almost 4 years
    I had to use var app = express(); app.set('views', path.join(__dirname, '../views'));. Without the "../folderName" it was looking in the routes folder.
  • Sam007
    Sam007 over 3 years
    server.configure is deprecated, so directly use server.use
  • VPaul
    VPaul over 3 years
    Make sure to install jade i.e. npm i jade to use this setup
  • xgqfrms
    xgqfrms about 3 years
    awesome,I like native node.js API
  • Shaikh Shahid
    Shaikh Shahid about 3 years
    One of the easiest approaches is sending the HTML back to the browser. ``` router.get('/about',function(req,res){ res.sendFile(path.join(__dirname+'/about.html')); }); ``` Or using rendering engines like Pug or Jade. I personally believe that sending the HTML build from frameworks like React.js is the easiest way to achieve rendering of the apps. This codeforgeek.com/render-html-file-expressjs covers most of it.
  • ThN
    ThN almost 3 years
    Even though this answer is old and it didn't exactly work as described here, I managed to get this to work in a weird way. All the prep work for this answer worked, but when it came to actually rendering a html file, it threw up the same error OP mentioned in his question; Cannot find module 'html.' Then, I realized that regardless of what content is in the file just as long as the file extension is ejs, render procedure renders and client displays it with no errors. So, I changed all of my html files' extension to ejs and they are all being rendered successfully. Horay!!! :)
  • Andrew Nessin
    Andrew Nessin about 2 years
    I have just one html file because I am using create-react-app and I need to serve the same HTML file for all URLs for react-router to work correctly. This solution seems perfect when I cache the contents in a variable!