Changing __webpack_public_path__
may not to be enough....
Why
Vue CLI has a publicPath option:
By default, Vue CLI assumes your app will be deployed at the root of a domain, e.g. https://www.my-app.com/
. If your app is deployed at a sub-path, you will need to specify that sub-path using this option. For example, if your app is deployed at https://www.foobar.com/my-app/
, set publicPath
to '/my-app/'
This value is used in multiple places:
- To configure Webpack - set it's output.publicPath option.
The value is important both at build time and runtime.
At runtime it is made available as a global JS variable __webpack_public_path__
and used (by Webpack) when creating URL's for any module requests (loading dynamic JS chunks, referencing images etc.)
At build time, it is also used for creating URL's but this time for the assets which are needed to load your app into the browser - all the <link>
and <script>
tags responsible to load all JavaScript and CSS of your app. Those are directly injected into the index.html
as hardcoded strings
- The value is made available as an ENV variable
process.env.BASE_URL
usable inside your code. This variable is very useful
For example Vue-router, also requires some configuration to work correctly when the app is not hosted in server root (because its responsible for creating URL's for <router-link>
). This is most of the time done using this line in it's config: base: process.env.BASE_URL
Or you may need to configure base url for Axios to make API calls...
All of this works thanks to Webpack's DefinePlugin. And really important thing to understand is how it works. Anytime you use process.env.BASE_URL
in your code, Webpack replaces that string with configured value during build time (ie. there is no variable process.env.BASE_URL
know at runtime)
How
From all the above it should be clear now that just replacing the value of __webpack_public_path__
at runtime as suggested by linked answer is just not enough. So what else is needed?
Do not use process.env.BASE_URL
anywhere in your code. Using __webpack_public_path__
instead should be enough to solve this problem
Much bigger problem are the links in index.html
generated during build time. Those are clearly not affected by __webpack_public_path__
variable. Only option I see here is to set publicPath
for production build to some unique value and instead of serving index.html
as a static file, serve it as dynamic response - reading file from the disk, replacing original publicPath
value with correct value (for the specific deployment) and serving the result
Alternatives
First and obvious alternative is just to setup multiple CI/CD pipelines, configure publicPath
for each using ENV variables and build separate package for each instance
Second alternative is hinted in Vue CLI documentation
The value (publicPath
) can also be set to an empty string (''
) or a relative path (./
) so that all assets are linked using relative paths. This allows the built bundle to be deployed under any public path, or used in a file system based environment like a Cordova hybrid app.
The point is if your site uses relative link without leading slash, it should be interpreted by the browser as a path relative to the current path (source) and as a result, you can deploy under any public path...
The decision is yours as only you know the details needed to make one...