Skip to content

Instantly share code, notes, and snippets.

@EnixCoda
Last active December 3, 2024 09:01
Show Gist options
  • Select an option

  • Save EnixCoda/715f61acf81bb42a6433163d4ae12ca7 to your computer and use it in GitHub Desktop.

Select an option

Save EnixCoda/715f61acf81bb42a6433163d4ae12ca7 to your computer and use it in GitHub Desktop.
Vite custom JSON loader plugin

In my special use case, I import JSON file and use them as functions.

For example,

import validator from './example.schema.json'; // schema JSON imported as function
import data from './data.json';                // general JSON imported as data

console.log(data); // { value: 'random-data' }
validator(data);

To achieve this in Vite, we had to override its internal json plugin with ours. So that normal JSON files would be imported as usual. While JSON files named as .schema.json can be used as functions.

// make your editor and compiler happy
declare module "*.schema.json" {
const value: (data: unknown) => boolean;
export default value;
}
import fs from 'fs';
import path from 'path';
import { createFilter, Plugin, ResolvedConfig } from 'vite';
export function customJSONLoaderPlugin(pattern: string): Plugin {
const resolvedVirtualModuleId = '\0' + 'virtual-custom-json-module';
const exclusiveSuffix = '\0'; // to avoid being processed by other plugins like vite:json
const filterSource = createFilter(pattern);
let resolvedConfig: ResolvedConfig;
return {
name: 'vite-plugin-custom-json-loader',
enforce: 'pre',
configResolved(config) {
resolvedConfig = config;
},
resolveId(source, importer) {
if (filterSource(source)) {
const relativeToRootPath = path.resolve(path.dirname(importer), source);
return resolvedVirtualModuleId + relativeToRootPath + exclusiveSuffix;
}
},
async load(id) {
if (id.includes(resolvedVirtualModuleId)) {
const originalPath = path.resolve(
resolvedConfig.root,
id.replace(resolvedVirtualModuleId, '').replace(exclusiveSuffix, '')
);
const content = await fs.promises.readFile(originalPath, 'utf-8');
return `export default function (data) { return data + ${content}; }`;
}
},
};
}
export default {
plugins: [customJSONLoaderPlugin(/\.schema\.json$/)],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment