I have a vue frontend, and spring boot backend application. My application has multiple instances with different url paths (for example /instance1, /instance2), but uses the same build project - meaning every instances runs the same jar. Also the application serves static files - the index.html of the compiled vue application.
My problem is that the vue application needs to know dynamically from which url path to get all its static files, so for example when i get the index.html of instance1 it need to get all the assets from /instance1/assets
I read many answers to this problem which they all suggested basically to configure dynamically the webpack_public_path global variable like this first answer
so in my vue app I did this:
in main.js
file:
import './publicpath'
import Vue from 'vue'
then in publicpath.js
file:
__webpack_public_path__ = `/${window.location.pathname.split('/')[1]}/`
The problem with the answer linked above is that it only works for me when I run the application as a dev application (when running npm run serve
on vue project). This doesn't work after building the project, and the build index.html is served by spring boot.
I couldn't find any answer that solved this problem so I would really appreciate any help
Thank you!
Changing __webpack_public_path__
may not to be enough....
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 athttps://www.foobar.com/my-app/
, setpublicPath
to'/my-app/'
This value is used in multiple places:
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
process.env.BASE_URL
usable inside your code. This variable is very usefulFor 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)
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
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...