diff --git a/src/core/moduleConstants.ts b/src/core/moduleConstants.ts index 7c20875ae..babdae8ce 100644 --- a/src/core/moduleConstants.ts +++ b/src/core/moduleConstants.ts @@ -35,3 +35,13 @@ export const routeBlockQueryRE = /\?vue&type=route/ export function asVirtualId(id: string) { return VIRTUAL_PREFIX + id } + +// from https://github.com/vitejs/vite-plugin-vue/pull/582/files#diff-6e789a0a69ac40966dc0c6cf31b4603231ed60412915af87f0b0b8611765efa1R1 +export function exactRegex(input: string): RegExp { + return new RegExp(`^${escapeRegex(input)}$`) +} + +const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g +function escapeRegex(str: string): string { + return str.replace(escapeRegexRE, '\\$&') +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index d51df9472..9a00c4d72 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,8 @@ import { routeBlockQueryRE, ROUTE_BLOCK_ID, ROUTES_LAST_LOAD_TIME, + VIRTUAL_PREFIX, + exactRegex, } from './core/moduleConstants' import { Options, @@ -50,15 +52,18 @@ export default createUnplugin((opt = {}, _meta) => { mergeAllExtensions(options) ) + const IDS_TO_INCLUDE = options.routesFolder.flatMap((routeOption) => + pageFilePattern.map((pattern) => join(routeOption.src, pattern)) + ) + const DEFINE_PAGE_QUERY_RE = /\?.*\bdefinePage\&vue\b/ + // this is a larger filter that includes a bit too many files // the RouteFolderWatcher will filter it down to the actual files const filterPageComponents = createFilter( [ - ...options.routesFolder.flatMap((routeOption) => - pageFilePattern.map((pattern) => join(routeOption.src, pattern)) - ), + ...IDS_TO_INCLUDE, // importing the definePage block - /\?.*\bdefinePage\&vue\b/, + DEFINE_PAGE_QUERY_RE, ], options.exclude ) @@ -68,25 +73,36 @@ export default createUnplugin((opt = {}, _meta) => { name: 'unplugin-vue-router', enforce: 'pre', - resolveId(id) { - if ( - // vue-router/auto-routes - id === MODULE_ROUTES_PATH || - // NOTE: it wasn't possible to override or add new exports to vue-router - // so we need to override it with a different package name - id === MODULE_VUE_ROUTER_AUTO - ) { - // virtual module - return asVirtualId(id) - } - - // this allows us to skip the route block module as a whole since we already parse it - if (routeBlockQueryRE.test(id)) { - return ROUTE_BLOCK_ID - } - - // nothing to do, just for TS - return + resolveId: { + filter: { + id: { + include: [ + exactRegex(MODULE_ROUTES_PATH), + exactRegex(MODULE_VUE_ROUTER_AUTO), + routeBlockQueryRE, + ], + }, + }, + handler(id) { + if ( + // vue-router/auto-routes + id === MODULE_ROUTES_PATH || + // NOTE: it wasn't possible to override or add new exports to vue-router + // so we need to override it with a different package name + id === MODULE_VUE_ROUTER_AUTO + ) { + // virtual module + return asVirtualId(id) + } + + // this allows us to skip the route block module as a whole since we already parse it + if (routeBlockQueryRE.test(id)) { + return ROUTE_BLOCK_ID + } + + // nothing to do, just for TS + return + }, }, buildStart() { @@ -103,10 +119,17 @@ export default createUnplugin((opt = {}, _meta) => { return filterPageComponents(id) }, - transform(code, id) { - // console.log('👋 Transforming', id) - // remove the `definePage()` from the file or isolate it - return ctx.definePageTransform(code, id) + transform: { + filter: { + id: { + include: [...IDS_TO_INCLUDE, DEFINE_PAGE_QUERY_RE], + }, + }, + handler(code, id) { + // console.log('👋 Transforming', id) + // remove the `definePage()` from the file or isolate it + return ctx.definePageTransform(code, id) + }, }, // loadInclude is necessary for webpack @@ -119,32 +142,45 @@ export default createUnplugin((opt = {}, _meta) => { ) }, - load(id) { - // remove the block as it's parsed by the plugin - // stub it with an empty module - if (id === ROUTE_BLOCK_ID) { - return { - code: `export default {}`, - map: null, + load: { + filter: { + id: { + include: [ + exactRegex(ROUTE_BLOCK_ID), + exactRegex(MODULE_ROUTES_PATH), + exactRegex(MODULE_VUE_ROUTER_AUTO), + exactRegex(`${VIRTUAL_PREFIX}${MODULE_ROUTES_PATH}`), + exactRegex(`${VIRTUAL_PREFIX}${MODULE_VUE_ROUTER_AUTO}`), + ], + }, + }, + handler(id) { + // remove the block as it's parsed by the plugin + // stub it with an empty module + if (id === ROUTE_BLOCK_ID) { + return { + code: `export default {}`, + map: null, + } } - } - // we need to use a virtual module so that vite resolves the vue-router/auto-routes - // dependency correctly - const resolvedId = getVirtualId(id) + // we need to use a virtual module so that vite resolves the vue-router/auto-routes + // dependency correctly + const resolvedId = getVirtualId(id) - // vue-router/auto-routes - if (resolvedId === MODULE_ROUTES_PATH) { - ROUTES_LAST_LOAD_TIME.update() - return ctx.generateRoutes() - } + // vue-router/auto-routes + if (resolvedId === MODULE_ROUTES_PATH) { + ROUTES_LAST_LOAD_TIME.update() + return ctx.generateRoutes() + } - // vue-router/auto - if (resolvedId === MODULE_VUE_ROUTER_AUTO) { - return ctx.generateVueRouterProxy() - } + // vue-router/auto + if (resolvedId === MODULE_VUE_ROUTER_AUTO) { + return ctx.generateVueRouterProxy() + } - return // ok TS... + return // ok TS... + }, }, // improves DX