Skip to content

Commit

Permalink
feat: support static data loaders
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 14, 2021
1 parent 621d37a commit 26fe81c
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 1 deletion.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"@types/koa-static": "^4.0.1",
"@types/lru-cache": "^5.1.0",
"@types/markdown-it": "^12.0.1",
"@types/micromatch": "^4.0.2",
"@types/node": "^15.6.1",
"@types/polka": "^0.5.3",
"chalk": "^4.1.1",
Expand All @@ -102,6 +103,7 @@
"esbuild": "^0.13.4",
"escape-html": "^1.0.3",
"execa": "^5.0.0",
"fast-glob": "^3.2.7",
"fs-extra": "^10.0.0",
"globby": "^11.0.3",
"gray-matter": "^4.0.3",
Expand All @@ -114,6 +116,7 @@
"markdown-it-container": "^3.0.0",
"markdown-it-emoji": "^2.0.0",
"markdown-it-table-of-contents": "^0.5.2",
"micromatch": "^4.0.4",
"minimist": "^1.2.5",
"npm-run-all": "^4.1.5",
"ora": "^5.4.0",
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion src/node/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { DIST_CLIENT_PATH, APP_PATH, SITE_DATA_REQUEST_PATH } from './alias'
import { slash } from './utils/slash'
import { OutputAsset, OutputChunk } from 'rollup'
import { staticDataPlugin } from './staticDataPlugin'

const hashRE = /\.(\w+)\.js$/
const staticInjectMarkerRE =
Expand Down Expand Up @@ -273,5 +274,10 @@ export function createVitePressPlugin(
}
}

return [vitePressPlugin, vuePlugin, ...(userViteConfig?.plugins || [])]
return [
vitePressPlugin,
vuePlugin,
...(userViteConfig?.plugins || []),
staticDataPlugin
]
}
116 changes: 116 additions & 0 deletions src/node/staticDataPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// TODO figure out why it causes full page reload

import { Plugin, ViteDevServer, loadConfigFromFile, normalizePath } from 'vite'
import { dirname, relative } from 'path'
import { isMatch } from 'micromatch'

const loaderMatch = /\.data\.(j|t)s$/

let server: ViteDevServer

interface LoaderModule {
base: string
pattern: string | undefined
loader: () => any
}

const idToLoaderModulesMap: Record<string, LoaderModule | undefined> =
Object.create(null)

// During build, the load hook will be called on the same file twice
// once for client and once for server build. Not only is this wasteful, it
// also leads to a race condition in loadConfigFromFile() that results in an
// fs unlink error. So we reuse the same Promise during build to avoid double
// loading.
let idToPendingPromiseMap: Record<string, Promise<string> | undefined> =
Object.create(null)
let isBuild = false

export const staticDataPlugin: Plugin = {
name: 'vitepress:data',

configResolved(config) {
isBuild = config.command === 'build'
},

configureServer(_server) {
server = _server
},

async load(id) {
if (loaderMatch.test(id)) {
let _resolve: ((res: any) => void) | undefined
if (isBuild) {
if (idToPendingPromiseMap[id]) {
return idToPendingPromiseMap[id]
}
idToPendingPromiseMap[id] = new Promise((r) => {
_resolve = r
})
}

const base = dirname(id)
let pattern: string | undefined
let loader: () => any

const existing = idToLoaderModulesMap[id]
if (existing) {
;({ pattern, loader } = existing)
} else {
// use vite's load config util as a away to load Node.js file with
// TS & native ESM support
const loaderModule = (await loadConfigFromFile({} as any, id))
?.config as any
pattern = loaderModule.watch
if (pattern && pattern.startsWith('./')) {
pattern = pattern.slice(2)
}
loader = loaderModule.load
}

// load the data
const data = await loader()

// record loader module for HMR
if (server) {
idToLoaderModulesMap[id] = { base, pattern, loader }
}

const result = `export const data = JSON.parse(${JSON.stringify(
JSON.stringify(data)
)})`

if (_resolve) _resolve(result)
return result
}
},

transform(_code, id) {
if (server && loaderMatch.test(id)) {
// register this module as a glob importer
const { base, pattern } = idToLoaderModulesMap[id]!
;(server as any)._globImporters[id] = {
module: server.moduleGraph.getModuleById(id),
importGlobs: [{ base, pattern }]
}
}
return null
},

handleHotUpdate(ctx) {
for (const id in idToLoaderModulesMap) {
const { base, pattern } = idToLoaderModulesMap[id]!
const isLoaderFile = normalizePath(ctx.file) === id
if (isLoaderFile) {
// invalidate loader file
delete idToLoaderModulesMap[id]
}
if (
isLoaderFile ||
(pattern && isMatch(relative(base, ctx.file), pattern))
) {
ctx.modules.push(server.moduleGraph.getModuleById(id)!)
}
}
}
}

0 comments on commit 26fe81c

Please sign in to comment.