Webpack: Configuring webpack-dev-server

3 minute read

TIL how to configure webpack-dev-server (WDS) to both serve files from the publicPath and proxy APIs on different domains to avoid cross site request warnings in the browser.

Click here for my previous TIL on paths and naming in webpack.

This post will focus on setting up WDS and some of the configuration options I wound up using.

WDS works by holding your bundled files in memory on the dev server. This allows for the quick diffing and serving of changes to application assets as they change during development. WDS “stores” these files at the output.publicPath.

The following gist contains the webpack config I will reference throughout this post. NOTE: I am using webpack 2 so the config might look slightly different if you’re used to webpack 1 config:

The devServer.contentBase Option

Yet another path related configuration option… what makes this one different from path and publicPath (which were covered in my last blog post)?

Per the documentation, the devServer.contentBase option tells the dev server where content should be served from. In other words, if there are any files that the devServer should reference from disk (like other generated code as part of your build steps) it should be located at the contentBase.

contentBase can be an array, so there can be multiple locations in your file system that make up the devServer’s contentBase if necessary.

In my case, I used contentBase to point my devServer to some static locale files that were generated during a build step for our app. Unlike the bundled files served from publicPath, the locale files served from contentBase do not change during development, and therefore do not need to be held in memory on the dev server. They can be referenced directly from disk at the contentBase.

A pro-tip I learned: if there aren’t any HTML files configured to be served from / on the devServer, if you access the base path directly you can see the files currently being stored at contentBase. If you want to see files being reference at publicPath (in other words, files held in memory on the dev server and not written to disk), navigate to /webpack-dev-server!

Also, a word of warning: It appears that if a file with the same path && name exists at both the contentBase and the publicPath, that the contentBase version will be preferentially served by the devServer. I discovered this when I had an old bundle.min.js at the contentBase while I was debugging my configuration, and changed the publicPath to be the same as my contentBase. Changes that I made to files in my bundle were not being reflected in the browser, even through a hard refresh of the page.

The devServer.proxy option

The whole reason I started this re-tooling process was to get to WDS proxies… the moment is finally here!

The proxy option allows you to specify a path that, when a request is made to WDS with that path, the server will forward the request to the target in the configuration.

So from my configuration example above: my devServer.proxy object contains a key '/api2', which itself contains a target mapping of https://new-api-domain.com. My dev server is configured to run at https://localhost:8445 NOTE: the devServer.https option is set to true in my configuration above, so my devServer will use a self-signed certificate to feign an https connection (you can also provide your own if needed).

Any requests made to https://localhost:8445/api2 will be proxied to https://new-api-domain.com/api2, which allows me to send requests to the domain where my app originated and get data from a different one. Pretty nifty!

Diagram of What Proxy Looks Like (after pathRewrite)

You might also be asking yourself: what if my other domain doesn’t have a route of /api2? Well you’re in luck, because WDS allows you to pass a pathRewrite option to your proxy mapping, in which you can pass a regex to match on the mapped path and change it to a different one that makes sense for your new domain (see configuration above).

One final trick that proxy does, is it can proxy requests to https domains that have broken certificates! Just set the secure option to false, and your requests will resolve with no problem.

This wasn’t the end of my webpack learnings: I also worked on loader and plugin configuration to transpile our .jsx files to ES5 and extract our CSS from the main webpack bundles into their own files to reduce the main bundle size.

EDIT: Find the next post in the series!