@snapkit-studio/react
v1.7.3
Published
React components for Snapkit image optimization
Downloads
23
Maintainers
Readme
@snapkit-studio/react
React components and hooks for Snapkit Studio image optimization. This package provides high-performance React image components with automatic format optimization, responsive loading, and Next.js-compatible APIs.
Installation
npm install @snapkit-studio/react
# or
yarn add @snapkit-studio/react
# or
pnpm add @snapkit-studio/reactFeatures
- React Image Component - Drop-in replacement for HTML img with optimization
- Flexible CDN Configuration - Use Snapkit CDN or integrate with your existing infrastructure (CloudFront, GCS, Cloudflare)
- Provider-less Architecture - Direct component usage without wrappers
- Next.js Compatible - Same API as Next.js Image component
- Environment Auto-Detection - Automatically reads framework-specific environment variables
- Automatic Format Detection - AVIF, WebP, JPEG fallback
- Responsive Images - Automatic srcset generation
- DPR-based Optimization - Crisp images on high-DPI displays
- Lazy Loading - Intersection Observer based
- Network-aware Quality - Automatic adjustment based on connection
- TypeScript Support - Full type definitions included
Quick Start
1. CDN Configuration
Choose between Snapkit CDN for zero-config optimization or custom CDN integration:
Option A: Snapkit CDN (Recommended)
# .env (Vite/CRA) - Snapkit CDN
VITE_IMAGE_CDN_PROVIDER=snapkit
VITE_SNAPKIT_ORGANIZATION=your-organization-nameOption B: Custom CDN Integration
# .env (Vite/CRA) - Custom CDN (Google Cloud Storage example)
VITE_IMAGE_CDN_PROVIDER=custom
VITE_IMAGE_CDN_URL=https://storage.googleapis.com/my-image-bucket
# AWS CloudFront example
# VITE_IMAGE_CDN_PROVIDER=custom
# VITE_IMAGE_CDN_URL=https://d1234567890.cloudfront.net
# Cloudflare or any custom domain
# VITE_IMAGE_CDN_PROVIDER=custom
# VITE_IMAGE_CDN_URL=https://images.example.com2. Basic Usage
import { Image } from '@snapkit-studio/react';
function MyComponent() {
return (
<Image
src="/project/hero.jpg"
alt="Hero Image"
width={800}
height={600}
priority
transforms={{ format: 'auto' }}
/>
);
}Import Options
Selective Imports (Recommended)
// Image component only (~9 KB)
// Specific hooks only (~8 KB)
import { useImageOptimization } from '@snapkit-studio/react/hooks';
import { Image } from '@snapkit-studio/react/image';
// Utility functions only (~5 KB)
import {
createImageStyle,
mergeConfiguration,
} from '@snapkit-studio/react/utils';Full Bundle Import
// Full bundle (~22 KB)
import { Image, useImageRefresh } from '@snapkit-studio/react';CDN Configuration
The library supports flexible CDN configuration through environment variables. Configuration is automatically detected using getCdnConfig() from @snapkit-studio/core.
Snapkit CDN
Zero-configuration setup with automatic optimization, smart format delivery, and global edge caching:
# .env (Vite/CRA)
VITE_IMAGE_CDN_PROVIDER=snapkit
VITE_SNAPKIT_ORGANIZATION=your-organization-name
# .env.local (Next.js) - If using React package in Next.js
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=snapkit
NEXT_PUBLIC_SNAPKIT_ORGANIZATION=your-organization-nameCustom CDN Integration
Use your existing CDN infrastructure with Snapkit's optimization features:
# .env (Vite/CRA) - Custom CDN examples
VITE_IMAGE_CDN_PROVIDER=custom
VITE_IMAGE_CDN_URL=https://your-cdn-domain.com
# .env.local (Next.js) - Custom CDN examples
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=custom
NEXT_PUBLIC_IMAGE_CDN_URL=https://your-cdn-domain.comEnvironment Variables Reference
Vite/CRA
| Variable | Required For | Description |
| --------------------------- | ------------ | ----------------------------------- |
| VITE_IMAGE_CDN_PROVIDER | All setups | CDN provider: snapkit or custom |
| VITE_SNAPKIT_ORGANIZATION | Snapkit CDN | Your Snapkit organization name |
| VITE_IMAGE_CDN_URL | Custom CDN | Your custom CDN base URL |
Next.js (when using React package)
| Variable | Required For | Description |
| --------------------------------------- | ------------ | ----------------------------------- |
| NEXT_PUBLIC_IMAGE_CDN_PROVIDER | All setups | CDN provider: snapkit or custom |
| NEXT_PUBLIC_SNAPKIT_ORGANIZATION | Snapkit CDN | Your Snapkit organization name |
| NEXT_PUBLIC_IMAGE_CDN_URL | Custom CDN | Your custom CDN base URL |
Image Component Props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------- | -------- | ---------------------------- |
| src | string | - | Image path (required) |
| alt | string | - | Alt text (required) |
| width | number | - | Image width |
| height | number | - | Image height |
| fill | boolean | false | Fill parent container |
| sizes | string | - | Responsive size settings |
| quality | number | 85 | Image quality (1-100) |
| priority | boolean | false | Priority loading |
| loading | 'lazy' \| 'eager' | 'lazy' | Loading method |
| optimizeFormat | 'auto' \| 'avif' \| 'webp' \| 'off' | 'auto' | Format optimization |
| transforms | ImageTransforms | {} | Image transformation options |
Key Features
Automatic Format Detection
The library uses Canvas-based detection to determine browser support for modern image formats:
// Automatically serves AVIF, WebP, or JPEG based on browser
<Image
src="/photo.jpg"
alt="Photo"
width={800}
height={600}
optimizeFormat="auto"
/>
// Force specific format
<Image
src="/logo.png"
alt="Logo"
width={200}
height={100}
optimizeFormat="webp"
/>Format Selection Logic:
- AVIF: Chosen if browser supports it (Chrome 85+, Firefox 93+, Edge 91+, Safari 16+)
- WebP: Chosen if AVIF not supported but WebP is (Chrome 23+, Firefox 65+, Edge 79+, Safari 14+)
- JPEG: Final fallback for all other browsers
Detection Method:
- Client-side: Uses
Canvas.toDataURL()to test format support - Server-side: Conservative fallback to basic formats for SSR consistency
Responsive Images
// DPR-based srcset (1x, 2x, 3x) - default behavior
<Image
src="/image.jpg"
alt="High-DPI optimized"
width={800}
height={600}
/>
// Width-based srcset for responsive layouts
<Image
src="/banner.jpg"
alt="Responsive banner"
width={1200}
height={400}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw"
/>Image Transformations
// Basic transformations
<Image
src="/photo.jpg"
alt="Transformed"
width={400}
height={400}
transforms={{
fit: "cover", // contain | cover | fill | inside | outside
quality: 90, // Override quality
blur: 20, // Blur effect
grayscale: true, // Convert to grayscale
}}
/>
// Extract/crop region
<Image
src="/large-image.jpg"
alt="Cropped section"
width={300}
height={200}
transforms={{
extract: {
x: 100,
y: 100,
width: 300,
height: 200,
},
}}
/>Loading Control
// Priority loading for above-the-fold images
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority={true}
/>
// Lazy loading (default)
<Image
src="/content.jpg"
alt="Content image"
width={400}
height={300}
loading="lazy"
/>Event Handling
function ImageWithEvents() {
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
return (
<div>
{isLoading && <div>Loading...</div>}
{hasError && <div>Failed to load image</div>}
<Image
src="/photo.jpg"
alt="Photo"
width={600}
height={400}
onLoad={() => {
setIsLoading(false);
console.log('Image loaded successfully');
}}
onError={() => {
setIsLoading(false);
setHasError(true);
console.log('Failed to load image');
}}
/>
</div>
);
}Type Definitions
// Image component props
interface SnapkitImageProps {
src: string;
alt: string;
width?: number;
height?: number;
fill?: boolean;
sizes?: string;
quality?: number;
priority?: boolean;
loading?: 'lazy' | 'eager';
optimizeFormat?: 'auto' | 'avif' | 'webp' | 'off';
transforms?: ImageTransforms;
organizationName?: string;
className?: string;
style?: React.CSSProperties;
onLoad?: React.ReactEventHandler<HTMLImageElement>;
onError?: React.ReactEventHandler<HTMLImageElement>;
}
// Image transformations
interface ImageTransforms {
width?: number;
height?: number;
quality?: number;
format?: ImageFormat;
fit?: 'contain' | 'cover' | 'fill' | 'inside' | 'outside';
blur?: number;
grayscale?: boolean;
flip?: boolean;
flop?: boolean;
extract?: {
x: number;
y: number;
width: number;
height: number;
};
}
// Image formats
type ImageFormat = 'auto' | 'avif' | 'webp' | 'jpeg' | 'png' | 'gif';Migration from Next.js Image
The Snapkit Image component is designed to be a drop-in replacement for Next.js Image:
// Before (Next.js Image)
import Image from 'next/image';
<Image
src="/photo.jpg"
alt="Photo"
width={800}
height={600}
quality={90}
priority
sizes="(max-width: 768px) 100vw, 50vw"
/>
// After (Snapkit Image)
import { Image } from '@snapkit-studio/react';
<Image
src="/photo.jpg"
alt="Photo"
width={800}
height={600}
quality={90}
priority
sizes="(max-width: 768px) 100vw, 50vw"
// Additional Snapkit features
transforms={{ fit: "cover" }}
optimizeFormat="auto"
/>Live Demo
Experience all features in action with our interactive demo:
🚀 Live Demo → - Real-time examples with source code
Explore features including:
- Image transformations with live preview
- Error boundary demonstrations
- Network-aware quality adjustments
- DPR optimization examples
- All component props and configurations
Browser Support
- AVIF: Chrome 85+, Firefox 93+, Edge 91+ (Chromium), Safari 16+
- WebP: Chrome 23+, Firefox 65+, Edge 79+ (Chromium), Safari 14+
- Lazy Loading: Chrome 76+, Firefox 75+, Edge 79+, Safari 15.4+
- Intersection Observer: Chrome 58+, Firefox 55+, Edge 79+, Safari 12.1+
Note: Only Chromium-based Edge (79+) is supported. Legacy EdgeHTML Edge (18 and below) is not supported.
Format Selection: Automatically selects the best supported format in order: AVIF → WebP → JPEG. Falls back to JPEG in browsers that don't support modern formats.
Testing
The package includes comprehensive test coverage with automatic coverage reporting:
# Run tests
npm test
# Run with coverage report
npm run test:coverage
# Watch mode for development
npm test -- --watchTest Coverage
The package maintains high test coverage standards:
- Coverage Threshold: 80% minimum for branches, functions, lines, and statements
- Test Framework: Vitest with jsdom environment and v8 coverage provider
- Coverage Reports: Text (console), JSON, HTML, and LCOV formats
- Coverage Exclusions: Test files, configuration files, type definitions, and test utilities
Coverage reports are generated in multiple formats:
- Text: Console output during test runs
- HTML: Detailed coverage report in
coverage/directory - LCOV: For CI/CD integration and coverage tools
- JSON: Machine-readable coverage data
Test Environment
Tests run in a jsdom environment to simulate browser behavior for React components testing.
Development
# Install dependencies
npm install
# Build package
npm run build
# Watch mode for development
npm run dev
# Type checking
npm run check-types
# Linting
npm run lintContributing
See the main repository README for contribution guidelines.
License
MIT
