Alternatywa dla Next.js (SSR)? Spróbuj NestJS + Nunjucks + Tailwind CSS

Next.js alternative

Next.js to popularny framework oparty na React, który pozwala na budowanie aplikacji z renderowaniem po stronie serwera (SSR) oraz statycznym generowaniem stron (SSG). Kod aplikacji pisany jest w TypeScript. Next.js zyskał popularność dzięki łatwości tworzenia aplikacji korzystających z serwerowego renderowania, a także wsparciu dla Static Site Generation (SSG), co pozwala na budowanie statycznych wersji stron, które można szybko serwować użytkownikom. Jednak dla niektórych projektów warto rozważyć alternatywę dla Next.js.

Ostatnio stworzyłem przy jego pomocy listę programistycznych blogów i muszę przyznać, że jest to świetne rozwiązanie, szczególnie jeśli chodzi o deployment aplikacji na platformie vercel.com. Proces wdrażania był szybki i intuicyjny, co sprawia, że Next.js jest bardzo atrakcyjny dla tego typu projektów. Dodatkowo, stworzenie tej strony było testem Next.js, czy jest to optymalne rozwiązanie do mojego kolejnego projektu, który ma być dostępny w większości języków świata.

Jednakże, choć Next.js jest potężnym narzędziem, nie zawsze jest optymalnym rozwiązaniem dla wszystkich projektów. Dla przykładu, framework automatycznie dodaje do kodu HTML dodatkowe dane, takie jak pliki JSON, które zawierają informacje potrzebne do późniejszego ponownego odtworzenia stanu aplikacji w przeglądarce. Ten proces, choć użyteczny w niektórych przypadkach, może prowadzić do przesyłania większej ilości informacji, niż jest to konieczne.

Na przykład, gdy tworzysz wielojęzyczną stronę, w Next.js często wszystkie tłumaczenia (dla wielu języków) są przesyłane do przeglądarki, nawet jeśli użytkownik widzi tylko jedną wersję językową strony. Next.js umieszcza te dane w źródle strony w formie plików JSON, które mają na celu umożliwienie natychmiastowego przełączania języków lub rekonstruowania stanu aplikacji po stronie klienta. Problem pojawia się, gdy strona obsługuje wiele języków — wszystkie tłumaczenia mogą być przesyłane do przeglądarki, nawet jeśli użytkownik widzi tylko jedną wersję językową, np. angielską.

Przykładowo, załóżmy, że Twoja strona obsługuje 10 języków. W takim przypadku Next.js może wygenerować pliki JSON, które będą zawierać wszystkie wersje tłumaczeń, nawet te, które w danym momencie nie są wyświetlane. To powoduje, że przesyłane są nadmiarowe dane, które zwiększają rozmiar strony, a tym samym wydłużają czas ładowania. Użytkownik odwiedzający stronę w języku angielskim nie potrzebuje danych tłumaczeń dla języka francuskiego, niemieckiego czy japońskiego, ale mimo to są one przesyłane. To właśnie dlatego warto rozważyć jakąś alternatywę Next.js, aby uniknąć takich nieefektywności i dostarczać tylko niezbędne dane.

Może to znacząco wpłynąć na wydajność strony, zwłaszcza w przypadku użytkowników z wolniejszym połączeniem internetowym lub korzystających z urządzeń mobilnych. Większa ilość danych do pobrania oznacza dłuższy czas ładowania strony, co negatywnie wpływa na doświadczenie użytkownika (UX) oraz pozycję strony w wynikach wyszukiwania (SEO).

Dlatego, jeśli zależy Ci na pełnej kontroli nad tym, jakie dane są przesyłane i jak strona jest generowana, warto rozważyć alternatywne rozwiązania dla Next.js, takie jak NestJS w połączeniu z Nunjucks lub z innym silnikiem szablonów. W tym podejściu renderowanie odbywa się w pełni po stronie serwera, a do przeglądarki przesyłane są jedynie te dane, które są niezbędne dla aktualnie wyświetlanej wersji strony. Dzięki temu możesz uniknąć problemu nadmiarowych danych, a każda wersja językowa strony będzie optymalnie załadowana i szybka.

