Last active
July 22, 2021 14:27
-
-
Save dimer22zhc/1944064ed907deca7b7bd0d6a20e34e1 to your computer and use it in GitHub Desktop.
Laravel and vue js+vuex-vue-route => you can load Your route and middle ware dynamically
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue' | |
import store from '~/store' | |
import Meta from 'vue-meta' | |
import routes from './routes' | |
import Router from 'vue-router' | |
import { sync } from 'vuex-router-sync' | |
Vue.use(Meta) | |
Vue.use(Router) | |
// The middleware for every page of the application. | |
const globalMiddleware = ['locale', 'check-auth'] | |
// Load middleware modules dynamically. | |
const routeMiddleware = resolveMiddleware( | |
require.context('~/middleware', false, /.*\.js$/) | |
) | |
const router = createRouter() | |
sync(store, router) | |
export default router | |
/** | |
* Create a new router instance. | |
* | |
* @return {Router} | |
*/ | |
function createRouter () { | |
const router = new Router({ | |
scrollBehavior, | |
mode: 'history', | |
routes | |
}) | |
router.beforeEach(beforeEach) | |
router.afterEach(afterEach) | |
return router | |
} | |
/** | |
* Global router guard. | |
* | |
* @param {Route} to | |
* @param {Route} from | |
* @param {Function} next | |
*/ | |
async function beforeEach (to, from, next) { | |
let components = [] | |
try { | |
// Get the matched components and resolve them. | |
components = await resolveComponents( | |
router.getMatchedComponents({ ...to }) | |
) | |
} catch (error) { | |
if (/^Loading( CSS)? chunk (\d)+ failed\./.test(error.message)) { | |
window.location.reload(true) | |
return | |
} | |
} | |
if (components.length === 0) { | |
return next() | |
} | |
// Start the loading bar. | |
if (components[components.length - 1].loading !== false) { | |
router.app.$nextTick(() => router.app.$loading.start()) | |
} | |
// Get the middleware for all the matched components. | |
const middleware = getMiddleware(components) | |
// Call each middleware. | |
callMiddleware(middleware, to, from, (...args) => { | |
// Set the application layout only if "next()" was called with no args. | |
if (args.length === 0) { | |
router.app.setLayout(components[0].layout || '') | |
} | |
next(...args) | |
}) | |
} | |
/** | |
* Global after hook. | |
* | |
* @param {Route} to | |
* @param {Route} from | |
* @param {Function} next | |
*/ | |
async function afterEach (to, from, next) { | |
await router.app.$nextTick() | |
router.app.$loading.finish() | |
} | |
/** | |
* Call each middleware. | |
* | |
* @param {Array} middleware | |
* @param {Route} to | |
* @param {Route} from | |
* @param {Function} next | |
*/ | |
function callMiddleware (middleware, to, from, next) { | |
const stack = middleware.reverse() | |
const _next = (...args) => { | |
// Stop if "_next" was called with an argument or the stack is empty. | |
if (args.length > 0 || stack.length === 0) { | |
if (args.length > 0) { | |
router.app.$loading.finish() | |
} | |
return next(...args) | |
} | |
const middleware = stack.pop() | |
if (typeof middleware === 'function') { | |
middleware(to, from, _next) | |
} else if (routeMiddleware[middleware]) { | |
routeMiddleware[middleware](to, from, _next) | |
} else { | |
throw Error(`Undefined middleware [${middleware}]`) | |
} | |
} | |
_next() | |
} | |
/** | |
* Resolve async components. | |
* | |
* @param {Array} components | |
* @return {Array} | |
*/ | |
function resolveComponents (components) { | |
return Promise.all(components.map(component => { | |
return typeof component === 'function' ? component() : component | |
})) | |
} | |
/** | |
* Merge the the global middleware with the components middleware. | |
* | |
* @param {Array} components | |
* @return {Array} | |
*/ | |
function getMiddleware (components) { | |
const middleware = [...globalMiddleware] | |
components.filter(c => c.middleware).forEach(component => { | |
if (Array.isArray(component.middleware)) { | |
middleware.push(...component.middleware) | |
} else { | |
middleware.push(component.middleware) | |
} | |
}) | |
return middleware | |
} | |
/** | |
* Scroll Behavior | |
* | |
* @link https://router.vuejs.org/en/advanced/scroll-behavior.html | |
* | |
* @param {Route} to | |
* @param {Route} from | |
* @param {Object|undefined} savedPosition | |
* @return {Object} | |
*/ | |
function scrollBehavior (to, from, savedPosition) { | |
if (savedPosition) { | |
return savedPosition | |
} | |
if (to.hash) { | |
return { selector: to.hash } | |
} | |
const [component] = router.getMatchedComponents({ ...to }).slice(-1) | |
if (component && component.scrollToTop === false) { | |
return {} | |
} | |
return { x: 0, y: 0 } | |
} | |
/** | |
* @param {Object} requireContext | |
* @return {Object} | |
*/ | |
function resolveMiddleware (requireContext) { | |
return requireContext.keys() | |
.map(file => | |
[file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)] | |
) | |
.reduce((guards, [name, guard]) => ( | |
{ ...guards, [name]: guard.default } | |
), {}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment