Html-webpack-plugin: HtmlWebpackPlugin + webpack-dev-middleware other pathname than /

Created on 17 Dec 2015  ·  29Comments  ·  Source: jantimon/html-webpack-plugin

Hello,

First, thank you for your wonderful work!

Second ,) My issue, I tried to use HtmlWebpackPlugin with dev server as middleware.
All is fine when path / but when path is /login webpack-dev-middleware return 404

Then I need something like:

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

but for HtmlWebpackPlugin or may be if it's possible, fix it by option of HtmlWebpackPlugin.

question

Most helpful comment

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

var compiler = webpack(require('./webpack.config.js'));

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: '/'
}));

app.use('*', function (req, res, next) {
  var filename = path.join(compiler.outputPath,'index.html');
  compiler.outputFileSystem.readFile(filename, function(err, result){
    if (err) {
      return next(err);
    }
    res.set('content-type','text/html');
    res.send(result);
    res.end();
  });
});

app.listen(3000);

All 29 comments

The reason is that webpack-dev-middle ware doesn't write the index.html on disk but keeps it in memory for better performance.

You could try:

new HtmlWebpackPlugin({
  filename: 'login/index.html'
})

I know ,) It's good for dev process of course.

And yes, of course, I tried. But plugin do not write index.html when webpack-dev-middle work.

The is the reason why I make issue.

Did you try the proposed solution?

I thought about it. It's really not a bug.

But sorry may be my suggestion is not great. I hope you can make better.

But anyway.

// file like HtmlWebpackPlugin.config.js
export default {
  filename: '..',
  minify: {...}
}
// webpack.config.js
import htmlConfig from HtmlWebpackPlugin.config
...
  plugins: [
    ...,
    new HtmlWebpackPlugin(htmlConfig)
 ]
...
// webpack-dev-server.js
...
app.use(new HtmlWebpackPlugin(htmlConfig).middleware)

Maybe it's separate package like webpack-html-middleware. I'm really not sure ,))

@jantimon Your solution doesn't work. Still have 404 error. My configuration:
dev-server.js:

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

webpack.config.js:

plugins: [
     new HtmlWebpackPlugin({
      template: 'src/index.html',
      filename: 'index.html',
      inject: 'body'
    }),
  ]

Hi,

I found a solution which should solve it for you: next('route');
This will tell express to execute the route again:

app.get('*', function (req, res, next) {
    req.url = 'index.html';
    next('route');
});

from: http://stackoverflow.com/a/22081112/159319

Now it says: Cannot GET /. Maybe it is because the generated file is virtual? As @Sigura mentioned above some middleware for html-webpack-plugin may solve this issue.

Hello @jantimon,

I tried this way before. Unfortunately does not work (for me).

req.url = 'index.html';
// and
req.url = '/';

and etc. result is: Cannot GET /bla-bla-bla

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

var compiler = webpack(require('./webpack.config.js'));

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: '/'
}));

app.use('*', function (req, res, next) {
  var filename = path.join(compiler.outputPath,'index.html');
  compiler.outputFileSystem.readFile(filename, function(err, result){
    if (err) {
      return next(err);
    }
    res.set('content-type','text/html');
    res.send(result);
    res.end();
  });
});

app.listen(3000);

@jantimon Sorry, it's work.

Thank-you!

ps: I missed compiler.outputFileSystem before

It works! Thank you @jantimon. This solution should go to README.

Well actually it is just webpack-dev-server.. This is just a plugin ;)
Better post this on stackoverflow and google will find it - if someone has the use case.

this solution is awesome, thks @jantimon

thks! @jantimon

thks! @jantimon

sweet! @jantimon

谢谢!@jantimon

This was so hard to find, thanks a lot @jantimon.

@jantimon
thanks for the solution, I see it works for the people, however, in my case for some reason it tells that file doesn't exist:

    Error: Uncaught error: no such file or directory
    at MemoryFileSystem.readFileSync (/Users/PavelPolyakov/Sites/webpack-react-pure/node_modules/memory-fs/lib/MemoryFileSystem.js:107:10)
    at MemoryFileSystem.(anonymous function) [as readFile] (/Users/PavelPolyakov/Sites/webpack-react-pure/node_modules/memory-fs/lib/MemoryFileSystem.js:300:34)

however, I'm sure that the file is there, because it works for the urls which are not 404.

My OS is macOS, but I don't think it's a reason for something.

Any suggestion is appreciated.

Regards,

Wow ... I searched for hours until I find this snippet. @jantimon THANK YOU! it is crazy how hard it is to find this. Saved my bacon! Probably hard to find because it is missing keywords like express, SPA, routing.

Considering the fact how much upvotes this issue still gets, adding this to docs might be a good idea :)

Because my express URL path (/) didn't match a filename known to webpack the webpack-dev-middleware was passing through the request even if it hadn't finished building my bundle. This led to 'file not found' issues. I was able to fix this by calling waitUntilValid on the middleware instance.

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

var compiler = webpack(require('./webpack.config.js'));

var devMiddleware = require('webpack-dev-middleware');

app.use(devMiddleware(compiler, {
  noInfo: true,
  publicPath: '/'
}));

app.use('*', function (req, res, next) {
  var filename = path.join(compiler.outputPath,'index.html');
  devMiddleware.waitUntilValid(() => {
    compiler.outputFileSystem.readFile(filename, function(err, result){
      if (err) {
        return next(err);
      }
      res.set('content-type','text/html');
      res.send(result);
      res.end();
    });
  });
});

app.listen(3000);

@jantimon I love you thank you so much.

Use html-webpack-harddisk-plugin after HtmlWebpackPlugin. It keeps index.html at hard disk, so that you can simply doing this:

plugins: [
  new HtmlWebpackPlugin({
    alwaysWriteToDisk: true
  }),
  new HtmlWebpackHarddiskPlugin()
]

...achieve this:

app.get('*', (req, res) => {
  // for example
  res.sendFile(path.join(__dirname, 'dist', 'index.html'));
})

@walandemar Thank you. That works great.

@walandemar Thank you,it works for me!!!

Error: no such file or directory
at MemoryFileSystem.readFileSync (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/memory-fs/lib/MemoryFileSystem.js:114:10)
at app.get (/Users/ramintaghizada/ReactJS/VotingApp/server.js:51:29)
at Layer.handle [as handle_request] (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/layer.js:95:5)
at /Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/index.js:281:22
at param (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/index.js:354:14)
at param (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/index.js:365:14)
at Function.process_params (/Users/ramintaghizada/ReactJS/VotingApp/node_modules/express/lib/router/index.js:410:3)

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings