Mike Driver
Mike Driver

Reputation: 8511

Is it possible to have `publicPath` configured dynamically in the browser with webpack?

I've got a project where I deploy the same webpack JS bundle to multiple different environments. Some environments use a CDN to serve static assets like JS files, and some do not and just have static assets served from the same root as the rest of the project.

This project also has multiple async webpack chunks, and so I define a publicPath for them to be correctly loaded.

When deploying to non-cdn, webpack works fine with a statically configured publicPath in my webpack config serving everything from something like /static/.

However when deploying to environments that use a CDN, this no longer works for async chunks, because webpack will try to access these from /static/ which means they ask the main app server and not the CDN.

Clearly I can re-build the project with my CDN in publicPath to solve this issue. However, I'd prefer to be able to use just one deployment package in both situations.

My server-side app provides a javascript global detailing the CDN root path, along the lines of window.staticCDNRoot. And this global is also present in non-cdn situations, just pointing back to the app server - so it always resolves to the correct location to load static assets from.

Is there any way I can get webpack to utilize this at runtime so that publicPath becomes window.staticCDNRoot + publicPath without huge hackery?

Or is there a better solution to this issue?

Upvotes: 23

Views: 13233

Answers (3)

prograhammer
prograhammer

Reputation: 20590

If you only have a handful of different environments just go ahead and abstract a webpack config (on top of a shared config) that has the different publicPath you need for each. This shouldn't be much of an extra impact on your build pipeline. Then in your application, when you fetch main/runtime webpack chunks from a specific environment/server/cdn, then webpack will pick up the other chunks and async chunks that correctly correspond.

Also, you can work with the assets in your app directly if you need to. You can use something like webpack-manifest-plugin to create a manifest file, which will include all the paths to all your assets with the correct public path. You can request this from your server somewhere in the client at runtime, or you could have your server include this manifest in some config object included in the initial html response sent to the browser.

Upvotes: 0

agoldis
agoldis

Reputation: 1067

I can suggest to use the plugin at https://github.com/agoldis/webpack-require-from that I have created specifically for that purpose

Upvotes: 3

Mike Driver
Mike Driver

Reputation: 8511

Okay so I was looking for this all day and then found it just after deciding to post here!

Just in case anyone else needs this:

The solution is to define __webpack_public_path__ at runtime when making a production build. But be careful not to use it in development as it can mess up module hot-loading.

More info here:

http://webpack.github.io/docs/configuration.html#output-publicpath

Upvotes: 15

Related Questions