Documentation Index
Fetch the complete documentation index at: https://mintlify.com/crxjs/chrome-extension-tools/llms.txt
Use this file to discover all available pages before exploring further.
Building your Chrome extension for production involves optimization, testing, and packaging. This guide covers best practices for creating production-ready builds.
Production Build
Create a production build:
This command:
- Type-checks your code (if using TypeScript)
- Bundles and optimizes all assets
- Generates the extension in
dist/ directory
- Creates source maps (if configured)
- Minifies JavaScript and CSS
Build Configuration
Configure your production build in vite.config.ts:
import path from 'node:path'
import { crx } from '@crxjs/vite-plugin'
import { defineConfig } from 'vite'
import manifest from './manifest.config'
export default defineConfig({
plugins: [
crx({ manifest }),
],
build: {
// Output directory
outDir: 'dist',
// Generate source maps for debugging
sourcemap: true,
// Minification
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remove console.log in production
drop_debugger: true,
},
},
// Chunk size warnings
chunkSizeWarningLimit: 1000,
// Rollup options
rollupOptions: {
output: {
manualChunks: {
// Split vendor code
vendor: ['react', 'react-dom'],
},
},
},
},
})
Manifest Configuration
Configure your manifest for production:
import { defineManifest } from '@crxjs/vite-plugin'
import pkg from './package.json'
const isDev = process.env.NODE_ENV === 'development'
export default defineManifest({
manifest_version: 3,
// Add [DEV] prefix in development
name: isDev ? `[DEV] ${pkg.name}` : pkg.name,
// Semantic versioning
version: pkg.version,
description: pkg.description,
icons: {
16: 'public/icon-16.png',
48: 'public/icon-48.png',
128: 'public/icon-128.png',
},
action: {
default_popup: 'src/popup/index.html',
},
background: {
service_worker: 'src/background.ts',
type: 'module',
},
// Only include dev permissions in development
permissions: [
'storage',
...(isDev ? ['tabs'] : []),
],
content_scripts: [{
js: ['src/content/main.ts'],
matches: ['https://*/*'],
}],
})
Package.json Scripts
Set up comprehensive build scripts:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"build:watch": "vite build --watch",
"type-check": "tsc -b --noEmit",
"lint": "eslint src",
"preview": "vite preview"
}
}
Optimization Strategies
Code Splitting
Split your code into smaller chunks:
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: (id) => {
// Vendor chunk
if (id.includes('node_modules')) {
return 'vendor'
}
// UI framework chunk
if (id.includes('react') || id.includes('vue') || id.includes('svelte')) {
return 'framework'
}
// Components chunk
if (id.includes('/components/')) {
return 'components'
}
},
},
},
},
})
Tree Shaking
Ensure proper tree shaking:
// Good: Named imports enable tree shaking
import { map, filter } from 'lodash-es'
// Bad: Imports entire library
import _ from 'lodash'
Lazy Loading
Load components on demand:
// React
const Settings = lazy(() => import('./components/Settings'))
// Vue
const Settings = defineAsyncComponent(() => import('./components/Settings.vue'))
// Svelte
const Settings = () => import('./components/Settings.svelte')
Asset Optimization
Optimize images and fonts:
npm install -D vite-plugin-image-optimizer
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
export default defineConfig({
plugins: [
crx({ manifest }),
ViteImageOptimizer({
png: { quality: 80 },
jpeg: { quality: 80 },
webp: { quality: 80 },
}),
],
})
Source Maps
Configure source maps for debugging:
export default defineConfig({
build: {
// 'hidden' generates source maps but doesn't reference them
// Good for production debugging without exposing source
sourcemap: 'hidden',
// Alternative options:
// sourcemap: true, // Full source maps
// sourcemap: false, // No source maps
// sourcemap: 'inline', // Inline source maps
},
})
Chrome Web Store allows source maps. Include them for easier debugging of production issues.
Packaging
Create ZIP Archive
Install the zip plugin:
npm install -D vite-plugin-zip-pack
import zip from 'vite-plugin-zip-pack'
import { name, version } from './package.json'
export default defineConfig({
plugins: [
crx({ manifest }),
zip({
outDir: 'release',
outFileName: `${name}-${version}.zip`,
}),
],
})
After building, find your extension in release/.
Manual Packaging
Or package manually:
# Build first
npm run build
# Create zip
cd dist
zip -r ../extension.zip .
cd ..
Version Management
Use semantic versioning:
{
"version": "1.2.3",
"scripts": {
"version:patch": "npm version patch && npm run build",
"version:minor": "npm version minor && npm run build",
"version:major": "npm version major && npm run build"
}
}
Update version:
npm run version:patch # 1.2.3 -> 1.2.4
npm run version:minor # 1.2.4 -> 1.3.0
npm run version:major # 1.3.0 -> 2.0.0
Build Checklist
Before publishing, verify:
Testing Production Build
Load and test your production build:
-
Build the extension:
-
Open Chrome and navigate to
chrome://extensions
-
Enable “Developer mode”
-
Click “Load unpacked”
-
Select the
dist/ directory
-
Test all features thoroughly
Size Analysis
Analyze bundle size:
npm install -D rollup-plugin-visualizer
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
crx({ manifest }),
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
}),
],
})
After building, opens a visual report of your bundle.
Chrome Web Store Requirements
Size Limits
- Maximum upload size: 20 MB
- Maximum unpacked size: 100 MB
Required Assets
Prepare store assets:
- Small icon: 128x128 PNG
- Promotional images:
- Small: 440x280 PNG
- Marquee: 1400x560 PNG (optional)
- Screenshots: 1280x800 or 640x400 PNG (min 1, max 5)
- Description (max 132 characters)
- Detailed description
- Privacy policy URL (if collecting data)
Manifest Requirements
export default defineManifest({
manifest_version: 3,
name: 'Your Extension Name',
version: '1.0.0',
description: 'Clear, concise description under 132 characters',
icons: {
16: 'public/icon-16.png',
48: 'public/icon-48.png',
128: 'public/icon-128.png',
},
// ... rest of manifest
})
Continuous Integration
Automate builds with GitHub Actions:
.github/workflows/build.yml
name: Build Extension
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Type check
run: npm run type-check
- name: Lint
run: npm run lint
- name: Build
run: npm run build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: extension
path: dist/
Environment-Specific Builds
Build for different environments:
{
"scripts": {
"build": "vite build",
"build:staging": "vite build --mode staging",
"build:production": "vite build --mode production"
}
}
VITE_API_URL=https://staging.api.example.com
VITE_API_URL=https://api.example.com
Publishing
Steps to publish:
- Create a Chrome Web Store Developer account
- Pay one-time $5 registration fee
- Build and package your extension
- Upload ZIP file to dashboard
- Fill in store listing details
- Submit for review
Review typically takes 1-3 business days.
Post-Publication
Monitoring
Monitor your extension:
- Check Chrome Web Store reviews
- Monitor error reports
- Track user count and ratings
- Review crash reports (if using error tracking)
Updates
To update:
- Increment version in
package.json
- Build and test
- Upload new ZIP to Chrome Web Store
- Submit for review
Users receive updates automatically.
Next Steps