|
|
|
@ -4,7 +4,7 @@ import {
|
|
|
|
|
loadConfigFromFile,
|
|
|
|
|
normalizePath
|
|
|
|
|
} from 'vite'
|
|
|
|
|
import { dirname, resolve } from 'path'
|
|
|
|
|
import path, { dirname, resolve } from 'path'
|
|
|
|
|
import { isMatch } from 'micromatch'
|
|
|
|
|
|
|
|
|
|
const loaderMatch = /\.data\.(j|t)s$/
|
|
|
|
@ -24,6 +24,8 @@ interface CachedLoaderModule {
|
|
|
|
|
const idToLoaderModulesMap: Record<string, CachedLoaderModule | undefined> =
|
|
|
|
|
Object.create(null)
|
|
|
|
|
|
|
|
|
|
const depToLoaderModuleIdMap: Record<string, string> = 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
|
|
|
|
@ -66,8 +68,16 @@ export const staticDataPlugin: Plugin = {
|
|
|
|
|
} 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 LoaderModule
|
|
|
|
|
const res = await loadConfigFromFile({} as any, id)
|
|
|
|
|
|
|
|
|
|
// record deps for hmr
|
|
|
|
|
if (res) {
|
|
|
|
|
for (const dep of res.dependencies) {
|
|
|
|
|
depToLoaderModuleIdMap[normalizePath(path.resolve(dep))] = id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const loaderModule = res?.config as LoaderModule
|
|
|
|
|
pattern =
|
|
|
|
|
typeof loaderModule.watch === 'string'
|
|
|
|
|
? [loaderModule.watch]
|
|
|
|
@ -103,20 +113,27 @@ export const staticDataPlugin: Plugin = {
|
|
|
|
|
if (server && loaderMatch.test(id)) {
|
|
|
|
|
// register this module as a glob importer
|
|
|
|
|
const { pattern } = idToLoaderModulesMap[id]!
|
|
|
|
|
if (pattern) {
|
|
|
|
|
;(server as any)._importGlobMap.set(id, [pattern])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleHotUpdate(ctx) {
|
|
|
|
|
for (const id in idToLoaderModulesMap) {
|
|
|
|
|
const { pattern } = idToLoaderModulesMap[id]!
|
|
|
|
|
const isLoaderFile = normalizePath(ctx.file) === id
|
|
|
|
|
if (isLoaderFile) {
|
|
|
|
|
// invalidate loader file
|
|
|
|
|
const file = normalizePath(ctx.file)
|
|
|
|
|
|
|
|
|
|
// dependency of data loader changed
|
|
|
|
|
// (note the dep array includes the loader file itself)
|
|
|
|
|
if (file in depToLoaderModuleIdMap) {
|
|
|
|
|
const id = depToLoaderModuleIdMap[file]!
|
|
|
|
|
delete idToLoaderModulesMap[id]
|
|
|
|
|
ctx.modules.push(server.moduleGraph.getModuleById(id)!)
|
|
|
|
|
}
|
|
|
|
|
if (isLoaderFile || (pattern && isMatch(ctx.file, pattern))) {
|
|
|
|
|
|
|
|
|
|
for (const id in idToLoaderModulesMap) {
|
|
|
|
|
const { pattern } = idToLoaderModulesMap[id]!
|
|
|
|
|
if (pattern && isMatch(file, pattern)) {
|
|
|
|
|
ctx.modules.push(server.moduleGraph.getModuleById(id)!)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|