Building Chrome Extensions with React in 2025: Complete Tutorial
The intersection of Chrome extension development and React has become one of the most productive environments for building browser-based tools. As we move through 2025, the combination of React’s component-based architecture with Chrome’s powerful extension APIs enables developers to create sophisticated extensions with modern development workflows. This comprehensive guide will walk you through building Chrome extensions with React, from project setup to deployment.
Whether you are a seasoned React developer looking to expand into browser extensions or a Chrome extension developer wanting to adopt modern UI patterns, this tutorial provides everything you need to build production-ready extensions using React and Manifest V3.
Why Use React for Chrome Extensions?
React has become the de facto standard for building user interfaces in web development, and its adoption in Chrome extension development continues to grow rapidly in 2025. There are several compelling reasons to choose React for your Chrome extension projects.
Component-Based Architecture
React’s component-based architecture aligns perfectly with how Chrome extensions are structured. Extensions typically consist of multiple entry points—the popup, options page, content scripts, and background service worker—each requiring their own UI. React components allow you to build reusable UI elements that work consistently across all these different contexts.
When you build a react chrome extension, you can create a design system of buttons, forms, inputs, and layouts that maintain visual and functional consistency throughout your extension. This becomes particularly valuable as your extension grows in complexity.
State Management Benefits
Chrome extensions often need to manage complex state across different contexts. React’s state management capabilities, combined with Context API or libraries like Zustand, make it straightforward to handle application state, synchronize data between popup and background scripts, and maintain UI consistency.
Development Experience
Using React for Chrome extension development provides access to modern tooling including hot reload, TypeScript support, and a vast ecosystem of npm packages. The development experience mirrors what you would expect from building a modern web application, making it comfortable for developers already familiar with React.
Performance Optimizations
React 19, released in 2025, brings significant performance improvements including automatic batching, concurrent rendering, and reduced bundle sizes. These optimizations are particularly valuable in the constrained environment of Chrome extensions, where memory usage and load times directly impact user experience.
Setting Up Your React Chrome Extension Project
The first step in building a react chrome extension is setting up your development environment. While you can configure everything manually, using a template or scaffolding tool specifically designed for Chrome extensions with React will save significant time.
Using Create React App with Chrome Extension Templates
One popular approach is to use Create React App as your base and configure it for Chrome extension development. However, this requires significant manual configuration. Instead, consider using specialized templates that handle the complex build configuration required for Chrome extensions.
For a react popup extension specifically, you will need to configure your build system to output multiple entry points—the popup HTML, options page, and any content scripts—while maintaining Hot Module Replacement for development.
Recommended Project Structure
A well-organized react chrome extension project should follow this structure:
my-extension/
├── public/
│ ├── manifest.json
│ ├── popup.html
│ └── icons/
├── src/
│ ├── components/
│ ├── popup/
│ ├── options/
│ ├── content/
│ ├── background/
│ └── App.tsx
├── package.json
└── webpack.config.js
This structure separates your React application code from the static files that Chrome requires, making it easier to maintain and develop your extension.
Essential Dependencies
When setting up your react chrome extension tutorial project, you will need several key dependencies. React and ReactDOM are, of course, essential. For build tooling, Webpack or Vite are the most popular choices in 2025. TypeScript is highly recommended for maintaining code quality as your extension grows.
You will also need packages for communicating between your React components and Chrome APIs. The @chrome-extension-manager/bridge package or similar utilities can simplify message passing between your React popup and background scripts.
Understanding Manifest V3 Configuration
Manifest V3 is mandatory for all new Chrome extensions since 2023, and understanding its configuration is critical for react chrome extension development in 2025. The manifest file defines your extension’s capabilities, permissions, and entry points.
Basic Manifest Configuration
Your manifest.json must specify Manifest V3 and include the appropriate host permissions for your extension’s functionality. For a react popup extension, you will declare the popup action and specify which files to load.
{
"manifest_version": 3,
"name": "My React Extension",
"version": "1.0.0",
"action": {
"default_popup": "popup.html",
"default_icon": "icons/icon48.png"
},
"permissions": ["activeTab", "storage"],
"host_permissions": ["<all_urls>"]
}
Handling Service Workers
In Manifest V3, background scripts run as service workers rather than persistent background pages. This change has significant implications for how you architect your extension. Service workers have a different lifecycle and cannot maintain in-memory state between events.
For React applications, this means you need to be intentional about state management. Any state that needs to persist should be stored in chrome.storage rather than in memory variables. Your React components should be designed to handle the asynchronous nature of retrieving data from storage.
Building the Popup Interface with React
The popup is often the primary interface users interact with in a Chrome extension. Building a react popup extension requires understanding how React integrates with the limited lifecycle of popup windows.
Popup Lifecycle Considerations
Chrome extension popups have a short lifespan—they close when the user clicks outside of them or navigates away. This presents challenges for React developers accustomed to persistent application state.
When designing your react popup extension, consider these best practices:
First, always load state from chrome.storage on component mount. The popup may be closed and reopened multiple times, so you cannot rely on in-memory state persisting between sessions.
Second, use effects to synchronize state with background scripts. If your popup needs data from the background service worker, establish communication on mount and update your React state accordingly.
Third, keep popup interactions quick and responsive. Users expect popups to open instantly, so optimize your initial render and avoid heavy computations in the popup context.
Sample Popup Component
A well-structured react popup extension popup component might look like this:
import React, { useEffect, useState } from 'react';
import { getDataFromStorage } from '../utils/storage';
export function Popup() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadData() {
try {
const storedData = await getDataFromStorage('extensionData');
setData(storedData);
} catch (error) {
console.error('Failed to load data:', error);
} finally {
setLoading(false);
}
}
loadData();
}, []);
if (loading) {
return <div className="popup-loading">Loading...</div>;
}
return (
<div className="popup-container">
<h1>My Extension</h1>
{/* Your popup content */}
</div>
);
}
Content Scripts and React Integration
Content scripts run in the context of web pages and require special handling when using React. Unlike popup pages, content scripts must be careful about conflicting with the page’s existing JavaScript.
Injecting React into Web Pages
To use React in content scripts, you typically create a container element and mount your React application to it. This approach allows you to build sophisticated UIs that appear to be part of the web page while maintaining separation from the page’s own JavaScript.
function injectReactComponent() {
const container = document.createElement('div');
container.id = 'my-extension-root';
document.body.appendChild(container);
const root = ReactDOM.createRoot(container);
root.render(<App />);
}
// Run when the page loads
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', injectReactComponent);
} else {
injectReactComponent();
}
Handling Page Lifecycle
Content scripts in Manifest V3 run in a separate world, which provides some protection but also requires careful management. Your React components should handle page navigation gracefully, as single-page applications may change content without full page reloads.
Consider using mutation observers or the chrome.scripting API to re-render your React components when the page content changes significantly.
State Management in React Chrome Extensions
Effective state management is crucial for building complex Chrome extensions with React. You need to handle state across multiple contexts—the popup, options page, content scripts, and background service worker.
Using Chrome Storage
Chrome’s storage API provides persistent state that works across all extension contexts. For React applications, you can create custom hooks that sync React state with chrome.storage.
function useChromeStorage(key, initialValue) {
const [value, setValue] = useState(initialValue);
useEffect(() => {
chrome.storage.local.get(key, (result) => {
if (result[key] !== undefined) {
setValue(result[key]);
}
});
const listener = (changes) => {
if (changes[key]) {
setValue(changes[key].newValue);
}
};
chrome.storage.onChanged.addListener(listener);
return () => chrome.storage.onChanged.removeListener(listener);
}, [key]);
const updateValue = (newValue) => {
setValue(newValue);
chrome.storage.local.set({ [key]: newValue });
};
return [value, updateValue];
}
Communicating Between Contexts
Chrome extensions use message passing to communicate between different contexts. For react chrome extension development, you should establish clear patterns for this communication.
For simple cases, you can use chrome.runtime.sendMessage and chrome.runtime.onMessage. For more complex scenarios involving streaming data or persistent connections, consider using chrome.runtime.connect with named ports.
Building the Options Page
Most production Chrome extensions include an options page where users can configure behavior. React makes building these settings pages straightforward, applying the same component patterns you would use in any React application.
Options Page Structure
Your options page should be structured as a separate React application that mounts to its own HTML page. This separation keeps the options page lightweight and ensures it loads quickly when users access it.
function OptionsPage() {
const [settings, setSettings] = useChromeStorage('settings', defaultSettings);
const handleSettingChange = (key, value) => {
setSettings({ ...settings, [key]: value });
};
return (
<div className="options-page">
<h1>Extension Settings</h1>
<SettingsForm
settings={settings}
onChange={handleSettingChange}
/>
</div>
);
}
Responsive Design for Options
Options pages open in a full browser tab rather than the constrained popup window, so you have more space for complex configurations. However, many users access options on mobile devices or smaller screens, so responsive design remains important.
Performance Optimization for React Extensions
Chrome extensions must be performant to provide good user experience. Users expect extensions to load quickly and not impact browser performance. React applications can achieve excellent performance with appropriate optimization.
Reducing Bundle Size
Use code splitting to reduce your initial bundle size. Webpack and other bundlers support dynamic imports that allow you to load components only when needed. For extension popups, load only the minimum code required for initial render.
Tree shaking eliminates dead code from your production bundles. Ensure your bundler is configured to remove unused exports, particularly from large libraries like lodash or moment.js.
Memoization Strategies
React’s memoization tools—React.memo, useMemo, and useCallback—help prevent unnecessary re-renders. This is particularly valuable in extension contexts where updates may occur frequently, such as when listening to browser events.
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
const processedData = useMemo(() => {
return complexDataProcessing(data);
}, [data]);
return <div>{processedData}</div>;
});
Lazy Loading
For extensions with multiple features, consider lazy loading components that are not immediately necessary. This approach keeps your popup fast while still providing access to advanced features when users need them.
Testing React Chrome Extensions
Comprehensive testing ensures your extension works correctly across different contexts and edge cases. Testing React Chrome extensions requires understanding the unique environment in which they run.
Unit Testing Components
Test your React components in isolation using testing libraries like Jest and React Testing Library. Mock Chrome APIs to ensure your components work correctly without actual browser APIs during unit tests.
import { render, screen } from '@testing-library/react';
import { Popup } from '../popup/Popup';
test('displays extension name', () => {
render(<Popup />);
expect(screen.getByText('My Extension')).toBeInTheDocument();
});
Integration Testing
Integration tests verify that your extension components work correctly with Chrome APIs. Use Chrome’s headless mode or tools like Puppeteer to automate extension testing in a real browser environment.
Manifest Testing
Validate your manifest.json to ensure it follows Manifest V3 requirements and declares all necessary permissions. Chrome provides a linter that catches common manifest errors.
Deployment and Publishing
Once your react chrome extension is complete, you need to prepare it for distribution through the Chrome Web Store. This process involves building production bundles and creating store listings.
Building for Production
Configure your build system to create optimized production bundles. Remove development dependencies, enable minification, and generate source maps only if needed for debugging published extensions.
Your build process should output all required files to a single directory that can be packaged into a ZIP file for upload.
Chrome Web Store Submission
Prepare compelling store listing materials including a clear description, screenshots, and a concise summary. Emphasize the value your extension provides and highlight key features.
Ensure your extension complies with Chrome Web Store policies, particularly regarding user data collection and privacy practices. Manifest V3 has stricter requirements for extension capabilities, so review the latest policies before submission.
Conclusion and Next Steps
Building Chrome extensions with React in 2025 combines the best of modern web development with the unique capabilities of the Chrome extension platform. React’s component architecture, state management, and development tooling make it an excellent choice for extension development.
Throughout this react chrome extension tutorial, we have covered the essential topics: project setup, Manifest V3 configuration, popup development, content scripts, state management, performance optimization, testing, and deployment. With this foundation, you can build sophisticated extensions that provide real value to Chrome users.
As you continue developing, explore advanced topics like declarative Net Requests for network filtering, Side Panel API for persistent UIs, and the various Chrome AI APIs that are becoming available. The Chrome extension ecosystem continues to evolve, and React developers are well-positioned to build the next generation of browser tools.
Start your react chrome extension project today, and join the thousands of developers creating extensions that millions of users rely on every day.
Related Articles
- Building Chrome Extensions with Vue Complete Guide
- Building Chrome Extensions with Svelte Complete Guide
- Chrome Extension Popup Design Best Practices
Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.