Jednym z takich podejść jest kombinacja NestJS z Nunjucks i Tailwind CSS, które oferują większą elastyczność i kontrolę nad procesem generowania stron. W tym artykule omówimy, dlaczego warto rozważyć te technologie przy tworzeniu globalnych, wielojęzycznych projektów, które mogą potencjalnie generować duży ruch. Dzięki połączeniu Nunjucks i Tailwind CSS, możliwe jest budowanie szybkich, elastycznych i skalowalnych aplikacji, które przypominają klasyczne rozwiązania serwerowe, jak te znane z PHP, ale z nowoczesnymi narzędziami i większą kontrolą nad wydajnością.

Dlaczego NestJS + Nunjucks przypomina PHP?

Jeśli korzystałeś kiedyś z PHP do budowy stron internetowych, z pewnością pamiętasz, jak działa proces renderowania stron. Skrypty PHP generują dynamicznie HTML na serwerze i przesyłają go do przeglądarki użytkownika. Podobnie działa NestJS z Nunjucks – umożliwia to renderowanie stron HTML na serwerze na podstawie danych, co pozwala na większą elastyczność i kontrolę nad tym, co i kiedy zostaje wygenerowane.

NestJS to nowoczesny framework Node.js, zaprojektowany z myślą o skalowalnych i wydajnych aplikacjach serwerowych. Jest oparty na architekturze modularnej, co ułatwia zarządzanie złożonymi projektami, podobnie jak w przypadku frameworków backendowych, takich jak Spring w Javie czy ASP.NET w ekosystemie Microsoft. NestJS korzysta z TypeScript i oferuje wbudowane wsparcie dla serwerowego renderowania stron, dzięki czemu jest doskonałym wyborem do budowy aplikacji opartych na API, aplikacji webowych czy systemów backendowych.

W kontekście renderowania stron HTML, NestJS współpracuje z różnymi silnikami szablonów, z których jednym z najpotężniejszych i najbardziej elastycznych jest Nunjucks. Nunjucks to wszechstronny silnik szablonów inspirowany Jinja2 z Pythona, który oferuje zaawansowane funkcje, takie jak dziedziczenie szablonów, makra, pętle, warunki, oraz dynamiczne wstawianie danych. Dzięki Nunjucks, możesz w łatwy sposób zarządzać złożonymi strukturami HTML, renderować dynamiczne treści i kontrolować logikę wyświetlania elementów na stronie. Jest to idealne rozwiązanie do budowania globalnych aplikacji, które muszą obsługiwać wiele komponentów i dynamiczne treści w różnych językach.

Jeśli NestJS z Nunjucks wydaje się być dla Ciebie odpowiednim rozwiązaniem, warto także wiedzieć, że istnieje wiele innych silników szablonów. Silniki takie jak Pug, Handlebars, Mustache, czy EJS oferują różne funkcje i podejścia do renderowania stron po stronie serwera. Wybór odpowiedniego silnika zależy od złożoności projektu, potrzeb w zakresie struktury szablonów oraz preferencji dotyczących składni.

Główne korzyści NestJS + Nunjucks + Tailwind CSS nad Next.js (SSR)

1. Większa kontrola nad procesem renderowania

Next.js automatyzuje wiele aspektów renderowania po stronie serwera, co dla niektórych projektów może być ograniczeniem. Dzięki NestJS i Nunjucks masz pełną kontrolę nad każdym krokiem procesu renderowania – od dostępu do bazy danych po generowanie finalnego HTML-a. W ten sposób możesz optymalizować strony dokładnie według swoich potrzeb.

2. Mniejsza ilość nadmiarowych danych

W Next.js (SSR i SSG), podczas generowania stron, oprócz statycznego kodu HTML, do źródła strony dodawane są również dane w formie plików JSON. Są one potrzebne do ponownego odtworzenia stanu aplikacji po stronie klienta, co jest charakterystyczne dla aplikacji React. Jednak to podejście może prowadzić do przesyłania większej ilości danych niż jest to konieczne, co spowalnia stronę. Większa ilość przesyłanych danych oznacza nie tylko dłuższy czas ładowania, ale także wyższe koszty, jeśli korzystasz z usług chmurowych, takich jak Azure, AWS czy Google Cloud. W zależności od wybranych rozwiązań, za transfer danych często trzeba płacić dodatkowo, zwłaszcza przy dużej liczbie użytkowników i dużym ruchu na stronie.

