Contributing to shadow-cljs-vite-plugin
January 10, 2026 · View on GitHub
Thank you for your interest in contributing! We want to make this plugin the best bridge between Vite and shadow-cljs.
Development Setup
-
Clone the repository:
git clone <repository-url> cd <folder-path> -
Install dependencies:
pnpm install -
Build the project:
pnpm run build -
Run in watch mode:
pnpm run dev
Code Structure
To help you navigate the codebase, here is an overview of the internal architecture. We aim to keep concerns separated and the logic predictable.
High-Level Architecture
This plugin is actually a collection of smaller, focused Vite plugins that work together. The entry point is src/index.ts, which composes these sub-plugins.
Directory Layout
src/
├── index.ts # Main entry point. Initializes context and composes sub-plugins.
├── constants.ts # Shared constants (e.g., logging tags).
├── types.ts # Shared TypeScript interfaces and types.
├── plugins/ # Core logic split into specific plugin phases.
│ ├── build.ts # Handles the 'build' command (runs `shadow-cljs release`).
│ ├── serve.ts # Handles the 'serve' command (runs `shadow-cljs watch`).
│ ├── virtualModule.ts # Manages the virtual module `virtual:shadow-cljs/...` for HMR entry.
│ └── importsInjector.ts # Fixes dependency issues by injecting explicit ESM imports.
└── utils/ # specific utility functions.
├── shadowCljsConfig.ts # Parses `shadow-cljs.edn`.
├── shadowCljsProcess.ts # Manages the global shadow-cljs child process.
├── googDependencyHandler.ts # Scans and maps Google Closure dependencies.
└── ...
Key Concepts
- Plugin Context: We use a
PluginContextobject to share state (like parsed config, project root) between the sub-plugins without polluting the global scope. - Virtual Module: The plugin injects a virtual entry point into Vite. This allows us to control exactly when the ClojureScript output is loaded and attach HMR listeners.
- Imports Injection: A critical part of this plugin is
importsInjector.ts. It ensures thatgoog.requirecalls in the generated JS interact correctly with native ESM imports, preventing race conditions in environments like Cloudflare Workers.
Submitting a Pull Request
- Fork the repo and create your branch from
main. - Make sure your code lints and builds (
npm run build). - Add tests for new features (if applicable).
- Ensure your commit messages follow the Angular Commit Convention.
feat(scope): messagefix(scope): messagedocs(scope): message
- Open a Pull Request!