VueJS + Webpack Dev Server not able to hot reload url subpaths - vue.js

My application runs on the subdirectory http://localhost:8080/admin_suffix
suffix is a ENV variable which I can change and define in a .env file.
Once i run the webpack dev server, accessing http://localhost:8080/admin_suffix works.
Clicking on the hyperlinks in the SPA which points other subpaths works too. For example, I can navigate to http://localhost:8080/admin_suffix/subdirectory
However, when i hit reload on http://localhost:8080/admin_suffix/subdirectory, i will get an error "Cannot GET /admin_suffix/subdirectory"
I also cannot enter the subpath into the browser directly to load the page. Only ``http://localhost:8080/admin_suffix` works.
My configuration are as follows:
webpack.base.config.js:
entry: {
main: './src/main',
vendors: './src/vendors'
},
devServer: {
host: '0.0.0.0',
disableHostCheck: true
},
output: {
path: path.join(__dirname, '../dist')
}
webpack.dev.config.js:
module.exports = merge(webpackBaseConfig, {
output: {
publicPath: '/',
filename: '[name].js',
chunkFilename: '[name].chunk.js'
}
});
src/main.js:
const RouterConfig = {
mode: 'history',
routes: Routers,
base: '/admin_suffix/'
}

Enable devServer.historyApiFallback in webpack.base.config.js:
devServer: {
historyApiFallback: true,
// ...
},
This configures webpack-dev-server to fallback to index.html when the route is not found (404).
The Vue app and router are initialized from the main page (index.html), so refreshing the page while on a subroute would normally result in a 404 because the router would not have been setup yet. However, the fallback configuration mentioned above would result in the index.html being served instead, allowing the router to be setup and the subroute to subsequently complete.

Related

Issue with Vue application deployed to subdirectory when route changes from publicPath

We have a Vue application that we're deploying to a subdirectory: /deploypath/
Right now, we have vue.config.js as:
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
publicPath: process.env.NODE_ENV === 'production'
? '/deploypath/'
: '/',
transpileDependencies: [
'vuetify'
]
})
Here's what's happening: In index.js (router) I have multiple paths configured to return multiple views and components. When a user is logged in, they can access additional pages. When they're not logged in, they're redirected to a (landing page).
I have multiple routes defined:
const routes = [
{
path: '/deploypath',
name: 'feature1',
component: FeatureOneView,
meta: {
title: 'Feature One',
}
},
{
path: '/deploypath/notloggedin',
name: 'notloggedin',
component: NotLoggedInView,
meta: {
title: 'Landing',
}
}
]
const router = new VueRouter({
mode: 'history',
routes: routes
});
Now, the issue I'm running into is that (after deploying a production build) when I visit /deploypath it works, however any other path (e. g. /deploypath/notloggedin) doesn't work. We have an Ubuntu instance running with nginx.
Are we doing something wrong with the Vue config or is there an issue on the nginx side, or other?
In case it helps anyone, a good buddy of mine helped find a solution:
cd /etc/nginx/sites-available
then:
sudo vim <insert your site's conf file here>
then press "i" to edit and within the top-level server { ... } section paste in (replace "dirname" with the name of the subdirectory you're hosting your Vue application in):
location ^~ /dirname {
try_files $uri /dirname/index.html =400;
}
then press escape (esc) on keyboard, then type ":wq" and press enter to save..
Then run:
sudo service nginx restart
then refresh your browser window and hopefully you see your Vue app!

Nuxt static generated page and axios post

I have a Nuxt project. Everything is OK when I generate a static page.
However, I need to send a POST request to the other server.
I tried to use both a proxy in nuxt.config.js and just direct query, but after deploy to the ngnix eventually, nothing works.
Please help.
UPDATE. Steps to reproduce.
Create Nuxt App including axios and proxy
Configure your proxy for other webservice:
proxy: {
'/api': {
target: 'http://example.com:9000',
pathRewrite: {
'^/api': '/',
},
},
changeOrigin: true,
},
call this service somewhere in the code:
const result = await this.$axios.post('/api/email/subscribe', {email: email})
run "yarn dev" and test the service. It works locally properly.
run 'nuxt generate' and deploy the static code hosting service, for example, hosting.com
run your page which calls the above-mentioned service.
As a result, instead of making POST call to the hosting.com/api/email/subscribe, it calls localhost:3000/api/email/subscribe.
Be sure to install the nuxt versions of axios and proxy in your project #nuxt/axios and #nuxtjs/proxy
after that in your nuxt.config.js add axios as module plus this options for axios and proxy:
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
//more modules if you need
],
/*
** Axios module configuration
*/
axios: {
proxy: true,
// See https://github.com/nuxt-community/axios-module#options
},
proxy: {
'/api/': {
target: process.env.AXIOS_SERVER, // I use .env files for the variables
pathRewrite: { '^/api/': '' }, //this should be your bug
},
},
now you can use axios in any part of the code like this
const result = await this.$axios.post('/api/email/subscribe', {email: email})
it will internally resolve to AXIOS_SERVER/email/subscribe without cause cors issues.
EXTRA: test enviroments in local using multiples .env files
you can configure .env for dev and .env.prod for production, after that in local you can use yarn build && yarn start for test your app with your production enviroment. You only need add this at the top of your nuxt.config.js file
const fs = require('fs')
const path = require('path')
if (process.env.NODE_ENV === 'production' && fs.existsSync('.env.prod')) {
require('dotenv').config({ path: path.join(__dirname, `.env.prod`) })
} else {
require('dotenv').config()
}
By definition on the Nuxt docs page what nuxt generate does is: Build the application and generate every route as a HTML file (used for static hosting).
Therefore, using proxy is out of question here. Take note that you path is not even being rewritten.
And probably the result you're looking for is not hosting.com/api/email/subscribe (wit /api), but hosting.com/email/subscribe.
Nevertheless, if you use nginx then I don't think you should use Nuxt's proxy option. Nginx is built just for that so point your API calls there and in nginx config file just declare where it should point further.

