问题
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!
回答1:
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 athttps://www.foobar.com/my-app/
, setpublicPath
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 problemMuch 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 setpublicPath
for production build to some unique value and instead of servingindex.html
as a static file, serve it as dynamic response - reading file from the disk, replacing originalpublicPath
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 instanceSecond 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...
来源:https://stackoverflow.com/questions/65915610/dynamically-setting-webpack-public-path-does-not-work-after-build-in-vue-app