Search code examples
node.jsreactjsisomorphic-javascript

can I create a route that could be use both for serving HTML and REST API?


Okay here's the scenario, to my knowledge there are three ways to create a web application

  1. Traditional way: Render the HTML page from the server
  2. Not sure: Create an API and let the user's browser to download the Javascript application (Angular, React, Ember) to get a highly interactive application
  3. The future: Isomorphic web app, which render the HTML together with the client-side technologies (Angular, React, Ember) from the server.

I'm planning to use the third way, due to faster load page, but the problem right now is if I were about to create a mobile application.

My stack: Node.js + React

Let say if I'm planning to go mobile, do i need to duplicate the same route and logic ? Current problem

app.get('/users', function(req, res) {
   res.render('index', { message: "Hey Im Jack" });
});

app.get('/api/users', function(req, res) {
   res.json({ message: "Hey Im Jack" })
});

Is there any way that I could use to for one route to serve both the HTML and REST?


Solution

  • You can ultimately only send either HTML or JSON (in case of REST).

    The /api/xxx route syntax makes it clearer which path serves the JSON.

    But you can depend on client's request header to check whether they requested JSON or HTML

    app.get('/users', function(req, res) {
        if (req.headers.accept && req.headers.accept.match(/json/))
            res.json(data);
        else
            res.render('index', data);
    });
    

    Angular's $http usually requests json by default, not sure about others, but you can set the headers. Browsers normally request text/html, but I'm not sure.

    Or if you're only concerned about not having to repeat the logic that fetches the data, you could put a middleware preceeding both:

    // regex to match both routes
    app.get(/.*users/, function(req, res) {
       res.locals.data = { message: "Hey Im Jack" };
       req.next();
    });
    
    app.get('/users', function(req, res) {
       res.render('index', res.locals.data);
    });
    
    app.get('/api/users', function(req, res) {
       res.json(res.locals.data)
    });