feat(data-loader): pass watched files into load()

pull/2044/head
Evan You 2 years ago
parent de84c01b72
commit e29b6a051e

@ -1,21 +1,17 @@
import fs from 'fs' import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const dirname = path.dirname(fileURLToPath(import.meta.url))
type Data = Record<string, boolean>[] type Data = Record<string, boolean>[]
export declare const data: Data export declare const data: Data
export default { export default {
watch: ['./data/*'], watch: ['./data/*'],
async load(): Promise<Data> { async load(files: string[]): Promise<Data> {
const foo = fs.readFileSync( const foo = fs.readFileSync(
path.resolve(dirname, './data/foo.json'), files.find((f) => f.endsWith('foo.json'))!,
'utf-8' 'utf-8'
) )
const bar = fs.readFileSync( const bar = fs.readFileSync(
path.resolve(dirname, './data/bar.json'), files.find((f) => f.endsWith('bar.json'))!,
'utf-8' 'utf-8'
) )
return [JSON.parse(foo), JSON.parse(bar)] return [JSON.parse(foo), JSON.parse(bar)]

@ -6,22 +6,18 @@ import {
} from 'vite' } from 'vite'
import path, { dirname, resolve } from 'path' import path, { dirname, resolve } from 'path'
import { isMatch } from 'micromatch' import { isMatch } from 'micromatch'
import glob from 'fast-glob'
const loaderMatch = /\.data\.(j|t)s$/ const loaderMatch = /\.data\.(j|t)s$/
let server: ViteDevServer let server: ViteDevServer
interface LoaderModule { interface LoaderModule {
watch: string[] | string | undefined watch?: string[] | string
load: () => any load: (watchedFiles: string[]) => any
} }
interface CachedLoaderModule { const idToLoaderModulesMap: Record<string, LoaderModule | undefined> =
pattern: string[] | undefined
loader: () => any
}
const idToLoaderModulesMap: Record<string, CachedLoaderModule | undefined> =
Object.create(null) Object.create(null)
const depToLoaderModuleIdMap: Record<string, string> = Object.create(null) const depToLoaderModuleIdMap: Record<string, string> = Object.create(null)
@ -59,12 +55,12 @@ export const staticDataPlugin: Plugin = {
} }
const base = dirname(id) const base = dirname(id)
let pattern: string[] | undefined let watch: LoaderModule['watch']
let loader: () => any let load: LoaderModule['load']
const existing = idToLoaderModulesMap[id] const existing = idToLoaderModulesMap[id]
if (existing) { if (existing) {
;({ pattern, loader } = existing) ;({ watch, load } = existing)
} else { } else {
// use vite's load config util as a away to load Node.js file with // use vite's load config util as a away to load Node.js file with
// TS & native ESM support // TS & native ESM support
@ -78,26 +74,34 @@ export const staticDataPlugin: Plugin = {
} }
const loaderModule = res?.config as LoaderModule const loaderModule = res?.config as LoaderModule
pattern = watch =
typeof loaderModule.watch === 'string' typeof loaderModule.watch === 'string'
? [loaderModule.watch] ? [loaderModule.watch]
: loaderModule.watch : loaderModule.watch
if (pattern) { if (watch) {
pattern = pattern.map((p) => { watch = watch.map((p) => {
return p.startsWith('.') return p.startsWith('.')
? normalizePath(resolve(base, p)) ? normalizePath(resolve(base, p))
: normalizePath(p) : normalizePath(p)
}) })
} }
loader = loaderModule.load load = loaderModule.load
} }
// load the data // load the data
const data = await loader() let watchedFiles
if (watch) {
watchedFiles = (
await glob(watch, {
ignore: ['**/node_modules/**', '**/dist/**']
})
).sort()
}
const data = await load(watchedFiles || [])
// record loader module for HMR // record loader module for HMR
if (server) { if (server) {
idToLoaderModulesMap[id] = { pattern, loader } idToLoaderModulesMap[id] = { watch, load }
} }
const result = `export const data = JSON.parse(${JSON.stringify( const result = `export const data = JSON.parse(${JSON.stringify(
@ -112,9 +116,11 @@ export const staticDataPlugin: Plugin = {
transform(_code, id) { transform(_code, id) {
if (server && loaderMatch.test(id)) { if (server && loaderMatch.test(id)) {
// register this module as a glob importer // register this module as a glob importer
const { pattern } = idToLoaderModulesMap[id]! const { watch } = idToLoaderModulesMap[id]!
if (pattern) { if (watch) {
;(server as any)._importGlobMap.set(id, [pattern]) ;(server as any)._importGlobMap.set(id, [
Array.isArray(watch) ? watch : [watch]
])
} }
} }
return null return null
@ -132,8 +138,8 @@ export const staticDataPlugin: Plugin = {
} }
for (const id in idToLoaderModulesMap) { for (const id in idToLoaderModulesMap) {
const { pattern } = idToLoaderModulesMap[id]! const { watch } = idToLoaderModulesMap[id]!
if (pattern && isMatch(file, pattern)) { if (watch && isMatch(file, watch)) {
ctx.modules.push(server.moduleGraph.getModuleById(id)!) ctx.modules.push(server.moduleGraph.getModuleById(id)!)
} }
} }

Loading…
Cancel
Save