Serving VueJS Builds via Express.js using history mode

12,897

Solution 1

Have a look at connect-history-api-fallback that is referenced in the vue docs. This should solve your problems.

Example using connect-history-api-fallback

var express = require('express');
var history = require('connect-history-api-fallback');
var app = express();

// Middleware for serving '/dist' directory
const staticFileMiddleware = express.static('dist');

// 1st call for unredirected requests 
app.use(staticFileMiddleware);

// Support history api
// this is the HTTP request path not the path on disk
app.use(history({
  index: '/index.html'
}));

// 2nd call for redirected requests
app.use(staticFileMiddleware);

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Solution 2

The very simpler one if anyone wants to use

Just add this below all the valid routes and above app.listen

app.all("*", (_req, res) => {
  try {
    res.sendFile('/absolute/path/to/index.html');
  } catch (error) {
    res.json({ success: false, message: "Something went wrong" });
  }
});

Make sure you have included

app.use(express.static('/path/to/dist/directory'));
Share:
12,897
tbhaxor
Author by

tbhaxor

I do full-stack developer to fund my cybersecurity and machine learning research.

Updated on June 13, 2022

Comments

  • tbhaxor
    tbhaxor almost 2 years

    I want to serve vue js dist/ via express js. I am using history router in vue js app.

    The following are the api calls

    1. api/
    2. s-file/sending/:id
    3. terms/get/:which

    As i have figured out a solution in python here. I don't know how to do it in node js with express

    The code i am using right now is

    app.use(function (req, res, next) {
        if (/api/.test(req.url))
            next();
        else {
            var file = "";
            if (req.url.endsWith(".js")) {
                file = path.resolve(path.join(distPath, req.url))
                res.header("Content-Type", "application/javascript; charset=utf-8");
                res.status(200);
                res.send(fs.readFileSync(file).toString());
            } else if (req.url.endsWith(".css")) {
                file = path.resolve(path.join(distPath, req.url))
                res.header("Content-Type", "text/css; charset=utf-8");
                res.status(200);
                res.send(fs.readFileSync(file).toString());
    
            } else {
                file = path.resolve(path.join(distPath, "index.html"))
                res.header("Content-Type", "text/html; charset=utf-8");
                res.status(200);
                res.send(fs.readFileSync(file).toString());
            }
    
        }
    })
    
  • tbhaxor
    tbhaxor over 5 years
    it will not work for vue routerlinks i.e fallbacks and moreover i am getting Cannot GET /
  • Benno
    Benno over 5 years
    My bad, have a look at the use of connect-history-api-fallback in my updated answer
  • LOG_TAG
    LOG_TAG almost 5 years
    Error: Forbidden Your client does not have permission to get URL / from this server after deploying to docker !! what does that mean ?
  • Benno
    Benno almost 5 years
    @LOG_TAG this error could have many causes either in your hosting configuration or in your server code. Consider opening a separate question where you give all the background information needed: (What are you trying to do? What is working? What isn’t? What have you tried so far)
  • LOG_TAG
    LOG_TAG almost 5 years
    @Benno sure thanks for responding, I'm dealing with same 'Serving VueJS Builds via Express.js" using google cloud run via gcloud! wondering it's going to be duplicate one :)
  • Benno
    Benno almost 5 years
    @LOG_TAG your question seems to be specific to setting up the docker hosting environment - that is out of scope for this question.
  • Abhilash KK
    Abhilash KK over 4 years
    @Benno I tried both ways, but nothing working. do I need to change anything in vuejs build?
  • Benno
    Benno over 4 years
    @Abhilash Please check the Vue docs here router.vuejs.org/guide/essentials/history-mode.html and make sure you did enable history mode in the router. If you don’t get it to work, please consider opening a new question and provide info on what you’re trying to do.
  • gbengaoyetade
    gbengaoyetade about 4 years
    Why is there an "async" when "await" is not being used in the function?
  • Admin
    Admin almost 3 years
    Can i serve more then one vuejs app using that middleware ? like serving the app and an admin page, each one of them as a separate vue app
  • Christopher Franko
    Christopher Franko about 2 years
    My man. You're the real mvp.