A language evangeliser Vite plugin with a pluggable adapter system. ReScript is the primary language with zero-config, all-pain-points-solved support. AffineScript is the secondary language. The adapter protocol is designed so that any language can be added, and the whole system integrates into PanLL’s language development workspace.
rescript-vite started as the definitive Vite plugin for ReScript — zero-config, every known pain point solved. It has since evolved into a multi-language evangeliser with a pluggable adapter protocol.
Just use it. Zero config. Everything is auto-detected.
// vite.config.js
import rescriptPlugin from "rescript-vite";
export default { plugins: [rescriptPlugin()] };Add language adapters for projects that mix ReScript with AffineScript (or future languages):
// vite.config.js
import { makeWithAdapters } from "rescript-vite";
import { make as affinescriptAdapter } from "rescript-vite/adapter/affinescript";
export default {
plugins: [
makeWithAdapters({
adapters: [affinescriptAdapter()],
}),
],
};-
Zero config —
plugins: [rescriptPlugin()]and you’re done. Everything is auto-detected fromrescript.json. -
Multi-language support — Pluggable adapter protocol. ReScript built-in, AffineScript included, any language can be added.
-
PascalCase module resolution — Fixes the #1 Linux pain point where ReScript emits lowercase imports but actual files are PascalCase on disk.
-
Auto
optimizeDepsexclusion — Merged across all active language adapters. -
Build artifact watcher ignore — Merged across all active adapters.
-
rescript.json auto-detection — Reads suffix, module format, in-source setting.
-
Rewatch support — Auto-detects
rewatchbinary (ReScript 12+). -
Automatic compiler management — Spawns compilers for all active languages.
-
HMR for all languages — Routes file changes to the correct adapter by extension.
-
Error overlay integration — Pushes diagnostics from any adapter to Vite’s overlay.
-
ANSI color forwarding —
NINJA_ANSI_FORCED=1for colored output. -
In-source: false support — Correctly maps out-of-source compilation.
-
Deno compatible — Auto-detects the Deno runtime.
-
BoJ build orchestration — Optionally delegates to a BoJ ssg-mcp cartridge.
-
All features toggleable —
autoOptimizeDeps,autoResolve,autoIgnoreArtifacts. -
panic-attacker compatible — Diagnostic format maps to SARIF output.
// vite.config.js
import rescriptPlugin from "rescript-vite";
export default {
plugins: [rescriptPlugin()],
};// vite.config.js
import { make } from "rescript-vite";
export default {
plugins: [
make({
useDeno: true,
logLevel: "verbose",
compilerFlags: ["-warn-error", "+a"],
}),
],
};// vite.config.js
import { makeWithAdapters } from "rescript-vite";
import { make as affinescriptAdapter } from "rescript-vite/adapter/affinescript";
export default {
plugins: [
makeWithAdapters({
adapters: [affinescriptAdapter()],
logLevel: "info",
}),
],
};Creates a Vite plugin instance with ReScript support (and optional extra adapters).
Returns a standard Vite plugin object with name: "rescript-vite" and enforce: "pre".
| Option | Type | Description | Default |
|---|---|---|---|
|
|
Additional language adapters beyond the built-in ReScript support. Each adapter teaches the plugin how to handle a different language. |
|
|
|
Enable BoJ ssg-mcp build orchestration. |
|
|
|
URL of the BoJ ssg-mcp cartridge endpoint. |
|
|
|
Use Deno to run the ReScript compiler. |
Auto-detected |
|
|
Path to the rescript binary. |
|
|
|
Extra flags passed to the ReScript compiler. |
|
|
|
Controls console output verbosity. |
|
|
|
Output suffix override (e.g., |
Auto-detected |
|
|
Use |
Auto-detected |
|
|
Auto-exclude packages from all active adapters from Vite’s dependency pre-bundling. |
|
|
|
Auto-resolve module imports (PascalCase for ReScript, adapter-specific for others). |
|
|
|
Auto-ignore build artifacts from all active adapters in Vite’s file watcher. |
|
Alias for make — identical function, named for clarity when using adapters.
| Export | Module |
|---|---|
|
Main plugin ( |
|
ReScript config reader ( |
|
BoJ bridge ( |
|
Language adapter protocol ( |
|
ReScript adapter ( |
|
AffineScript adapter ( |
To add support for a new language, create a module implementing LanguageAdapter.t:
// my-language-adapter.js
export function make() {
return {
id: "my-language",
displayName: "My Language",
extensions: [".ml"],
detect: (root) => { /* return config path or undefined */ },
readConfig: (root) => { /* return languageConfig */ },
defaultConfig: { language: "my-language", suffix: ".ml.js", ... },
getOutputPath: (config, sourceFile) => sourceFile + ".js",
build: async (root, config) => { /* return buildResult */ },
watch: (root, config) => { /* return { stop: () => {}, stopped: false } */ },
parseDiagnostics: (output) => { /* return diagnostic[] */ },
resolveImport: (source, importer, config) => undefined,
excludePackages: [],
artifactIgnorePatterns: ["**/_build/**"],
};
}-
Detection —
detect(root)is called duringconfigandconfigResolvedhooks. If it returns a path, the adapter is activated. -
Configuration —
readConfig(root)parses the language’s config file. -
Build —
build(root, config)runs a one-shot compile.watch(root, config)starts the compiler in watch mode. -
HMR — When a file matching the adapter’s extensions changes,
getOutputPathmaps it to compiled output for Vite’s module graph. -
Resolution —
resolveImportis called for imports that ReScript’s PascalCase resolver doesn’t handle. -
Cleanup — Watch handles are stopped during
closeBundle.
This plugin is designed to become a PanLL panel for language development. The adapter protocol will be the standard way PanLL discovers and manages language toolchains across database, language, and protocol development workspaces.
AffineScript will eventually split into a standalone affinescript-vite package,
leaving rescript-vite as the ReScript-focused plugin with a shared adapter
protocol published as a spec.
PMPL-1.0-or-later (Palimpsest License).
See LICENSE for the full text.
Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>