Webpack-dev-server: Provide more webpack-dev-server API

Created on 3 Nov 2018  路  17Comments  路  Source: webpack/webpack-dev-server

Webpack-dev-server is now like a black box, hoping to provide a convenient API for developers to call. The advantage of this approach is that, on the premise of ensuring devServer configuration, developers can use it programmatically and access custom logic.

Most helpful comment

I think ability to manually reload browser window would be great. Such ability exists in BrowserSync, but not in WDS :'(

const server =  new WebpackDevServer(compiler, {...})
server.refresh() // <-- Something like this

All 17 comments

I think this is what I'm looking for too. To reduce the number of API calls on page load I have moved to having a dynamic index.html served by express instead of a static one served by nginx. Now I'm trying to replicate the functionality of webpack-dev-server using webpack-dev-middleware and webpack-hot-middleware. This turns out to be really challenging.

I'm still lacking incremental compiling (full recompile happens on every change) and page reload is not happening automatically and I have no idea how to fix them.

I'm considering proxying webpack-dev-server from my express server in dev mode but this means having multiple processes which I don't really want. It would be much easier if I could just mount the webpack-dev-server as a middleware.

Have you tried the following way?

// devServer.js
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const createLogger = require('webpack-dev-server/lib/utils/createLogger');
const findport = require('./findport');

module.exports = async (config) => {
  try {
    const compiler = webpack(config);
    const options = config.devServer || {};
    const log = createLogger(options);
    const port = await findport(options.port);
    options.port = port;
    const devServer = new WebpackDevServer(compiler, options, log);
    return devServer.app;
  } catch (error) {
    console.warn(error);
  }
};

devServer.app is a express instance.

I think it should be able to run, but I haven't actually tested it yet.

@jiankafei what exactly you want to have in API?

@evilebottnawi
I think dev-server can be designed as follows:

main: defines middleware and exposes it;
bin: parse the parameters, instantiate express, invoke Middleware of main, and then generate services.

Such a design can ensure the use of bin commands, but also allow developers to use the middleware of main. Meet the developer's custom development.

@jiankafei it is require a lot of work, also it is impossible only defines middleware and exposes it, we should setup other part of system to more zero configuration - client, default setting, try/catch errors, setup webpack plugins and more

You should use custom setup for these purpose what you describe

@evilebottnawi
ok, I think webpack should officially support webpack-hot-middleware or webpack-hot-function-api. Based on webpack-dev-middleware and webpack-hot-middleware, webpack-dev-server can be implemented. If webpack-dev-server can not satisfy developers, developers can also build their own dev-server based on webpack-dev-middleware and webpack-hot-middleware.Maybe it's a good choice.

@jiankafei here webpack-hot-middleware https://github.com/webpack-contrib/webpack-hot-middleware, what is problem to setup own configuration?

@evilebottnawi
I know it. But @ncjones had problems.This means that it can not achieve the effect of webpack-dev-server.

Need more information what is not works as expected

@evilebottnawi with webpack-dev-server I didn't need any conditional logic in webpack.config.js - my production mode settings just worked perfectly with the dev server which is great. Now with dev middleware and HMR I must have conditional logic for setting:

  • mode ("production" vs "development")
  • js/css asset name format ("[contenthash]" not allowed with HMR)
  • plugins (HotModuleReplacement and NoEmitOnErrors required for HMR)
  • entries (webpack-hot-middleware/client?path=__webpack_hmr'),
  • styleLoader.

Plus conditional express routing is required to use either static middleware or webpack middleware. In my case extra config was required to make sure HMR is served with the correct base path since all my micro-front-end apps are proxied (I set the express hot middleware "path" and the webpack output "hotUpdateChunkFilename" config).

Everything is working perfectly for me now but it was a very painful 1-2 days to figure out all these tweaks and now my webpack config has conditional logic which I'd rather not have.

@ncjones

mode ("production" vs "development")

js/css asset name format ("[contenthash]" not allowed with HMR)

Fixed in https://github.com/webpack/webpack/releases/tag/v4.24.0

entries (webpack-hot-middleware/client?path=__webpack_hmr'),
plugins (HotModuleReplacement and NoEmitOnErrors required for HMR)

HotModuleReplacement is using if you use webpack-dev-server bin, feel free create issue if you think what it is should be not only in bin

NoEmitOnErrors is not suitable for all developers

styleLoader

Not related to webpack-dev-server, but feel free to feedback what is wrong

I think ability to manually reload browser window would be great. Such ability exists in BrowserSync, but not in WDS :'(

const server =  new WebpackDevServer(compiler, {...})
server.refresh() // <-- Something like this

@felixcatto why?

i am using WDS and webpack only for bundling client js. For moving images, process CSS and transpile server js i am using gulp. So when i change my server code, all code transpiled and i want to refresh browser after this process. I make a simple WDS config with proxy option to target my original server. It works well, when i change client code, but i can't trigger refresh after my server code changed.

There was one similar request in the past
https://github.com/webpack/webpack-dev-server/issues/1073
But webpack watch does not work for me :(

You can run server.invalidate() on backend or send content-changed to sockjs like:

before(app, server) {
      const chokidar = require("chokidar");
      const files = [ "**/*.php"];

      chokidar
        .watch(files, {
          alwaysStat: true,
          atomic: false,
          followSymlinks: false,
          ignoreInitial: true,
          ignorePermissionErrors: true,
          ignored,
          interval: typeof poll === "number" ? poll : null,
          persistent: true,
          usePolling: Boolean(poll)
        })
        .on("all", () => {
          server.sockWrite(server.sockets, "content-changed");
        });
    }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

wojtekmaj picture wojtekmaj  路  3Comments

mrdulin picture mrdulin  路  3Comments

daryn-k picture daryn-k  路  3Comments

MJ111 picture MJ111  路  3Comments

da2018 picture da2018  路  3Comments