Witaj w finalnym projekcie modulu wdrazania! W Metropolii Quantum 2150 kazdy system przechodzi przez rygorystyczny proces przygotowania do produkcji - od budowania i optymalizacji, przez konfiguracje SEO, az po monitoring i testowanie. W tym projekcie polaczymy wszystkie umiejetnosci zdobyte w calym module, aby przejsc przez pelny cykl wdrazania aplikacji Next.js.
Twoim zadaniem jest przygotowanie kompletnej aplikacji Next.js do wdrozenia produkcyjnego. Projekt obejmuje wszystkie kluczowe aspekty, ktore omowilismy w tym module:
Rozpocznij od pelnej konfiguracji Next.js z optymalizacjami produkcyjnymi:
1// next.config.ts
2import type { NextConfig } from 'next';
3import withBundleAnalyzer from '@next/bundle-analyzer';
4
5const config: NextConfig = {
6 // Optymalizacja obrazow
7 images: {
8 formats: ['image/avif', 'image/webp'],
9 remotePatterns: [
10 {
11 protocol: 'https',
12 hostname: 'cdn.quantum-city.com',
13 pathname: '/images/**',
14 },
15 ],
16 minimumCacheTTL: 60 * 60 * 24 * 30, // 30 dni cache
17 },
18
19 // Kompresja
20 compress: true,
21
22 // Optymalizacja bundla
23 experimental: {
24 optimizePackageImports: ['lucide-react', '@quantum/ui'],
25 },
26
27 // Naglowki bezpieczenstwa
28 async headers() {
29 return [
30 {
31 source: '/:path*',
32 headers: [
33 { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
34 { key: 'X-Content-Type-Options', value: 'nosniff' },
35 { key: 'X-XSS-Protection', value: '1; mode=block' },
36 { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
37 {
38 key: 'Strict-Transport-Security',
39 value: 'max-age=63072000; includeSubDomains; preload',
40 },
41 {
42 key: 'Permissions-Policy',
43 value: 'camera=(), microphone=(), geolocation=()',
44 },
45 ],
46 },
47 ];
48 },
49
50 // Przekierowania
51 async redirects() {
52 return [
53 {
54 source: '/old-page',
55 destination: '/new-page',
56 permanent: true, // 301 redirect
57 },
58 ];
59 },
60};
61
62const withAnalyzer = withBundleAnalyzer({
63 enabled: process.env.ANALYZE === 'true',
64});
65
66export default withAnalyzer(config);Skonfiguruj metadane dla kazdej strony z wykorzystaniem Metadata API:
1// app/layout.tsx
2import type { Metadata } from 'next';
3
4export const metadata: Metadata = {
5 metadataBase: new URL('https://quantum-city.com'),
6 title: {
7 default: 'Quantum City - Portal Metropolii',
8 template: '%s | Quantum City',
9 },
10 description: 'Oficjalny portal Metropolii Quantum 2150',
11 openGraph: {
12 type: 'website',
13 locale: 'pl_PL',
14 url: 'https://quantum-city.com',
15 siteName: 'Quantum City',
16 images: [
17 {
18 url: '/og-default.png',
19 width: 1200,
20 height: 630,
21 alt: 'Quantum City',
22 },
23 ],
24 },
25 twitter: {
26 card: 'summary_large_image',
27 creator: '@QuantumCity',
28 },
29 robots: {
30 index: true,
31 follow: true,
32 googleBot: {
33 index: true,
34 follow: true,
35 'max-video-preview': -1,
36 'max-image-preview': 'large',
37 'max-snippet': -1,
38 },
39 },
40};
41
42// app/products/[id]/page.tsx - dynamiczne metadane
43import type { Metadata } from 'next';
44
45type Props = { params: Promise<{ id: string }> };
46
47export async function generateMetadata({ params }: Props): Promise<Metadata> {
48 const product = await fetch(
49 `https://api.quantum-city.com/products/${(await params).id}`
50 ).then(r => r.json());
51
52 return {
53 title: product.name,
54 description: product.description,
55 openGraph: {
56 title: product.name,
57 description: product.description,
58 images: [{ url: product.imageUrl, width: 800, height: 600 }],
59 },
60 };
61}Wygeneruj dynamiczna mape witryny:
1// app/sitemap.ts
2import { MetadataRoute } from 'next';
3
4export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
5 const baseUrl = 'https://quantum-city.com';
6
7 // Pobierz dynamiczne strony
8 const products = await fetch('https://api.quantum-city.com/products')
9 .then(r => r.json());
10
11 const posts = await fetch('https://api.quantum-city.com/blog')
12 .then(r => r.json());
13
14 const productPages = products.map((product: any) => ({
15 url: `${baseUrl}/products/${product.slug}`,
16 lastModified: new Date(product.updatedAt),
17 changeFrequency: 'weekly' as const,
18 priority: 0.8,
19 }));
20
21 const blogPages = posts.map((post: any) => ({
22 url: `${baseUrl}/blog/${post.slug}`,
23 lastModified: new Date(post.updatedAt),
24 changeFrequency: 'monthly' as const,
25 priority: 0.6,
26 }));
27
28 return [
29 { url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1 },
30 { url: `${baseUrl}/products`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.9 },
31 ...productPages,
32 ...blogPages,
33 ];
34}
35
36// app/robots.ts
37import { MetadataRoute } from 'next';
38
39export default function robots(): MetadataRoute.Robots {
40 return {
41 rules: [
42 {
43 userAgent: '*',
44 allow: '/',
45 disallow: ['/admin/', '/api/', '/dashboard/'],
46 },
47 ],
48 sitemap: 'https://quantum-city.com/sitemap.xml',
49 };
50}Zintegruj system analityki i monitoringu bledow:
1// lib/analytics.ts
2export function trackEvent(name: string, properties?: Record<string, any>) {
3 if (typeof window === 'undefined') return;
4
5 // Wlasna analityka
6 fetch('/api/analytics', {
7 method: 'POST',
8 headers: { 'Content-Type': 'application/json' },
9 body: JSON.stringify({ event: name, properties, timestamp: Date.now() }),
10 }).catch(console.error);
11}
12
13// lib/monitoring.ts
14export function initErrorMonitoring() {
15 if (typeof window === 'undefined') return;
16
17 window.addEventListener('error', (event) => {
18 fetch('/api/errors', {
19 method: 'POST',
20 headers: { 'Content-Type': 'application/json' },
21 body: JSON.stringify({
22 message: event.message,
23 filename: event.filename,
24 lineno: event.lineno,
25 stack: event.error?.stack,
26 url: window.location.href,
27 timestamp: new Date().toISOString(),
28 }),
29 }).catch(console.error);
30 });
31}Skonfiguruj automatyczny pipeline wdrazania:
1# .github/workflows/deploy.yml
2name: Deploy to Production
3
4on:
5 push:
6 branches: [main]
7
8jobs:
9 test:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v4
13 - uses: actions/setup-node@v4
14 with:
15 node-version: '20'
16 cache: 'npm'
17 - run: npm ci
18 - run: npm run lint
19 - run: npm run type-check
20 - run: npm test
21
22 e2e:
23 needs: test
24 runs-on: ubuntu-latest
25 steps:
26 - uses: actions/checkout@v4
27 - uses: actions/setup-node@v4
28 with:
29 node-version: '20'
30 - run: npm ci
31 - run: npm run build
32 - name: Cypress E2E Tests
33 uses: cypress-io/github-action@v6
34 with:
35 start: npm start
36 wait-on: 'http://localhost:3000'
37 browser: chrome
38
39 deploy:
40 needs: [test, e2e]
41 runs-on: ubuntu-latest
42 steps:
43 - uses: actions/checkout@v4
44 - name: Deploy to Vercel
45 run: npx vercel --prod --token=VERCEL_TOKENDodaj funkcjonalnosc Progressive Web App:
1// app/manifest.ts
2import { MetadataRoute } from 'next';
3
4export default function manifest(): MetadataRoute.Manifest {
5 return {
6 name: 'Quantum City Portal',
7 short_name: 'QC Portal',
8 description: 'Oficjalny portal Metropolii Quantum 2150',
9 start_url: '/',
10 display: 'standalone',
11 background_color: '#0a0a1a',
12 theme_color: '#64ffda',
13 icons: [
14 { src: '/icon-192.png', sizes: '192x192', type: 'image/png' },
15 { src: '/icon-512.png', sizes: '512x512', type: 'image/png' },
16 ],
17 };
18}Napisz testy pokrywajace krytyczne sciezki uzytkownika:
1// cypress/e2e/production-readiness.cy.ts
2describe('Production Readiness Check', () => {
3 it('strona glowna laduje sie ponizej 3 sekund', () => {
4 cy.visit('/', { timeout: 3000 });
5 cy.get('h1').should('be.visible');
6 });
7
8 it('SEO meta tagi sa poprawne', () => {
9 cy.visit('/');
10 cy.get('head title').should('contain', 'Quantum City');
11 cy.get('meta[name="description"]').should('have.attr', 'content');
12 });
13
14 it('naglowki bezpieczenstwa sa ustawione', () => {
15 cy.request('/').then((response) => {
16 expect(response.headers).to.have.property('x-frame-options');
17 expect(response.headers).to.have.property('x-content-type-options');
18 });
19 });
20});Przed kazdym wdrozeniem produkcyjnym przejdz przez te punkty kontrolne:
next build konczy sie bez bledowW tym projekcie polaczyles wszystkie kluczowe umiejetnosci wdrazania aplikacji Next.js do produkcji. Kazdy z tych elementow jest niezbedny do stworzenia profesjonalnej, wydajnej i bezpiecznej aplikacji webowej.
Pamietaj - w Metropolii Quantum 2150 nie ma miejsca na polsrodki. Kazdy system musi byc w pelni zoptymalizowany, zabezpieczony i monitorowany. Teraz jestes gotowy, aby wdrozyc swoje aplikacje Next.js na najwyzszym poziomie!