refactor: migrate vite-plugin-pages to unplugin-vue-router

This commit is contained in:
YunYouJun 2024-01-14 20:56:58 +08:00
parent f7324b4157
commit 9a00a55dc8
26 changed files with 494 additions and 298 deletions

View File

@ -49,7 +49,7 @@ For a example, you can see [demo/yun](./demo/yun/) folder.
- 🔥 Hot Reload with Config & Markdown
- 🔧 Type Tooltip for all config by `valaxy.config.ts`
- 🗒 Extended Markdown Frontmatter
- 🗂 File based routing via [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)
- 🗂 File based routing via [unplugin-vue-router](https://github.com/posva/unplugin-vue-router)
- 📦 Components auto importing via [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
- 🖨 Static-site generation (SSG) via [vite-ssg](https://github.com/antfu/vite-ssg) (SPA is OK!)
- 🕸 RSS & Sitemap

View File

@ -49,7 +49,7 @@ pnpm create valaxy
- 🔥 配置 & Markdown 文件热更新
- 🔧 `valaxy.config.ts` 的所有配置项皆有类型提示
- 🗒 扩展 Markdown Frontmatter
- 🗂 实现基于文件路由 by [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)
- 🗂 实现基于文件路由 by [unplugin-vue-router](https://github.com/posva/unplugin-vue-router)
- 📦 自动引入组件 by [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
- 🖨 静态站点生成 (SSG) by [vite-ssg](https://github.com/antfu/vite-ssg) (支持单页面应用!)
- 🕸 RSS & Sitemap

View File

@ -0,0 +1,3 @@
# _Drafts
Temp, this folder contains all the drafts of the pages.

View File

@ -2,13 +2,11 @@ import { defineConfig } from 'vite'
// vite plugins
// import { VitePWA } from 'vite-plugin-pwa'
// import VueDevTools from 'vite-plugin-vue-devtools'
// import Inspect from 'vite-plugin-inspect'
export default defineConfig({
plugins: [
// not works, to be fixed
// VueDevTools(),
// VitePWA(),
// https://github.com/antfu/vite-plugin-inspect
// Visit http://localhost:3333/__inspect/ to see the inspector

View File

@ -225,12 +225,12 @@ to build their own.
## 基于文件的自动路由 {lang="zh-CN"}
::: zh-CN
路由会自动遵循相同目录结构从当前路径中的 Vue 文件生成。更多请参考 [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages)。
路由会自动遵循相同目录结构从当前路径中的 Vue/Markdown 文件生成。更多请参考 [unplugin-vue-router](https://github.com/posva/unplugin-vue-router)。
:::
::: en
Routes will be auto-generated for Vue files in this dir with the same file structure.
Check out [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) for more details.
Routes will be auto-generated for Vue/Markdown files in this dir with the same file structure.
Check out [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router) for more details.
:::
## 构建 {lang="zh-CN"}

View File

@ -103,15 +103,21 @@ pnpm create valaxy
我们提供了一个扩展函数,以供你快速扩展页面信息。
你也可以直接扩展 [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages) 插件中的 `extendRoute`
<!-- TODO -->
你也可以直接扩展 [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) 插件中的 `extendRoute`
> <https://github.com/posva/unplugin-vue-router/issues/43#issuecomment-1433140464>
```ts
// valaxy.config.ts
import { defineTheme } from 'valaxy'
export default defineTheme({
pages: {
extendRoute(route, parent) {
vueRouter: {
extendRoutes(route) {
// want to get component absolute paths?
// const path = route.components.get('default')
console.log(route)
},
},
@ -122,6 +128,8 @@ export default defineTheme({
```
```ts
import type { EditableTreeNode } from 'unplugin-vue-router'
// provided by valaxy, just as a tip
export interface ValaxyConfig {
vue?: Parameters<typeof Vue>[0]
@ -129,11 +137,7 @@ export interface ValaxyConfig {
unocss?: UnoCSSConfig
pages?: Parameters<typeof Pages>[0]
extendMd?: (ctx: {
route: {
meta: { frontmatter?: Record<string, any>, layout?: string }
path: string
component: string
}
route: EditableTreeNode
data: Readonly<Record<string, any>>
excerpt?: string
path: string

View File

@ -11,7 +11,6 @@
"resolveJsonModule": true,
"types": [
"vite/client",
"vite-plugin-pages/client",
"vite-plugin-vue-layouts/client"
],
"allowJs": true,

View File

@ -1,12 +1,11 @@
<script setup lang="ts">
defineProps<{ page: string }>()
import { useRoute } from 'vue-router'
import { computed } from 'vue'
const route = useRoute()
const pageIndex = computed(() => Number.parseInt((route.params as { page: string }).page))
</script>
<template>
<YunPostList :cur-page="parseInt(page)" />
<YunPostList :cur-page="pageIndex" />
</template>
<route lang="yaml">
meta:
layout: home
</route>

View File

@ -11,8 +11,8 @@
"resolveJsonModule": true,
"types": [
"vite/client",
"vite-plugin-pages/client",
"vite-plugin-vue-layouts/client"
"vite-plugin-vue-layouts/client",
"valaxy/client"
],
"allowJs": true,
"strict": true,

View File

@ -1,3 +1,8 @@
# ignore it
components.d.ts
index.html
# unplugin-vue-components
components.d.ts
# unplugin-vue-router
typed-router.d.ts

View File

@ -19,7 +19,7 @@ export function usePostTitle(post: ComputedRef<Post>) {
*/
export function usePageList() {
return computed<Post[]>(() => {
const excludePages = ['/:..all', '/:all(.*)*', '/']
const excludePages = ['/:..all', '/:all(.*)*', '/', '/:path(.*)']
const router = useRouter()
const routes = router.getRoutes()
.filter(i => i.name)
@ -27,7 +27,7 @@ export function usePageList() {
.filter(i => i.meta!.frontmatter)
.filter(i => i.path && !excludePages.includes(i.path))
.map((i) => {
return Object.assign({ path: i.path, excerpt: i.meta!.excerpt }, i.meta!.frontmatter) as Post
return Object.assign({ path: i.path, excerpt: i.meta!.excerpt }, i.meta!.frontmatter || {}) as Post
})
return routes
})

View File

@ -4,7 +4,7 @@ Vue components in this dir are used as layouts.
By default, `default.vue` will be used unless an alternative is specified in the route meta.
With [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this:
With [unplugin-vue-router](https://github.com/posva/unplugin-vue-router) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this:
```html
<route lang="yaml">

View File

@ -1,6 +1,7 @@
import type { ViteSSGContext } from 'vite-ssg'
import { ViteSSG } from 'vite-ssg'
import generatedRoutes from 'virtual:generated-pages'
import { routes } from 'vue-router/auto/routes'
import { setupLayouts } from 'virtual:generated-layouts'
import { initValaxyConfig, valaxyConfigSymbol } from 'valaxy'
@ -20,12 +21,6 @@ import 'uno.css'
import setupMain from './setup/main'
const routes = setupLayouts(import.meta.env.DEV
? generatedRoutes
: generatedRoutes.filter(i =>
i.meta && i.meta.frontmatter && !i.meta.frontmatter.draft,
))
/**
* register global components
* @param ctx
@ -35,12 +30,17 @@ export function registerComponents(ctx: ViteSSGContext) {
}
// not filter hide for ssg
const routesWithLayout = setupLayouts(import.meta.env.DEV
? routes
: routes.filter(i =>
i.meta && i.meta.frontmatter && !i.meta.frontmatter.draft,
))
// https://github.com/antfu/vite-ssg
export const createApp = ViteSSG(
App,
{
routes,
routes: routesWithLayout,
base: import.meta.env.BASE_URL,
scrollBehavior(to, from) {
if (to.path !== from.path)

View File

@ -63,7 +63,6 @@ $light: map.merge(
"c-primary-rgb": #{color.red($c-primary), color.green($c-primary), color.blue($c-primary)},
"c-link": get-css-var("c-primary-dark"),
"c-divider": rgba(60, 60, 60, 0.2),
),
$light
);

View File

@ -376,6 +376,7 @@ function injectPageDataCode(
const isUsingTS = tags.findIndex(tag => scriptLangTsRE.test(tag)) > -1
// merge lastUpdated
const exportScript = `
import { provide } from 'vue'
import { useRoute } from 'vue-router'

View File

@ -7,6 +7,7 @@ import Vue from '@vitejs/plugin-vue'
import Layouts from 'vite-plugin-vue-layouts'
import Components from 'unplugin-vue-components/vite'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import VueDevTools from 'vite-plugin-vue-devtools'
import UnheadVite from '@unhead/addons/vite'
@ -17,7 +18,7 @@ import { createUnocssPlugin } from './unocss'
import { createConfigPlugin } from './extendConfig'
import { createClientSetupPlugin } from './setupClient'
import { createFixPlugins } from './patchTransform'
import { createPagesPlugin } from './pages'
import { createRouterPlugin } from './vueRouter'
import { createValaxyPlugin } from './valaxy'
// for render markdown excerpt
@ -86,12 +87,13 @@ export async function ViteValaxyPlugins(
createClientSetupPlugin(options),
createValaxyPlugin(options, serverOptions),
// https://github.com/hannoeru/vite-plugin-pages
createPagesPlugin(options),
// https://github.com/posva/unplugin-vue-router
createRouterPlugin(options),
// https://github.com/JohnCampionJr/vite-plugin-vue-layouts
Layouts({
layoutsDirs: roots.map(root => `${root}/layouts`),
pagesDirs: roots.map(root => `${root}/pages`),
}),
// https://github.com/antfu/unplugin-vue-components
@ -130,5 +132,7 @@ export async function ViteValaxyPlugins(
splitVendorChunkPlugin(),
createFixPlugins(options),
VueDevTools(),
]
}

View File

@ -1,11 +1,10 @@
import Pages from 'vite-plugin-pages'
import VueRouter from 'unplugin-vue-router/vite'
import fs from 'fs-extra'
import matter from 'gray-matter'
import { isDate } from '@antfu/utils'
import { convert } from 'html-to-text'
import type { ExcerptType, Page } from 'valaxy/types'
import type { ResolvedValaxyOptions } from '../options'
import type { ValaxyExtendConfig } from '../types'
import { EXCERPT_SEPARATOR } from '../constants'
import { mdIt } from './preset'
@ -31,55 +30,51 @@ function getExcerptByType(excerpt = '', type: ExcerptType = 'html') {
}
/**
* @see https://github.com/hannoeru/vite-plugin-pages
* @see https://github.com/posva/unplugin-vue-router
* @param options
*/
export function createPagesPlugin(options: ResolvedValaxyOptions) {
export function createRouterPlugin(options: ResolvedValaxyOptions) {
const { roots, config: valaxyConfig } = options
return Pages({
extensions: ['vue', 'md'],
dirs: roots.map(root => `${root}/pages`),
return VueRouter({
extensions: ['.vue', '.md'],
routesFolder: roots.map(root => `${root}/pages`),
dts: `${options.clientRoot}/typed-router.d.ts`,
...valaxyConfig.pages,
...valaxyConfig.vueRouter,
/**
* we need get frontmatter before route, so write it in Pages.extendRoute
* @experimental See https://github.com/posva/unplugin-vue-router/issues/43
* we need get frontmatter before route, so write it in extendRoute
*/
async extendRoute(
route: Parameters<Required<ValaxyExtendConfig>['extendMd']>[0]['route'],
parent,
) {
let path: string = route.component
async extendRoute(route) {
const defaultFrontmatter = JSON.parse(JSON.stringify(valaxyConfig.siteConfig.frontmatter)) || {}
if (!route.meta) {
route.meta = {
frontmatter: defaultFrontmatter,
}
}
else if (!route.meta.frontmatter) {
// set default frontmatter
route.meta.frontmatter = defaultFrontmatter
}
// encode for chinese filename dev and build same
route.path = encodeURI(route.path)
// add default layout for home, can be overrode
if (route.path === '/')
route.meta.layout = 'home'
// find page path
roots.forEach((root) => {
const pagePath = root + route.component
if (fs.existsSync(pagePath))
path = pagePath
// merge deeply
route.addToMeta({
frontmatter: defaultFrontmatter,
})
// encode for chinese filename dev and build same
// const encodedPath = encodeURI(route.path)
// if (encodedPath !== route.path)
// route.path = encodedPath
// add default layout for home, can be overrode
if (route.fullPath === '/' || route.fullPath === '/page') {
route.addToMeta({
layout: 'home',
})
}
// find page path
const path = route.components.get('default') || ''
// page is post
if (route.path.startsWith('/posts/'))
route.meta.layout = 'post'
if (route.fullPath.startsWith('/posts/')) {
route.addToMeta({
layout: 'post',
})
}
if (path.endsWith('.md')) {
const md = fs.readFileSync(path, 'utf-8')
@ -89,7 +84,6 @@ export function createPagesPlugin(options: ResolvedValaxyOptions) {
const mdFm = data as Page
// todo, optimize it to cache or on demand
// https://github.com/hannoeru/vite-plugin-pages/issues/257
const lastUpdated = options.config.siteConfig.lastUpdated
// do not export password
@ -120,8 +114,11 @@ export function createPagesPlugin(options: ResolvedValaxyOptions) {
})
// set layout
if (data.layout)
route.meta.layout = data.layout
if (data.layout) {
route.addToMeta({
layout: data.layout,
})
}
// set default updated
if (!route.meta.frontmatter?.updated)
@ -152,9 +149,7 @@ export function createPagesPlugin(options: ResolvedValaxyOptions) {
valaxyConfig.extendMd?.(ctx)
}
valaxyConfig.pages?.extendRoute?.(route, parent)
return route
return valaxyConfig.vueRouter?.extendRoute?.(route)
},
})
}

View File

@ -1,7 +1,8 @@
import type Vue from '@vitejs/plugin-vue'
import type Components from 'unplugin-vue-components/vite'
import type { VitePluginConfig as UnoCSSConfig } from 'unocss/vite'
import type Pages from 'vite-plugin-pages'
import type VueRouter from 'unplugin-vue-router/vite'
import type { EditableTreeNode } from 'unplugin-vue-router'
import type { UserConfig as ViteUserConfig } from 'vite'
import type { presetAttributify, presetIcons, presetTypography, presetUno } from 'unocss'
import type { Hookable } from 'hookable'
@ -71,17 +72,13 @@ export interface ValaxyExtendConfig {
icons?: Parameters<typeof presetIcons>[0]
typography?: Parameters<typeof presetTypography>[0]
}
pages?: Parameters<typeof Pages>[0]
vueRouter?: Parameters<typeof VueRouter>[0]
/**
* for markdown
*/
markdown?: MarkdownOptions
extendMd?: (ctx: {
route: {
meta: { frontmatter: Record<string, any>, layout?: string } & object
path: string
component: string
}
route: EditableTreeNode
data: Readonly<Record<string, any>>
content: string
excerpt?: string

View File

@ -72,8 +72,8 @@
"@unhead/schema-org": "^1.8.9",
"@unhead/vue": "^1.8.9",
"@vitejs/plugin-vue": "^5.0.3",
"@vueuse/core": "^10.7.1",
"@vueuse/integrations": "^10.7.1",
"@vueuse/core": "^10.7.2",
"@vueuse/integrations": "^10.7.2",
"body-scroll-lock": "4.0.0-beta.0",
"consola": "^3.2.3",
"critters": "^0.0.20",
@ -114,9 +114,10 @@
"unconfig": "^0.3.11",
"unocss": "^0.58.3",
"unplugin-vue-components": "^0.26.0",
"unplugin-vue-router": "^0.7.0",
"vanilla-lazyload": "^17.8.5",
"vite": "^5.0.11",
"vite-plugin-pages": "^0.32.0",
"vite-plugin-vue-devtools": "^7.0.10",
"vite-plugin-vue-layouts": "0.11.0",
"vite-ssg": "0.23.6",
"vite-ssg-sitemap": "0.6.1",

View File

@ -1,5 +1,7 @@
import 'vue-router'
import './client/typed-router'
import type { Post } from './types'
import type { Header } from './node/markdown'

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,6 @@
"types": [
"vitest",
"vite/client",
"vite-plugin-pages/client",
"vite-plugin-vue-layouts/client",
"@intlify/unplugin-vue-i18n/messages"
],