Day 10: Deployment and Production
What You'll Learn Today
- Deploying to Vercel
- Managing environment variables
- Performance optimization
- Error monitoring
- Next steps
Building for Production
Production Build
npm run build
Build output:
Route (app) Size First Load JS
β β / 5.2 kB 89.5 kB
β β /about 2.1 kB 86.4 kB
β β /blog 3.4 kB 87.7 kB
β β /blog/[slug] 4.1 kB 88.4 kB
β Ζ /dashboard 6.3 kB 90.6 kB
β (Static) prerendered as static content
β (SSG) prerendered as static HTML (uses generateStaticParams)
Ζ (Dynamic) server-rendered on demand
Test Production Mode Locally
npm run build && npm run start
Deploying to Vercel
Connect GitHub Repository
- Go to Vercel
- Login with GitHub
- Click "New Project"
- Import repository
- Review settings and click "Deploy"
flowchart LR
subgraph GitHub["GitHub"]
PUSH["git push"]
end
subgraph Vercel["Vercel"]
BUILD["Build"]
DEPLOY["Deploy"]
CDN["Global CDN"]
end
PUSH --> BUILD --> DEPLOY --> CDN
style GitHub fill:#24292e,color:#fff
style Vercel fill:#000,color:#fff
Deploy with Vercel CLI
# Install Vercel CLI
npm install -g vercel
# Deploy
vercel
# Deploy to production
vercel --prod
Preview Deployments
When you create a PR, a preview URL is automatically generated.
https://my-app-git-feature-branch-username.vercel.app
Managing Environment Variables
Local Environment
# .env.local (include in gitignore)
DATABASE_URL="postgresql://..."
NEXTAUTH_SECRET="your-secret"
NEXT_PUBLIC_API_URL="http://localhost:3000/api"
Types of Environment Variables
| Prefix | Exposure |
|---|---|
NEXT_PUBLIC_ |
Exposed to browser |
| None | Server only |
// Available on server only
const secret = process.env.DATABASE_URL;
// Available in browser too
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Setting Environment Variables on Vercel
- Project Settings β Environment Variables
- Select environment (Production, Preview, Development)
- Enter key and value
flowchart TB
subgraph Environments["Environments"]
DEV["Development<br/>.env.local"]
PREVIEW["Preview<br/>Per PR"]
PROD["Production<br/>Live"]
end
subgraph Variables["Environment Variables"]
DB_DEV["DATABASE_URL<br/>(Dev DB)"]
DB_PREVIEW["DATABASE_URL<br/>(Staging DB)"]
DB_PROD["DATABASE_URL<br/>(Prod DB)"]
end
DEV --> DB_DEV
PREVIEW --> DB_PREVIEW
PROD --> DB_PROD
style Environments fill:#3b82f6,color:#fff
style Variables fill:#22c55e,color:#fff
Performance Optimization
Enable Next.js Analytics
// src/app/layout.tsx
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
);
}
Analyze Bundle Size
npm install @next/bundle-analyzer
// next.config.ts
import bundleAnalyzer from "@next/bundle-analyzer";
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
export default withBundleAnalyzer({
// config
});
ANALYZE=true npm run build
Performance Checklist
| Item | Solution |
|---|---|
| Images | Use next/image |
| Fonts | Use next/font |
| Large libraries | Dynamic imports |
| Unnecessary re-renders | Memoization (memo, useMemo) |
| Third-party scripts | Use next/script |
Dynamic Imports
import dynamic from "next/dynamic";
// Load only on client
const Chart = dynamic(() => import("@/components/Chart"), {
loading: () => <div>Loading chart...</div>,
ssr: false,
});
export default function DashboardPage() {
return (
<div>
<h1>Dashboard</h1>
<Chart />
</div>
);
}
Third-Party Scripts with next/script
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXX');
`}
</Script>
</body>
</html>
);
}
Error Monitoring
Sentry Integration
npx @sentry/wizard@latest -i nextjs
// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 1.0,
});
Error Boundary
// src/app/error.tsx
"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h2 className="text-2xl font-bold mb-4">Something went wrong</h2>
<button
onClick={reset}
className="px-4 py-2 bg-blue-600 text-white rounded"
>
Try again
</button>
</div>
</div>
);
}
Security
Security Headers
// next.config.ts
const nextConfig = {
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
{
key: "Content-Security-Policy",
value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';",
},
],
},
];
},
};
export default nextConfig;
Environment Variable Security
- Only use
NEXT_PUBLIC_prefix when necessary - Keep sensitive info server-side only
- Always include
.env.localin.gitignore
Production Best Practices
Deployment Checklist
## Pre-Deployment Checklist
### Build
- [ ] `npm run build` succeeds
- [ ] No TypeScript errors
- [ ] No ESLint errors
### Environment Variables
- [ ] Production environment variables set
- [ ] Sensitive info not exposed to client
### Performance
- [ ] Images optimized with next/image
- [ ] Fonts optimized with next/font
- [ ] Large libraries dynamically imported
### SEO
- [ ] Metadata configured
- [ ] OGP images set
- [ ] sitemap.xml generated
- [ ] robots.txt configured
### Security
- [ ] Security headers configured
- [ ] Authentication working correctly
- [ ] API routes protected
### Monitoring
- [ ] Error monitoring configured
- [ ] Analytics configured
10-Day Review
flowchart TB
subgraph Week1["Week 1: Fundamentals"]
D1["Day 1<br/>Next.js Intro"]
D2["Day 2<br/>Routing"]
D3["Day 3<br/>Server/Client Components"]
D4["Day 4<br/>Data Fetching"]
D5["Day 5<br/>Server Actions"]
end
subgraph Week2["Week 2: Advanced"]
D6["Day 6<br/>Optimization"]
D7["Day 7<br/>Rendering Strategies"]
D8["Day 8<br/>Styling"]
D9["Day 9<br/>Authentication"]
D10["Day 10<br/>Deployment"]
end
D1 --> D2 --> D3 --> D4 --> D5
D5 --> D6 --> D7 --> D8 --> D9 --> D10
style Week1 fill:#3b82f6,color:#fff
style Week2 fill:#22c55e,color:#fff
What You Learned
| Day | Topic | Key Concepts |
|---|---|---|
| 1 | Next.js Intro | App Router, file-based routing |
| 2 | Routing | Dynamic routes, route groups, loading/error |
| 3 | Components | Server Components, Client Components |
| 4 | Data Fetching | fetch, caching, parallel fetching, Suspense |
| 5 | Server Actions | Form handling, mutations, revalidation |
| 6 | Optimization | next/image, next/font, metadata |
| 7 | Rendering | SSG, SSR, ISR, streaming |
| 8 | Styling | CSS Modules, Tailwind, dark mode |
| 9 | Authentication | Middleware, NextAuth.js |
| 10 | Deployment | Vercel, environment variables, monitoring |
Next Steps
Topics to Explore Further
-
Database Integration
- Prisma + PostgreSQL
- Drizzle ORM
- PlanetScale / Neon
-
Advanced Features
- Internationalization (i18n)
- Edge Functions
- Turbopack
-
Testing
- Jest + Testing Library
- Playwright (E2E)
-
Practice Projects
- Blog platform
- E-commerce site
- SaaS application
Recommended Resources
| Resource | URL |
|---|---|
| Next.js Documentation | https://nextjs.org/docs |
| Next.js Learn | https://nextjs.org/learn |
| Vercel Templates | https://vercel.com/templates |
| GitHub Examples | https://github.com/vercel/next.js/tree/canary/examples |
Summary
| Concept | Description |
|---|---|
| Vercel Deployment | Automated deployment with GitHub |
| Environment Variables | Separate prod/preview/dev |
| Performance | Analytics, bundle analysis |
| Security | Headers, environment variable protection |
| Error Monitoring | Sentry integration |
Final Points
- Vercel is optimal: Same developers as Next.js
- Separate environments: Production/staging/development
- Monitoring is essential: Errors and performance
- Continue learning: Follow official docs
Conclusion
Congratulations on completing the 10-day journey!
Over these 10 days, you've built practical skills from Next.js fundamentals to production deployment. Next.js is an actively developed framework. Keep following the official documentation to learn the latest features and best practices.
Happy coding!