Installation
Install two packages: stream-chat, the JavaScript client that holds the state, and stream-chat-react, the components. stream-chat-react 15 and stream-chat 10 are release candidates, both published under the rc tag. stream-chat-react 15 needs stream-chat 10.0.0-rc.20 or later, and React 17, 18 or 19.
Install with npm
npm install stream-chat@rc stream-chat-react@rcInstall with Yarn
yarn add stream-chat@rc stream-chat-react@rcImport the default stylesheet once in your app:
import "stream-chat-react/dist/css/index.css";Some optional parts of the SDK have their own entry point and stylesheet. See Entry points and CSS files below. To build a first app, continue with the Quick start.
Best practices
- Install both
stream-chatandstream-chat-reactto keep client and UI versions aligned. - Import the default stylesheet once at app entry to avoid duplicate CSS and overrides.
- Import stylesheets from
stream-chat-react/dist/css/. - Prefer ESM named imports from
stream-chat-reactto enable tree-shaking. - Keep bundler config stock first; only add customizations if bundle size or SSR needs demand it.
- Verify the build pipeline handles CSS imports in your target framework before shipping.
Upgrade stream-chat and stream-chat-react together. The React SDK depends on newer low-level client features, so mismatched versions can fail at runtime even if installation succeeds.
Bundle size
The SDK is optimized for tree-shaking. Bundlers like Vite/Rollup, Webpack, and esbuild can remove unused components, so your final size depends on what you actually render (not the total package size reported by Bundlephobia).
Best practices for optimal bundle size
Besides minifying and gzipping your app, here’s how to keep stream-chat-react as small as possible.
Imports that support tree-shaking
- Use named ESM imports
// ✅ correct
import { Chat, Channel, MessageList, MessageComposer } from "stream-chat-react";
// ❌ Avoid (harder to tree-shake)
import * as SCR from "stream-chat-react";
// ❌ Avoid re-export from your own index file
export * from "stream-chat-react";
// ❌ Not exported: deep `dist/` paths. Import from an entry point instead.
import * as SCR from "stream-chat-react/dist/components/Avatar/Avatar";-
Don’t use CJS (
require()) in client code when ESM is available. -
Only import what you render. If you don’t show a component, don’t import it, so that your bundler can drop it.
Tree-shaking works with stream-chat-react because it ships ESM builds with granular exports. Use named imports and lazy-load optional features so bundlers can drop unused code.
Bundler docs
Modern bundlers document tree-shaking and code-splitting; here are some starting points:
| Framework | Links |
|---|---|
| Vite (Rollup) tree-shaking and build | https://vitejs.dev/guide/build.html, https://rollupjs.org/introduction/#tree-shaking |
| Webpack tree-shaking and code splitting | https://webpack.js.org/guides/tree-shaking/, https://webpack.js.org/guides/code-splitting/ |
| Next.js dynamic imports | https://nextjs.org/docs/app/api-reference/turbopack#bundle-sizes, https://nextjs.org/docs/app/getting-started/server-and-client-components#reducing-js-bundle-size |
| esbuild tree-shaking | https://esbuild.github.io/api/#tree-shaking |
| General: what is tree-shaking? | https://developer.mozilla.org/docs/Glossary/Tree_shaking |
| React: code splitting with React.lazy | https://react.dev/reference/react/lazy |
Bundle size measurement
Bundle size analyzers by framework:
| Framework | Links |
|---|---|
| Vite / Rollup: bundle visualizer | https://rollupjs.org/introduction/#visualizer |
| Webpack bundle analyzer | https://github.com/webpack-contrib/webpack-bundle-analyzer |
| Next.js: Next bundle analyzer | https://nextjs.org/docs/app/guides/package-bundling#analyzing-javascript-bundles |
Common gotchas (and easy fixes)
| Question | Answer |
|---|---|
| “My bundle didn’t shrink.” | Usually caused by namespace imports. Switch to named imports from the entry points and rebuild. |
| “I removed a component, but it’s still in the bundle.” | Something re-exports it or you import it indirectly. Import only exactly what you render, directly from stream-chat-react. |
| “Styles disappeared.” | Don’t mark CSS as tree-shakable. Check how to import styles for stream-chat-react correctly. |
| “Gallery/emoji added lots of KB.” | Lazy-load those modules. Many libraries ship large data (sprites, emoji sheets). Load them only when needed. |
Entry points and CSS files
The SDK has one main entry point and six optional ones. An optional part is its own entry point, so an app that never imports it doesn't bundle it. A part with its own styles has its own stylesheet, imported after index.css.
| Part | Import from | Stylesheet |
|---|---|---|
| Components, contexts and hooks | stream-chat-react |
index.css |
Layout: ChatView and its slots |
stream-chat-react/slot-layout |
included in index.css |
| Slot geometry: which layout slots are collapsed or covered | stream-chat-react/slot-geometry |
none |
| Channel details: members, media, files and pinned messages | stream-chat-react/channel-detail |
channel-detail.css |
| Emoji picker and emoji suggestions in the composer | stream-chat-react/emojis |
emoji-picker.css |
| MP3 encoding for voice recordings | stream-chat-react/mp3-encoder |
none |
| AI components: streaming messages, Markdown, the AI composer | stream-chat-react/ai-components |
ai-components.css |
Every stylesheet is in stream-chat-react/dist/css/. For example, an app that uses channel details and the emoji picker imports:
import "stream-chat-react/dist/css/index.css";
import "stream-chat-react/dist/css/channel-detail.css";
import "stream-chat-react/dist/css/emoji-picker.css";Two entry points need packages that you install yourself, only if you use them:
stream-chat-react/emojisneedsemoji-martand@emoji-mart/data.stream-chat-react/mp3-encoderneeds@breezystack/lamejs.
One more stylesheet, emoji-replacement.css, loads a color font for country flag emoji, which Windows shows as letters. Import it and set useImageFlagEmojisOnWindows on Chat. The class it needs is added to each Channel and to ChannelNavigation's root, so the font applies inside them.
Each entry point's exports are listed in Entry points and CSS files.
To load the stylesheets into a CSS cascade layer, so your own rules win without !important, see Theming.