3 minute read

TIL the difference between path and publicPath in webpack, and how the output.filename property can be used to assign files to sub-directories in the path.

We have been using webpack’s filesystem watcher at work to re-bundle our files on-save during development. I’ve been doing some prototyping work of our UI against a new version of an API we use, and I wanted to use webpack-dev-server (hereby referred to as WDS) to proxy requests to this new API while avoiding any cross origin request issues in the browser. Using WDS would require some retooling and rethinking of how our development process works.

To say it up front, I found setting up WDS to be an enormous pain: the amount of configuration necessary to set up webpack in general is intimidating, and the documentation is notoriously poor. I’ll be referencing the webpack config below for the rest of this blog post. NOTE: I am using webpack 2 so the config might look slightly different if you’re used to webpack 1 config.

path vs. publicPath

The bulk of my misunderstanding came from the differences between path and publicPath in webpack.

path represents the absolute path for webpack file output in the file system. In other words: path is the physical location on disk where webpack will write the bundled files.

publicPath represents the path from which bundled files should be accessed by the browser. In other words: publicPath is an alias for files located at path, and if specified, files are accessible from the publicPath in the browser.

In the example config above, path is set to path.join(__dirname, '/build/') in the output key. This means the files will be saved to disk at the absolute path /Users/username/prototype/build/.

The publicPath is configured to /assets/. This makes my bundled files accessible from http://localhost:3000/assets/.

I chose the public path /assets/ because that is where we are expecting files to exist in our index.html page. Using publicPath, I can match the static resource pathnames already being requested in my index.html, and I don’t need to worry about adding any conditionals to load assets at different paths based on environment (i.e. dev vs prod).

Naming of bundled assets

I specified the name of the bundled files to be 'js/[name].min.js' in the output.filename key. The code is not minified in development, but we minify for production and use the .min.js convention to name our minified files. By naming our bundled output with the .min.js postfix for development, we again don’t need to perform any environment checks in our index.html file (to point to the right file names), which is great.

By prepending js/ to the filename in output.filename, webpack will write bundled files to a js sub-directory in the output.path. This allows you to organize files of a particular type in appropriately named sub-directories.

Webpack also honors these sub-directories at the publicPath: for example, the bundle named js/bundle.min.js above would also be available at localhost:3000/assets/js/bundle.min.js.

[name] is a webpack convention that substitutes the bundle’s name in the output.filename when it creates a bundle. In this case, the file’s name is actually ‘bundle’ (which is configured in the entry key) so the resulting name would be 'js/bundle.min.js'. Webpack also honors two other substitutions during naming: [hash] and [id]

I learned a lot more about webpack while setting up the webpack dev server, including about CommonChunksPlugin for dealing with vendor bundles, ExtractTextPlugin for pulling CSS out of the main bundles and in to their own side bundles, as well as some webpack dev server lessons which I will discuss in future TILs.

Edit: find the next post on webpack-dev-server configuration here!

Updated:

Comments