Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack bundled express app fails to lookup view

I run npm run start and server is running fine. When I attempt to view client at localhost, server returns error: GET / 500 62.700 ms - 2028 Error: Failed to lookup view "error" in views directory "/views"

The application runs fine when just using source files. This error occurs when running application from webpack bundle.

What are the differences between source and bundled files that would make this error occur?

  • npm:3.8.2
  • node: 4.2.6
  • express: 4.13.1
  • webpack: 1.12.13
  • babel-loader: 6.2.4

webpack.config.js

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

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

module.exports = [
  {
    entry: {
      'app_bundle': './server.js'
    },
    target: 'node',
    query: {
      cacheDirectory: true,
      presets: ['es2015']
    },
    module: {
      loaders: [
        {
          test: /\.js$/,
          loader: 'babel',
          exclude: /node_modules/
        }
      ]
    },
    resolve: {
      extensions: ['', '.js']
    },
    output: {
      path: './',
      filename: '[name].js'
    },
    externals: nodeModules
  },
  {
    entry: [
      './src/index.jsx'
    ],
    target: 'web',
    query: {
      cacheDirectory: true,
      presets: ['es2015']
    },
    module: {
      loaders: [
        {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel'
        },
        {
          test: /\.css$/,
          loader: 'style!css!autoprefixer'
        },
        { test: /\.(woff|woff2)$/,  loader: "url-loader?limit=10000&mimetype=application/font-woff" },
        { test: /\.ttf$/,    loader: "file-loader" },
        { test: /\.eot$/,    loader: "file-loader" },
        { test: /\.svg$/,    loader: "file-loader" }
      ]
    },
    resolve: {
      alias: {
        'react': path.join(__dirname, 'node_modules', 'react')
      },
      extensions: ['', '.js', '.jsx']
    },
    output: {
      path: __dirname + '/public',
      publicPath: '/',
      filename: 'webpack_bundle.js'
    }
  }
];

The error trace tells me that the error is being handled by the production error handler in my app.js file:

// production error handler
app.use(function(err, req, res, next) {
  console.log(err);
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

I console.log the error with the following output:

{ [Error: Failed to lookup view "error" in views directory "/views"]
  view: 
   View {
     defaultEngine: 'ejs',
     ext: '.ejs',
     name: 'error',
     root: '/views',
     engine: [Function],
     path: undefined } }

View engine setup

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

I'm not sure how to start debugging...

like image 526
Hunter Lester Avatar asked Mar 23 '16 19:03

Hunter Lester


1 Answers

I believe the answer lies in how webpack handles the special __dirname global variable. Webpack's default behavior is to replace __dirname with the "mock" value /. This can be seen in the error you get from express where it's looking for a file at the root of /views, not ./views.

The solution is to add the following section to your webpack configuration:

node: {
  __dirname: true
}

Here's the docs which explain this behavior: https://webpack.github.io/docs/configuration.html#node

like image 128
cjhveal Avatar answered Oct 22 '22 00:10

cjhveal