1

I try to set up an express server to host my react single page application. When I run my script and open http://localhost:8080 on my browser, the index.html file is loaded and I can navigate through my application.

But when I refresh the page while the url contains some path (e.g. http://localhost/items instead of http://localhost/) I get the following error:

Error: ENOENT: no such file or directory, stat '/index.html'

If I remove the path of the url http://localhost/ and refresh the page, I get the index.html again and the applications works again.

import http from 'http';
import https from 'https';
import express from 'express';
import path from 'path';
import cors from 'cors';

var env = {
    proc: 'http',
    port: 8080,
    host: 'localhost',
};

app.use(cors());
app.options('*',cors());
app.use(function allowCrossDomain(req,res,next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
});

app.use(express.static('./build/public'));

app.get('*', function(req, res) { 
    console.log('test');

    //These don't work
    return res.sendFile(__dirname + 'index.html'); 
    //return res.sendFile(path.resolve(__dirname + 'index.html', '../'))
    //return res.sendFile('public/index.html' , { root : __dirname});
    //return res.sendFile('index.html');
});

var server = (env.proc != 'https') 
             ? http.createServer(app)
             : https.createServer(null, app);

server.listen(env.port, function() {
    console.log('' + env.proc + '://' + env.host + ':' + env.port + ' listening...'); 
});

I thought in using the * on app.get('*', function(req, res) { ... }); the server would respond on every get call with the response which is given as the second parameter (which should be sending the index.html file as a response). So both on both http://localhost:8080 and http://localhost/items the server should response with the index file. But this doesn't work.

I have tried to replace the response

return res.sendFile(__dirname + 'index.html'); 

with the following responses

return res.sendFile(path.resolve(__dirname + 'index.html', '../'))

But I get the same error. I have also tried this

return res.sendFile('public/index.html' , { root : __dirname});

But then I get this error

Error: ENOENT: no such file or directory, stat '/public/index.html'

Here is my webpack.server.js

var webpack = require('webpack');
var path = require('path');
var fs = require('fs');

var nodeModules = {};

fs.readdirSync('node_modules')
  .filter((x) => {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach((mod) => {
    nodeModules[mod] = 'commonjs ' + mod;
  });

module.exports = {
  entry: ['./src/index.js'],
  target: 'node',
  mode: 'development',  
  output: {
    filename: 'server.js',
    path: path.join(__dirname, '../', 'build'),
  },
  externals: nodeModules,
  plugins: [
    new webpack.IgnorePlugin(/\.(css|less)$/),
    new webpack.BannerPlugin({ 
      banner: 'require("source-map-support").install();',
      entryOnly: false,
      raw: true,
    }),
  ],
  devtool: 'sourcemap'

};

My npm scripts

"scripts": {
    "build:server": "webpack --config config/webpack.server.js --watch",
    "build:client": "webpack --config config/webpack.client.js --watch",
    "start": "nodemon build/server.js"
},

I have already looked up a bunch of posts with the same question, but these didn't work for me

node.js - TypeError: path must be absolute or specify root to res.sendFile

TypeError: path must be absolute or specify root to res.sendFile

Express.js “path must be absolute or specify root to res.sendFile” error

node.js TypeError: path must be absolute or specify root to res.sendFile [failed to parse JSON]

Can someone help with this one?

Olli
  • 658
  • 5
  • 26

0 Answers0