Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Projekt: Pelne wdrozenie aplikacji Next.js do produkcji

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.

Cel projektu

Twoim zadaniem jest przygotowanie kompletnej aplikacji Next.js do wdrozenia produkcyjnego. Projekt obejmuje wszystkie kluczowe aspekty, ktore omowilismy w tym module:

  1. Budowanie i optymalizacja (z lekcji o build i analyze)
  2. SEO i metadane (z lekcji o metadanych dynamicznych)
  3. Open Graph i social sharing (z lekcji o OG)
  4. Sitemap i robots.txt (z lekcji o mapach witryn)
  5. Web Analytics (z lekcji o analityce)
  6. Wdrazanie na platformy hostingowe (z lekcji o Vercel/Netlify)
  7. Zmienne środowiskowe i konfiguracja produkcyjna (z lekcji o env vars)
  8. CI/CD (z lekcji o automatyzacji)
  9. Monitoring (z lekcji o monitoringu)
  10. PWA i Service Workers (z lekcji o PWA)
  11. Preview Deployments i staging (z lekcji o środowiskach)

Krok 1: Konfiguracja next.config.js

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);

Krok 2: SEO i dynamiczne metadane

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}

Krok 3: Sitemap i robots.txt

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}

Krok 4: Web Analytics i monitoring

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}

Krok 5: CI/CD Pipeline

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_TOKEN

Krok 6: PWA i offline support

Dodaj 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}

Krok 7: Testy E2E z Cypress

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});

Krok 8: Checklist przed wdrozeniem

Przed kazdym wdrozeniem produkcyjnym przejdz przez te punkty kontrolne:

Wydajnosc

  • Komenda
    next build
    konczy sie bez bledow
  • Rozmiar bundla JS ponizej 200KB (gzipped)
  • LCP ponizej 2.5 sekundy, CLS ponizej 0.1
  • Obrazy zoptymalizowane (WebP/AVIF)

SEO

  • Kazda strona ma unikalne title i description
  • Open Graph tagi sa poprawne
  • Sitemap.xml i robots.txt sa wygenerowane

Bezpieczenstwo

  • Naglowki bezpieczenstwa (HSTS, CSP, X-Frame-Options)
  • CSRF protection i rate limiting
  • Walidacja inputu z Zod

Monitoring

  • Error tracking skonfigurowany
  • Web Vitals monitorowane
  • Alerty na krytyczne bledy

CI/CD

  • Testy jednostkowe i E2E przechodza
  • Linting i type-checking bez bledow
  • Automatyczny deploy po merge do main

Podsumowanie

W 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!

Przejdź do CodeWorlds