Image Optimization
Next.js provides a built-in <Image> component that automatically handles image optimization and responsive layouts.
// app/page.js
import Image from 'next/image';
export default function Page() {
return (
<div>
<Image
src="/path/to/image.jpg"
alt="Sample image"
width={800}
height={600}
/>
</div>
);
}Notes
- Size Attributes: Ensure correct
widthandheightattributes are provided so Next.js can generate appropriate responsive images. - Unoptimized Attribute: Set
unoptimizedtotrueif you do not want Next.js to handle image optimization.
Video Optimization
Use the HTML5 <video> tag to embed videos, allowing control over playback, pausing, and other behaviors.
// app/page.js
export default function Page() {
return (
<div>
<video controls>
<source src="/path/to/video.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
);
}Notes
- Format Compatibility: Provide multiple video source formats to support different browsers.
- Compression: Ensure video files are compressed before uploading to reduce file size.
Font Optimization
Using Web Fonts
Web fonts enhance a website’s visual appeal but may increase page load times. Use the following strategies to optimize font loading:
// app/page.js
import dynamic from 'next/dynamic';
const DynamicFontLink = dynamic(() => import('next/font/google'), {
ssr: false,
});
export default function Page() {
return (
<div>
<DynamicFontLink
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
as="style"
crossOrigin=""
/>
<h1 style={{ fontFamily: 'Roboto', fontSize: '2rem' }}>Hello World</h1>
</div>
);
}Notes
- Lazy Loading: Use
next/dynamicto load fonts asynchronously, deferring font loading until after initial page interaction. - Font Display Strategy: Use the
font-displayproperty (e.g.,font-display: swap) to control font loading and display behavior. - Font Subsets: Load only the required character subsets to reduce font file size.
Metadata
Metadata, including page titles, descriptions, and keywords, is critical for SEO. Use next/head or next/document to dynamically set page metadata.
// app/page.js
import Head from 'next/head';
export default function Page() {
return (
<>
<Head>
<title>My Page Title</title>
<meta name="description" content="A description of my page" />
<meta name="keywords" content="keyword1, keyword2" />
</Head>
<h1>Welcome to My App</h1>
<p>This is a sample page.</p>
</>
);
}Script Optimization
Optimizing script loading can significantly improve page load speed and performance.
Using next/script
The next/script component allows control over script loading timing.
// app/page.js
import Script from 'next/script';
export default function Page() {
return (
<>
<Script
strategy="beforeInteractive"
src="https://example.com/my-script.js"
/>
<h1>Welcome to My App</h1>
<p>This is a sample page.</p>
</>
);
}Strategy Attribute
beforeInteractive: Script loads before document parsing is complete.afterInteractive: Script loads after document parsing is complete.lazyOnload: Script loads during browser idle time.
Bundle Analyzer
A bundle analyzer helps understand the application’s bundle output, identifying areas for optimization.
Using next/dist/build/webpack/loaders/bundle-analyzer-plugin
- Install
webpack-bundle-analyzer:
npm install --save-dev webpack-bundle-analyzer- Configure
next.config.js:
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({});- Run the analysis:
NEXT_PUBLIC_ANALYZE=true next buildLazy Loading
Lazy loading (also known as deferred loading) improves initial page load speed by loading non-critical resources only when needed.
Using Intersection Observer API
The Intersection Observer API detects when an element enters the viewport, triggering lazy loading.
// app/page.js
import Image from 'next/image';
import { useRef, useState } from 'react';
import { useIntersectionObserver } from 'react-intersection-observer';
function LazyImage({ src, alt }) {
const [isVisible, setIsVisible] = useState(false);
const ref = useRef(null);
const handleIntersection = (entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
});
};
useIntersectionObserver(ref, handleIntersection, { threshold: 0.1 });
return (
<div ref={ref}>
{isVisible ? (
<Image
src={src}
alt={alt}
width={300}
height={200}
/>
) : (
<div>Loading...</div>
)}
</div>
);
}
export default function Page() {
return (
<div>
<LazyImage
src="/path/to/image.jpg"
alt="Sample image"
/>
</div>
);
}OpenTelemetry
OpenTelemetry is a framework for collecting, processing, and exporting telemetry data (e.g., metrics, logs, and traces). In Next.js, use OpenTelemetry to collect application performance data.
Install OpenTelemetry
npm install @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/instrumentation-fetchInitialize OpenTelemetry
// telemetry.js
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { ConsoleSpanExporter } from '@opentelemetry/exporter-console';
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new BatchSpanProcessor(new ConsoleSpanExporter()));
provider.register();
// Instrument the fetch API
import { registerInstrumentations } from '@opentelemetry/instrumentation';
registerInstrumentations({
instrumentations: [getNodeAutoInstrumentations()],
});Using Tracer
// app/page.js
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('my-app');
export default function Page() {
const span = tracer.startSpan('my-operation');
span.end();
return (
<div>
<h1>Welcome to My App</h1>
<p>This is a sample page.</p>
</div>
);
}Static Assets in Public
The public directory stores static assets like images and fonts, accessible directly via the / path.
Example
Assume a logo.png image file is located in the public directory.
// app/page.js
import Image from 'next/image';
export default function Page() {
return (
<div>
<Image
src="/logo.png"
alt="Logo"
width={100}
height={100}
/>
</div>
);
}Third-Party Libraries
Third-party libraries can significantly impact application performance. Choose lightweight libraries and load only required modules.
Assume you are using a library named my-third-party-library.
// app/page.js
import { specificFunction } from 'my-third-party-library';
export default function Page() {
specificFunction();
return (
<div>
<h1>Welcome to My App</h1>
<p>This is a sample page.</p>
</div>
);
}Memory Usage
Analyzing memory usage helps identify memory leaks and other performance issues.
Using Chrome DevTools
Chrome DevTools provides memory analysis tools to inspect memory usage.
- Open DevTools: Right-click the page and select “Inspect.”
- Go to the Memory panel.
- Take a memory snapshot: Click the “Take snapshot” button.
Using Node.js Memory Analysis Tools
For server-side memory analysis, use Node.js built-in tools or third-party libraries like memwatch-next.
// server.js
require('memwatch-next');
// ... your server code ...



