diff --git a/client.d.ts b/client.d.ts index e6afb9f3b..719410e64 100644 --- a/client.d.ts +++ b/client.d.ts @@ -1,32 +1,49 @@ declare module 'vue-router/auto-routes' { - import type { RouteRecordRaw, Router } from 'vue-router' + import type { RouteRecordRaw, Router, RouterOptions } from 'vue-router' /** * Array of routes generated by unplugin-vue-router */ export const routes: RouteRecordRaw[] + type HandleHotUpdateCallback = (newRoutes: RouteRecordRaw[]) => void + /** - * Setups hot module replacement for routes. - * @param router - The router instance - * @param hotUpdateCallback - Callback to be called after replacing the routes and before the navigation - * @example + * Creates a router instance. + * @param options - The router options + * @param hotUpdateCallback - Callback to be called after replacing the routes and before the navigation. + * (If `import.meta.hot` is not supported, it will only be executed once during initialization.) + * @example Common usage * ```ts * import { createRouter, createWebHistory } from 'vue-router' - * import { routes, handleHotUpdate } from 'vue-router/auto-routes' + * import { routes, createRouter } from 'vue-router/auto-routes' + * * const router = createRouter({ * history: createWebHistory(), * routes, * }) - * if (import.meta.hot) { - * handleHotUpdate(router) - * } + * ``` + * + * @example Hot module replacement + * ```ts + * import { createRouter, createWebHistory } from 'vue-router' + * import { routes, createRouter } from 'vue-router/auto-routes' + * + * const router = createRouter( + * { + * history: createWebHistory(), + * routes, + * }, + * (newRoutes) => { + * console.log('🔥 HMR with', newRoutes) + * } + * ) * ``` */ - export function handleHotUpdate( - router: Router, - hotUpdateCallback?: (newRoutes: RouteRecordRaw[]) => void - ): void + export function createRouter( + options: RouterOptions, + hotUpdateCallback?: HandleHotUpdateCallback + ): Router } declare module 'vue-router' { diff --git a/docs/guide/hmr.md b/docs/guide/hmr.md index c85a60608..fbd729174 100644 --- a/docs/guide/hmr.md +++ b/docs/guide/hmr.md @@ -2,38 +2,25 @@ When using `definePage()` and `` blocks, it's possible to enable Hot Module Replacement (HMR) for your routes **and avoid the need of reloading the page or the server** when you make changes to your routes. -Enabling HMR is **strongly recommended** and currently **only works with Vite**. - -```ts [src/router.ts] -import { createRouter, createWebHistory } from 'vue-router' -import { - routes, - handleHotUpdate, // [!code ++] -} from 'vue-router/auto-routes' - -export const router = createRouter({ - history: createWebHistory(), - routes, -}) - -// This will update routes at runtime without reloading the page -if (import.meta.hot) { // [!code ++] - handleHotUpdate(router) // [!code ++] -} // [!code ++] -``` +Enabling HMR is **strongly recommended** and currently **only works with Vite**. But you don't need to do anything, because this step has been done for you internally. ## Runtime routes If you add routes at runtime, you will have to add them within a callback to ensure they are added during development. ```ts{16-23} [src/router.ts] -import { createRouter, createWebHistory } from 'vue-router' -import { routes, handleHotUpdate } from 'vue-router/auto-routes' - -export const router = createRouter({ - history: createWebHistory(), - routes, -}) +import { createWebHistory } from 'vue-router' +import { routes, createRouter } from 'vue-router/auto-routes' + +export const router = createRouter( + { + history: createWebHistory(), + routes, + }, + () => { + addRedirects() + } +) function addRedirects() { router.addRoute({ @@ -41,15 +28,6 @@ function addRedirects() { redirect: '/about?from=/new-about', }) } - -if (import.meta.hot) { - handleHotUpdate(router, (newRoutes) => { - addRedirects() - }) -} else { - // production - addRedirects() -} ``` diff --git a/docs/introduction.md b/docs/introduction.md index 71e4147e2..c37d1d34d 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -188,8 +188,9 @@ Given the following route configuration: ::: code-group ```ts [src/router.ts] -import { createRouter, createWebHistory } from 'vue-router' -import { routes, handleHotUpdate } from 'vue-router/auto-routes' // [!code ++] +import { createRouter, createWebHistory } from 'vue-router' // [!code --] +import { createWebHistory } from 'vue-router/auto-routes' // [!code ++] +import { routes, createRouter } from 'vue-router/auto-routes' // [!code ++] export const router = createRouter({ history: createWebHistory(), @@ -209,11 +210,6 @@ export const router = createRouter({ ] // [!code --] routes, // [!code ++] }) - -// This will update routes at runtime without reloading the page -if (import.meta.hot) { // [!code ++] - handleHotUpdate(router) // [!code ++] -} // [!code ++] ``` ```ts{2,5} [main.ts] diff --git a/playground/src/router.ts b/playground/src/router.ts index 69e44b1c9..889adf5b7 100644 --- a/playground/src/router.ts +++ b/playground/src/router.ts @@ -1,11 +1,16 @@ -import { createRouter, createWebHistory } from 'vue-router' -import { routes, handleHotUpdate } from 'vue-router/auto-routes' +import { createWebHistory } from 'vue-router' +import { routes, createRouter } from 'vue-router/auto-routes' import type { RouteRecordInfo, ParamValue } from 'vue-router' -export const router = createRouter({ - history: createWebHistory(), - routes, -}) +export const router = createRouter( + { + history: createWebHistory(), + routes, + }, + (routes) => { + console.log('🔥 HMR', routes) + } +) function addRedirects() { router.addRoute({ @@ -14,15 +19,7 @@ function addRedirects() { }) } -if (import.meta.hot) { - handleHotUpdate(router, (routes) => { - console.log('🔥 HMR with', routes) - addRedirects() - }) -} else { - // production - addRedirects() -} +addRedirects() // manual extension of route types declare module 'vue-router/auto-routes' { diff --git a/src/core/context.ts b/src/core/context.ts index 5d9de314e..523ac69c4 100644 --- a/src/core/context.ts +++ b/src/core/context.ts @@ -188,11 +188,19 @@ export function createRoutesContext(options: ResolvedOptions) { )}\n` let hmr = ts` -export function handleHotUpdate(_router, _hotUpdateCallback) { +import { createRouter as createVueRouter } from 'vue-router' + +export function createRouter(options, _hotUpdateCallback) { + const _router = createVueRouter(options || {}) + if (import.meta.hot) { import.meta.hot.data.router = _router import.meta.hot.data.router_hotUpdateCallback = _hotUpdateCallback + } else if (typeof _hotUpdateCallback === 'function') { + _hotUpdateCallback(_router.getRoutes()) } + + return _router } if (import.meta.hot) {