Installation
This guide covers adding CRXJS Vite Plugin to an existing Vite project or setting up a new project from scratch.
Want to get started quickly? Use npm create crxjs@latest to scaffold a new project. See the Quick start guide.
Prerequisites
Before installing CRXJS, ensure you have:
- Node.js 14.18+ or 16+
- A Vite project (or create one using
npm create vite@latest)
Install the plugin
Install @crxjs/vite-plugin as a dev dependency:
npm install --save-dev @crxjs/vite-plugin
Create a manifest
Create a manifest.json file in your project root. This file defines your extension’s metadata and entry points:
{
"manifest_version": 3,
"name": "My Chrome Extension",
"version": "1.0.0",
"action": {
"default_popup": "index.html"
}
}
CRXJS supports Manifest V3, the latest version of the Chrome Extension manifest format with enhanced security features.
Manifest examples
Here are some common manifest configurations:
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0.0",
"action": {
"default_popup": "index.html"
}
}
All paths in the manifest are relative to your Vite project root (where vite.config.js is located). Use paths that start with a letter, not ./ or /.
Update Vite config
Import and configure the CRXJS plugin in your vite.config.js or vite.config.ts:
import { defineConfig } from 'vite'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.json'
export default defineConfig({
plugins: [
crx({ manifest }),
],
})
Ensure your package.json has "type": "module" set. Vite requires this to process your config file.
TypeScript manifest (optional)
For better type safety and dynamic configuration, use a TypeScript manifest with the defineManifest helper:
Create a manifest config file
Create manifest.config.ts in your project root:import { defineManifest } from '@crxjs/vite-plugin'
import packageJson from './package.json'
export default defineManifest({
manifest_version: 3,
name: packageJson.name,
version: packageJson.version,
action: {
default_popup: 'index.html',
},
})
Update your Vite config
Import the TypeScript manifest instead of JSON:import { defineConfig } from 'vite'
import { crx } from '@crxjs/vite-plugin'
import manifest from './manifest.config'
export default defineConfig({
plugins: [
crx({ manifest }),
],
})
The defineManifest helper provides autocompletion and supports async functions for dynamic manifest generation.
Dynamic manifest example
You can use environment variables and dynamic logic in your TypeScript manifest:
import { defineManifest } from '@crxjs/vite-plugin'
import packageJson from './package.json'
const { version } = packageJson
// Convert Semver to Chrome extension version format
const [major, minor, patch] = version.split('.')
export default defineManifest(async (env) => ({
manifest_version: 3,
name: env.mode === 'production'
? 'My Extension'
: '[DEV] My Extension',
version: `${major}.${minor}.${patch}`,
version_name: version,
action: {
default_popup: 'index.html',
},
}))
Run the development server
Start Vite’s development server:
CRXJS will:
- Parse your manifest
- Build all entry files (HTML pages, scripts, etc.)
- Generate the
dist folder with your extension
- Watch for changes and rebuild automatically
Load the extension
Open Chrome extensions page
Navigate to chrome://extensions in Chrome or Edge
Enable developer mode
Toggle the “Developer mode” switch in the top right (Chrome) or left sidebar (Edge)
Load your extension
Drag your dist folder into the Extensions DashboardYour extension is now installed and ready to use!
Verify installation
Your extension should appear in the extensions list with:
- The name from your manifest
- An icon showing the first letter of your extension name (or your custom icon if specified)
- A toggle to enable/disable it
Click the extension icon in your browser toolbar to test it. If you configured a popup page, it should open and display your Vite-powered UI.
Next steps
Quick start tutorial
Follow the 90-second tutorial to experience HMR
Manifest concepts
Learn more about manifest configuration
Add content scripts
Inject scripts into web pages
Configuration options
Explore advanced plugin configuration
Troubleshooting
”type”: “module” error
If Vite can’t process your config file, ensure your package.json includes:
Manifest paths not resolving
Manifest paths should be relative to your Vite project root and should NOT start with ./ or /:
{
"action": {
"default_popup": "index.html"
},
"background": {
"service_worker": "src/background.js"
}
}
Extension not loading
If your extension doesn’t load in Chrome:
- Check the browser console for errors
- Verify your
dist folder was generated
- Ensure your manifest has at minimum:
manifest_version, name, and version
- Try removing and re-adding the extension