Skip to content

Instantly share code, notes, and snippets.

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

  • Save EnixCoda/8b4c41cd079d53fafda4c5d7e13f165e to your computer and use it in GitHub Desktop.

Select an option

Save EnixCoda/8b4c41cd079d53fafda4c5d7e13f165e to your computer and use it in GitHub Desktop.
Override Vite's internal JSON 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.

See below Vite config for details.

// make your editor and compiler happy
declare module "*.schema.json" {
const value: (data: unknown) => boolean;
export default value;
}
import { createFilter, Plugin, PluginOption } from "vite";
function createValidator(schemaContent: any) {
return `export default function() { /* ... */ }`;
}
export const customJsonLoaderPlugin: (options: { pattern: string }) => PluginOption = ({ pattern }) => {
const filter = createFilter(pattern);
const transformSchema: Plugin["transform"] = (code, id) => filter(id)) ? createValidator(JSON.parse(code)) : null;
let jsonPlugin: Plugin | null = null;
return {
name: "vite-plugin-custom-json-loader",
enforce: "pre",
async configResolved(config) {
const jsonPluginIndex = config.plugins.findIndex((plugin) => plugin.name === "vite:json");
if (jsonPluginIndex !== -1) [jsonPlugin] = Array.prototype.splice.call(config.plugins, jsonPluginIndex, 1);
},
transform(...args) {
const transformJson =
typeof jsonPlugin?.transform === "function" ? jsonPlugin?.transform : jsonPlugin?.transform?.handler;
const [, id] = args;
const resolvedTransform = filter(id) ? transformSchema : transformJson;
return resolvedTransform?.call(this, ...args);
},
};
};
export const config = defineConfig({
plugins: [
customJsonLoaderPlugin({ pattern: "**/*.schema.json" })
],
});
@EnixCoda
Copy link
Author

EnixCoda commented Dec 3, 2024

Thanks to virtual-module. I made a cleaner version that does not hack existing vite:json plugin. Check it out

https://gist.github.com/EnixCoda/715f61acf81bb42a6433163d4ae12ca7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment