Build SPA app with relative base path
-
I’m using quasar CLI 2.2.1. I’m trying to figure out whether it’s possible to build a SPA app using Vue router, so that it can be deployed under different base paths on a server without having to rebuild the app.
That is, I’d like to be able to copy the build artifact from
quasar build
under https://example.com/ on one server, and under https://example2.com/prefix/ on another server, and have it work either way.As far as I can tell though, the only way to deploy under a path prefix is to set
publicPath: '/prefix'
in quasar.conf.js. I thought it would be possible to setpublicPath
to a relative URL, likepublicPath: './'
, since Vue CLI allows that, but if I try that, quasar prepends a ‘/’ to it.Is there any way to build a quasar app so it can be deployed under different prefixes, or do I just have to rebuild it for each prefix it’s deployed under?
Thanks
-
If you create a SPA build with
quasar build
. You can deploy the same build anywhere, no matter the prefix(== folder on your server).So for example (using nginx):
https://myQuasarSPA.com maps to the
www/foo
(nginx configured) folder on your server. Wherefoo
contains the contents of the quasar build.if you instead copy the same SPA Quasar build of your app to
www/foo/bar
, the Quasar app/site will run at
https://myQuasarSPA.com/bar without any additional configuration.(nginx or apache or quasar) -
Thank you for your response. This is not the behavior I observe though. If I haven’t overridden
publicPath
, when I runquasar build
, the generated index.html will have lines like<script src=/js/vendor.6e58a910.js>
. Note the absolute path. This will fail to load if the app is deployed under https://myQuasarSPA.com/bar, because the script tag needs to be<script src=/bar/js/vendor.6e58a910.js>
now for it to work. If I wanted the same index.html to work in either case, I’d need to change src urls to relative urls, like<script src=./js/vendor.6e58a910.js>
. However, if I try settingpublicPath
to ‘./’, quasar changes it to ‘/./’. The only way I’ve discovered to make the app work with the /bar path prefix is to setpublicPath
to ‘/bar’ in quasar.conf.js and rebuild.You can see the code responsible for this here:
https://github.com/quasarframework/quasar/blob/dev/app/lib/quasar-conf-file.js#L41
It simply won’t allowpublicPath
to be a relative path. This also affects vue router, sincevueRouterBase
is derived from publicPath. -
Note the absolute path.
Ah that’s because you use
history
mode for your router.App’s with
hash
mode have relative paths…See here for a github thread about your issue( and maybe a workaround / solution?):
https://github.com/quasarframework/quasar/issues/4687 -
@dobbel Thanks again. This still doesn’t seem to solve the problem though. I tried setting
vueRouterMode: 'hash'
in quasar.conf.js, and this has no effect on the generated index.html. It still contains script tags with absolute URLs, like<script src=/js/vendor.6e58a910.js>
. So I still can’t take this build output and mount it under different base paths.The issue you linked to also seems to be addressing a different problem: how to have static assets loaded from a different server than the one where index.html lives.
In case my original post wasn’t clear, let me restate what I want to accomplish.
I’d like to be able to configure a quasar app such that I can run
quasar build
once, and then take the build output from under dist/spa and deploy it to multiple servers mounted under different base paths. For example the app might be accessed on one server at https://example.com/, and on another server at https://example2.com/foo/.Currently in order to deploy under multiple base paths, for each desired base path I have to run
quasar build
again withpublicPath
set to the desired base path, and then the generated app can only be deployed under the configured base path. -
@ajenkins Actually it is working with vueRouterMode set to ‘hash’,
you could try:publicPath: process.env.NODE_ENV === "production" ? "." : "/",
-
@suleiman_as I tried putting this in quasar.conf.js
vueRouterMode: 'hash', // available values: 'hash', 'history' publicPath: '.',
After running
quasar build
, index.html now has links like<script src=/./js/vendor.6e58a910.js>
. Note the leading ‘/’ that quasar added. That’s because there’s code here
https://github.com/quasarframework/quasar/blob/dev/app/lib/quasar-conf-file.js#L41
that adds a ‘/’ to the front ofpublicPath
if it doesn’t already have one, so you can’t setpublicPath
to a relative path.I’m using @quasar/app 2.2.1. I gather from some old threads I found that some old versions quasar did support setting
publicPath
to a relative path. If you runquasar --version
what do you get? Perhaps you’re using an older version? -
With
hash
router modedon't
use/configurepublicPath
anywhere in your app. That’s my setup for years and has always worked for Qv1 apps.I have just updated one of my apps to the latest Quasar V1 and the build with
hash
mode hasrelative
paths. If Ichange
tohistory
mode it hasabsolute
paths.If still not resolved, could you post the output of
quasar info
andquasar.conf
? -
@dobbel Ahh, thank you! That worked. The key was I needed to remove
publicPath
entirely from quasar.conf.js, not just set it to a relative path.So, to recap for anyone else looking for an answer to this problem. If you want to build a quasar app such that the build can be mounted under arbitrary base paths, you need to:
- Set
vueRouterMode
to ‘hash’ - Set
publicPath
tonull
, or don’t set it all.
I may play around in my spare time with seeing if I can patch things up to get history mode to work with a relative public public path and post back here if I get something working.
- Set
-