Dzięki Nunjucks w NestJS, generujesz tylko to, co jest rzeczywiście potrzebne w danej chwili, co minimalizuje ilość przesyłanych danych. W ten sposób nie tylko poprawiasz wydajność strony, ale również ograniczasz koszty związane z transferem danych, co w dłuższej perspektywie może przynieść znaczące oszczędności, zwłaszcza w przypadku dużych aplikacji lub stron o wysokim ruchu.

Po przedstawieniu korzyści płynących z połączenia NestJS z Nunjucks oraz Tailwind CSS, warto teraz przejść do praktycznej części. Poniżej znajdziesz kompletny przewodnik krok po kroku, który poprowadzi Cię przez konfigurację środowiska, instalację wymaganych pakietów oraz przygotowanie struktury projektu.

Krok 1: Instalacja Nest.js

Zainstaluj Nest.js CLI globalnie, jeśli jeszcze tego nie zrobiłeś:

npm i -g @nestjs/cli

Utwórz nowy projekt Nest.js:

nest new name-of-your-project

Krok 2: Konfiguracja Nunjucks

Zainstaluj silnik szablonów Nunjucks:

npm install nunjucks

Skonfiguruj Nunjucks jako silnik widoków w pliku main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  // Ustawienie katalogu widoków i silnika Nunjucks
  nunjucks.configure('views', {
    autoescape: true,
    express: app,
    watch: true,
  });
  app.setViewEngine('njk');
  // Serwowanie plików statycznych z katalogu 'public'
  app.useStaticAssets(join(__dirname, '..', 'public'));
  await app.listen(3000);
}
bootstrap();

Krok 3: Konfiguracja Tailwind CSS

Zainstaluj Tailwind CSS oraz wymagane zależności:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init

Skonfiguruj plik tailwind.config.js:

module.exports = {
  content: [
    './views/**/*.njk',
    './public/**/*.js',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Utwórz plik CSS dla Tailwind w folderze public, np. public/styles.css, i dodaj do niego dyrektywy Tailwind:

@tailwind base;
@tailwind components;
@tailwind utilities;

Skonfiguruj PostCSS poprzez stworzenie pliku postcss.config.js:

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

Utwórz folder views. W plikach Nunjucks, dodaj link do wygenerowanego pliku CSS (np. w views/index.njk):

<link href="/styles.css" rel="stylesheet">

Przetwórz Tailwind, aby wygenerować finalny plik CSS:

npx tailwindcss -o public/styles.css

Krok 4: Stwórz kontroler, który będzie renderował stronę główną

W pliku kontrolera (np. app.controller.ts) stwórz metodę, która zwróci widok Nunjucks. Oto przykładowy kod kontrolera:

import { Controller, Get, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index') // Odwołuje się do pliku 'index.njk' w folderze 'views'"
  getHome() {
    return { title: 'Strona główna' }; // Możesz przekazać dane do widoku Nunjucks
  }
}

W pliku index.njk możesz dodać prosty kod HTML, aby wyświetlić stronę główną:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="/css/styles.css" rel="stylesheet">
  <title>{{ title }}</title>
</head>
<body>
  <h1>Witamy na stronie!</h1>
</body>
</html>

Uruchom aplikację i wejdź na stronę główną (http://localhost:3000/). Powinieneś zobaczyć stronę z zawartością pliku index.njk.

Podsumowując:

  • Widoki Nunjucks są umieszczane w folderze views.
  • Strona główna to plik index.njk, a kontroler odpowiada za renderowanie tej strony.

Alternatywa Next.js: Podsumowanie

Jeśli chcesz, możesz rozbudować ten szablon o dodatkowe sekcje i komponenty, a także w pełni wykorzystać możliwości Tailwind CSS do stylizacji. Uważam, że połączenie NestJS, Nunjucks i Tailwind CSS to doskonała alternatywa dla Next.js, szczególnie w przypadku projektów wymagających pełnej kontroli nad procesem renderowania i minimalizacji przesyłanych danych.

W kolejnym wpisie (lub aktualizując ten), pokażę, jak rozbudować tę aplikację, dodając integrację z MongoDB. Dzięki temu będziemy mogli zarządzać danymi w bazie danych, a aplikacja stanie się w pełni dynamiczna i gotowa na obsługę większych projektów. Pokażę również, jak łatwo zintegrować MongoDB z NestJS, wykorzystując moduł @nestjs/mongoose, oraz jak stworzyć operacje CRUD (Create, Read, Update, Delete) dla bardziej zaawansowanych aplikacji.

Śledź kolejne wpisy, aby dowiedzieć się więcej!