Wildcard subdomain routing with nuxt - vue.js

I'm relatively new to Nuxt and I'm trying to implement subdomain routing in my Nuxt app, so that a request to:-
mysubdomain.myapp.com is routed to myapp.com/groups/:slug
mysubdomain.myapp.com/<anything else>/ is routed to myapp.com/groups/:slug/<anything else>
where slug is the subdomain.
From what I can see, there are two possible ways to do this. Either extendRoutes in the nuxt config or by using my own router.js file. But I can't work out how get the subdomain into the route.
I've got something like this in my router.js:-
import Router from 'vue-router'
export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
const options = routerOptions || createDefaultRouter(ssrContext).options
const hostname = ssrContext ? ssrContext.req.headers.host : location.host
return new Router({
...options,
routes: fixRoutes(options.routes, hostname.match(/[^.]*/)[0]),
})
}
function fixRoutes(defaultRoutes, subdomain) {
return (
defaultRoutes
.map((route) => {
// TODO use the subdomain in here to route to /groups/:slug route
return route
})
)
}
It feels like I'm close but I can't figure out this last bit. Is this even possible?!

Related

What are the implications of migrating from createWebHashHistory() to createWebHistory()?

I have an application that I released that uses createWebHashHistory() to manage URLs. For example, a user visits the following URL to visit something called the earthquakes channel:
https://app.radar.chat/#/channel/earthquakes
I would like to switch over to using createWebHistory() to manage URLs instead (SEO, social media previews, iOS universal links configuration, etc). With that in mind, I would like it if my new URL structure looks like this:
https://app.radar.chat/channel/earthquakes
I know that to support this change I need to make a server change. The easiest way is to have the server redirect incoming requests to an index.html file (this is documented extensively on the Vue website).
However, there are URLs in the wild that link to these old pages, URLs that have been printed and that can never be updated.
Is there a convenient mechanism to continue to support the old hash-based URLs while having the non-hashed URLs be the new default?
In your router config, you could add a global beforeEach hook on the index path that resolves to the hash path in the URL if it exists:
// router.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [⋯]
})
router.beforeEach((to, from, next) => {
if (to.path === '/' && to.hash.startsWith('#/')) {
next(to.hash.substr(1))
} else {
next()
}
})
export default router
demo

Nuxt.js routing

I am migrating from ASP.NET MVC to Nuxt.js and I am trying to keep the same urls so I can keep the SEO ratings
My current URLs are
www.url.com/#computers/#laptops/#dell?page=1
All of the # are dynamic values so URL might also be
www.url.com/#phones/#smartphones/#apple?page=1
What is the easiest way to point all these URLs to one page ITEMS and to be able to get values for every # and also for QueryString values ?
Thanks in advance
You can accomplish this with serverMiddleware in nuxt
Make a file for your middleware:
middleware/server/seoMiddleware.js
Add that to your nuxt.config.js in the serverMiddleware block:
serverMiddleware: [
'~/middleware/server/seoMiddleware.js'
]
Create a file to handle a list of your 301's:
middleware/server/301.js
Add your path mapping using regex in your 301.js:
export default [
{ from: '/(#[\w\d]+)\/(#[\w\d]+)\/(#[\w\d]+)', to: 'items', capture: true }
]
Pop open your seoMiddleware.js
const redirects = require('./301.js').default
export default function (req, res, next) {
const redirect = redirects.find(redirect => req.url.test(redirect.from))
if (redirect) {
const to = redirect.capture ? applyCapturesToUrl(req.url, redirect) : redirect.to
res.writeHead(301, { Location: to })
res.end()
}
// failover
next()
}
const applyCapturesToUrl(url, redirect) {
const matches = url.match(redirect.from)
return `/${redirect.to}/` + matches.map(match => match.replace('#', '')).join('/')
}
We've used some simple regex here to create capture groups based on your URL structure and and serverMiddleware to intercept the request and return a 301 (permanent redirect) if we find a match. We failover with next() and allow the request through if there was no match found. We use a capture flag on the redirect object so we know when we're dealing with capture groups, without it we can just do simple pattern matching.

redirect default '/' to a specific path nuxt / netlify

Basically I want the root route '/' to be redirected to my '/home' route.
My Nuxt app is hosted on Netlify so I tried to do this is the _redirects file
/ /home
as per their redirect docs - but it's not working.
Now I know that in Vue in the router config you can set up redirects, but how do I achieve the same thing in Nuxt??
any help would be appreciated!
In your main index.vue page you would add:
<script>
export default {
middleware: 'redirect'
}
</script>
Then you would create a middleware to actually redirect to desired page, in middleware > redirect.js:
export default function ({ store, redirect }) {
return redirect('/home')
}

Populate router with external json

I would like to add routes from an external json file, which can change at runtime, to my Nuxt application. A similar topic can be found here.
I've overridden the default Nuxt router with my own implementation. If I import the routes async using axios + router.addRoutes(), I seem to loose the server side rendering. It seems like createRouter will have async support, but it's not in an official release of Nuxt yet.
How do I import a js/json file synchronously to my router.js below, so that I can populate the routes? I want to be able to configure the routes at runtime, so I don't want it to be a part of the bundle.
modules/router.js:
const path = require('path')
module.exports = function () {
this.nuxt.options.build.createRoutes = () => {}
this.addTemplate({
fileName: 'router.js',
src: path.resolve(`${this.options.srcDir}`, 'router.js')
})
}
nuxt.config.js:
modules: ['~/modules/router']
router.js:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export function createRouter () {
const router = new Router({
mode: 'history',
routes: [/* ... */]
})
return router
}
You could try with sync-request.
It is a NPM package aimed to perform synchronous web requests. It is available here.
Please note that, as stated in the documentation of the package itself, it is not suitable for production environment, probably because of application hanging in case of missing data.
So await would be an answer but I guess you already tried that? So, something like this.
const routeFile = await fetch('pathToTheJsonFile');
const routes = await routeFile.json();
In case you can't make the method async, as a workaround maybe use jQuery. I don't like this but if there's no other option, for now, use async: false in jQuery get.
jQuery.ajax({
url: 'pathToYourJsonRoutes',
success: function (result) {
},
async: false
});

how to write global router-function in nuxt.js

I am using Vue.js with Nuxt.js, but I got a problem in router's functions.
In the pure Vue, i can write in main.js like this:
val route = new Router({
routes:{
[...]
}
})
route.beforeEach(to,from,next){
//do something to validate
}
And how to do the same in nuxt.js ? I can not find any file like main.js.
Also, all i know is to deal with the pages folder to achieve router, I can not set the redirect path
please help, thx :)
You can create a plugin for Nuxt
create a plugins/route.js file:
export default ({ app }) => {
// Every time the route changes (fired on initialization too)
app.router.afterEach((to, from) => {
//do something to validate
})
}
and update your nuxt.config.js file:
plugins: ['~/plugins/route']
More details about Nuxt plugins: https://nuxtjs.org/guide/plugins
If anybody might be still interested, it's possible to setup global middleware in nuxt.config.js like this:
router: { middleware: ['foo'] },
then in your middleware/foo.js you do whatever...
export default function({ route, from, store, redirect }) {}
Beware: You can't use this for static sites (nuxt generate), because middleware is not executed on page load, but only on subsequent route changes. Thanks #ProblemsOfSumit for pointing that out.