Vue multiple pages with a webworker

Using vue cli 3 I have a project using harp.gl where I need a webworker to decode map tiles.
My vue.config.js has the following:
module.exports = {
pages: {
app: {
entry: './src/main.js',
filename: 'index.html',
title: 'Contextual Map HARP.GL/Vue',
},
decoder: {
target: "webworker",
entry: "./src/decoder.js",
output: {
filename: "[name].bundle.js",
},
devtool: 'source-map',
...
When I run this I have both the app and the decode.js running as a webworker of type "script" (when inspecting it using Chrome).
However, after upgrading to vue cli 4 the above code does not work, as inspecting it using Chrome the webworker type is text/html and it appears to serve the default index.html. It alomst as if the type: "webworker" is not working the same as with version 3.
I am at loss as how to fix this, the move from vue cli 3 to 4 changed something, but I cannot figure out what to change.

VueJS app as subdomain throws 404 when a path is added

I have a portfolio site portfolio.com and a subdomain which points to a VueJS frontend hosted on Netlify vuejsapp.portfolio.com
Users upload files to the app and it generates a download link URL, say vuejsapp.portfolio.com/download/048677a. When I navigate to the link within the VueJS app (by clicking a button to redirect after it's uploaded) it redirects to the Download component without issue. But if I copy and paste that link directly in my browser it throws a 404 error. Why is this?
I know it has to do with a Vue Router configuration but I can't seem to find much information about it or perhaps I'm looking in the wrong place. Could someone tell me what I'm missing or point me to some relevant documentation please?
My router.js file:
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
name: "home",
component: Home,
},
{
path: "/about",
name: "about",
component: About
},
{
path: "/download/:id",
name: "download",
component: Download,
props: route => ({ id: route.params.id }),
}
]
});
Since the code/setup is running properly on your local environment and only breaking on Netlify its pretty clear that you're running into a wrong server configuration issue.
Your Netlify environment has to know that it should always route any requests to / and leave the routing to your Vue App. You can read more about how to resolve that in the Netlify docs.

Using browser-sync with vue js and framework7

I have created a PWA using vue js 2.0 and framework7 and also use Webpack for bundling. I want to use browser-sync to share my project.
I used this config in my webpack.confg file :
new BrowserSyncPlugin({
// browse to http://localhost:3000/ during development,
// ./public directory is being served
host: 'localhost,
port: 3000,
server: { baseDir: ['src'] }
}),
In src/ I have my basic files like index.html, app.vue, app.js.
After using npm run dev command I see this result :
[Browsersync] Access URLs:
----------------------------------
Local: http://localhost:3000
External: http://192.168.1.118::3000
----------------------------------
UI: http://localhost:3001
UI External: http://localhost:3001
----------------------------------
[Browsersync] Serving files from: src
After this, localhost:3000 open in my browser and say browsersync: connected but it have showed me a blank page.
Also after I enter website path (http://localhost:3000/en/#!/login) in browser, it showed me Cannot Get /en Error. What is the problem?
Any help will greatly appreciated.
Based on your comment, looks like you are also using webpack-dev-server. In that case you can proxy to it:
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
module.exports = {
// ...
devServer: {
port: 3100
}
// ...
plugins: [
new BrowserSyncPlugin(
// BrowserSync options
{
// browse to http://localhost:3000/ during development
host: 'localhost',
port: 3000,
// proxy the Webpack Dev Server endpoint
// (which should be serving on http://localhost:3100/)
// through BrowserSync
proxy: 'http://localhost:3100/'
},
// plugin options
{
// prevent BrowserSync from reloading the page
// and let Webpack Dev Server take care of this
reload: false
}
)
]
}