Bundlery JavaScript: webpack vs Vite – porównanie i podstawowa konfiguracja

Mateusz Bogolubow

Mateusz Bogolubow

24-10-2026

(aktualizacja: 24-10-2026)

Czym jest bundler, do czego służy i czym różnią się webpack oraz Vite? Porównanie, minimalne konfiguracje i wskazówka, który wybrać w nowym projekcie.

Bundlery JavaScript: webpack vs Vite – porównanie i podstawowa konfiguracja
Bundler to narzędzie, które łączy wiele plików projektu (moduły JS, style, obrazy) w kilka zoptymalizowanych plików gotowych dla przeglądarki. Webpack to dojrzały, bardzo konfigurowalny bundler, który wciąż działa w wielu starszych projektach, a Vite to nowsze narzędzie z dev serverem opartym na natywnych modułach ES, które w nowych projektach jest dziś domyślnym wyborem. Jeśli zaczynasz nowy projekt, wybierz Vite; webpacka poznasz głównie przy utrzymywaniu istniejącego kodu.

Kiedy projekt frontendowy rośnie z jednego pliku do kilkudziesięciu, ktoś musi je ze sobą połączyć, przetworzyć i przygotować do wdrożenia. Robi to bundler. W tym artykule porównam dwa narzędzia, na które trafisz najczęściej: webpack i Vite. Pokażę, do czego służą, jak wygląda ich minimalna konfiguracja i gdzie każde z nich spotkasz w praktyce.

Czym jest bundler JavaScript i po co go używać?

Bundler (czyli „pakowacz”) czyta Twój kod od punktu wejścia (zwykle index.js), śledzi wszystkie instrukcje import i buduje z nich graf zależności. Następnie zapisuje wynik do kilku plików w katalogu dist. Po drodze potrafi też:

  • zminimalizować kod (usunąć białe znaki, skrócić nazwy zmiennych), żeby ważył mniej,
  • usunąć nieużywany kod (tzw. tree shaking),
  • przetworzyć inne pliki: CSS, Sass, obrazy, czcionki, TypeScript, JSX,
  • dodać hash do nazwy pliku (main.46b9f0.js), dzięki czemu przeglądarka pobierze nową wersję dopiero po zmianie kodu,
  • podzielić kod na części (code splitting), by użytkownik pobierał tylko to, czego potrzebuje na danej podstronie,
  • uruchomić serwer deweloperski z automatycznym odświeżaniem strony po zapisaniu pliku.

Czy bundler jest zawsze potrzebny? Nie. Pojedyncza strona z jednym skryptem działa bez niego. Przestaje to wystarczać, gdy używasz paczek z npm, pisasz w TypeScripcie albo Reakcie, albo chcesz mieć zoptymalizowany build produkcyjny.

Jak działa webpack i do czego służy?

Webpack powstał w 2012 roku i przez lata był standardem. Jego idea: wszystko jest modułem. Plik JS, CSS czy obraz da się zaimportować, o ile masz do niego odpowiedni loader (zamienia plik na moduł) lub plugin (rozszerza sam proces budowania).

Webpack konfiguruje się w pliku webpack.config.js. Minimalna konfiguracja z obsługą CSS i generowaniem index.html wygląda tak:

import path from "node:path";
import HtmlWebpackPlugin from "html-webpack-plugin";
import MiniCssExtractPlugin from "mini-css-extract-plugin";

export default {
  entry: "./src/index.js",
  output: {
    path: path.resolve(import.meta.dirname, "dist"),
    filename: "[name].[contenthash].js",
    clean: true,
  },
  module: {
    rules: [
      { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ title: "App" }),
    new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" }),
  ],
};

Co tu się dzieje?

KluczZa co odpowiada
entryPunkt startowy, od którego webpack buduje graf zależności
outputGdzie i pod jaką nazwą zapisać wynik ([contenthash] = hash w nazwie, clean czyści stary build)
module.rulesLoadery: który typ pliku przetworzyć jakim narzędziem
pluginsRozszerzenia całego procesu, np. generowanie index.html albo wydzielenie CSS do osobnego pliku

Budowanie uruchamiasz poleceniem webpack --mode production. Użyty w tym przykładzie plik z import.meta.dirname wymaga "type": "module" w package.json (w starszych projektach zobaczysz zamiast tego require i __dirname).

Mocną stroną webpacka jest ogromny ekosystem i pełna kontrola nad każdym etapem. Słabszą: konfiguracja szybko puchnie, a dev server przy dużym projekcie startuje powoli, bo najpierw musi zbudować całą aplikację.

Jak działa Vite i czym różni się od webpacka?

Vite (po francusku „szybki”) działa inaczej w trybie deweloperskim i produkcyjnym:

  • W trybie deweloperskim nie buduje całej aplikacji z góry. Przeglądarka sama prosi o moduły ES (import), a Vite przetwarza tylko te pliki, o które poprosiła. Dzięki temu serwer startuje niemal natychmiast, niezależnie od wielkości projektu.
  • W trybie produkcyjnym (vite build) tworzy zoptymalizowany bundle. Od wersji 8 robi to za pomocą Rolldown, bundlera napisanego w Rust (sprawdziłem to w drzewie zależności Vite 8.3.5), wcześniej używał do tego Rollupa.

Największa różnica na co dzień: Vite działa bez pliku konfiguracyjnego. Wystarczy index.html z tagiem <script type="module">:

<!doctype html>
<html>
  <head><title>App</title></head>
  <body>
    <script type="module" src="/src/index.js"></script>
  </body>
</html>

W package.json dodajesz skrypty:

{
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

Trzy skrypty robią różne rzeczy. vite (npm run dev) uruchamia serwer deweloperski, który serwuje Twój kod źródłowy i odświeża stronę po zapisie pliku. vite build tworzy katalog dist z gotowym buildem. vite preview nie buduje niczego, tylko serwuje to, co już leży w dist, żeby sprawdzić wersję produkcyjną lokalnie. Dlatego vite preview zadziała dopiero po vite build.

CSS importujesz zwykłym import "./style.css" i nie potrzebujesz żadnego loadera. Ten sam projekt, który w webpacku wymagał trzech paczek pomocniczych i kilkunastu linii konfiguracji, w Vite zbudował się samym vite build (w moich testach po stronie Vite zostały: index.html, plik JS i plik CSS z hashami w nazwach).

Plik vite.config.js pojawia się dopiero wtedy, gdy czegoś potrzebujesz, np. wtyczki dla Reacta albo proxy do API:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
    proxy: { "/api": "http://localhost:8000" },
  },
});

Webpack czy Vite: jakie są najważniejsze różnice?

CechawebpackVite
KonfiguracjaWymagana, rozbudowana (webpack.config.js)Opcjonalna, sensowne ustawienia domyślne
Start serwera deweloperskiegoNajpierw buduje cały bundleSerwuje moduły ES na żądanie
Build produkcyjnyWłasny silnik webpackaRolldown (od Vite 8), wcześniej Rollup
CSS, obrazy, TypeScriptPrzez loadery i pluginyObsługa w standardzie (TS i JSX transpilowane bez dodatków)
Dojrzałość i ekosystemBardzo duży, obecny od 2012 r.Mniejszy, ale szybko rosnący
ElastycznośćPełna kontrola nad każdym etapemMniej opcji „pod maską”, więcej gotowych rozwiązań
Typowe zastosowanieStarsze i bardzo rozbudowane projektyNowe aplikacje frontendowe
WymaganiaNode ≥ 10.13 (webpack 5)Node ≥ 20.19 lub ≥ 22.12 (Vite 8)

Gdzie najczęściej używa się webpacka, a gdzie Vite?

Webpack spotkasz głównie:

  • w starszych projektach: stare aplikacje Reacta, Angulara, Vue, które powstały przed erą Vite,
  • w projektach stworzonych przez Create React App: CRA ukrywał konfigurację webpacka, a to na tyle częste pytanie, że „gdzie jest konfiguracja webpacka w CRA?” ma na Stack Overflow ponad 400 tysięcy wyświetleń,
  • w dużych aplikacjach firmowych z rozbudowanym buildem (np. Module Federation, czyli współdzielenie kodu między aplikacjami),
  • jako silnik pod spodem: część frameworków i narzędzi używa go wewnętrznie, więc możesz z niego korzystać, nie pisząc ani jednej linii konfiguracji.

Vite wybierzesz:

  • w nowych aplikacjach w Reakcie, Vue, Svelte czy czystym JS i TypeScript (npm create vite@latest generuje gotowy szablon),
  • do szybkich prototypów i projektów edukacyjnych, bo nie wymaga żmudnej konfiguracji,
  • do bibliotek (tryb library w buildzie) i narzędzi, na których zbudowane są inne projekty (np. Vitest do testów).

Zauważ, że frameworki typu Next.js dostarczają własny system budowania, więc przy nich zwykle w ogóle nie wybierasz bundlera. Do wersji 15 Next.js korzystał domyślnie z webpacka, a od wersji 16 domyślnie używa Turbopacka (opisanego niżej). Webpack nadal działa w tych projektach pod flagą --webpack, więc jeśli trafisz na starszy projekt Next.js z własną sekcją webpack w next.config.js, to właśnie na to patrzysz. Uwaga: w Next.js 16 next build z taką konfiguracją kończy się błędem, dopóki nie dodasz --webpack albo nie przeniesiesz ustawień do Turbopacka.

Jak w obu narzędziach używać zmiennych środowiskowych?

To częsta pułapka. W Vite zmienne z pliku .env trafiają do kodu przeglądarki tylko wtedy, gdy ich nazwa zaczyna się od VITE_:

VITE_API_URL=https://api.example.com
SECRET_KEY=tajne123
console.log(import.meta.env.VITE_API_URL); // "https://api.example.com"
console.log(import.meta.env.SECRET_KEY);   // undefined

Sprawdziłem to w buildzie: wartość VITE_API_URL została wstawiona do pliku wynikowego, a SECRET_KEY w ogóle się w nim nie znalazł. To zabezpieczenie, a nie błąd. Wszystko, co trafia do bundla, zobaczy każdy użytkownik strony, więc klucza prywatnego nie wolno umieszczać w zmiennych VITE_* (ani w odpowiednikach w webpacku).

W webpacku nic takiego nie dzieje się automatycznie. Wartości trzeba wstrzyknąć ręcznie przez DefinePlugin lub EnvironmentPlugin, a plik .env wczytać paczką dotenv.

Jakie błędy najczęściej pojawiają się przy webpacku i Vite?

ObjawPrzyczynaCo zrobić
ERR_OSSL_EVP_UNSUPPORTED przy buildzie webpackaStary webpack 4 + Node 17 lub nowszy (zmiana algorytmu haszowania w OpenSSL)Zaktualizuj do webpacka 5 (najlepsze rozwiązanie), a tymczasowo użyj starszego Node
Module not found: Can't resolve 'path' lub 'buffer' w webpacku 5Webpack 5 nie dodaje już automatycznie polifilli modułów NodeNie używaj modułów Node w kodzie przeglądarkowym, albo dodaj resolve.fallback z odpowiednią paczką
Invalid Host header w webpack-dev-serverDev server odrzuca żądania z innej nazwy hosta niż localhostUstaw opcję allowedHosts w devServer
import.meta.env.MOJA_ZMIENNA jest undefined w ViteBrak prefiksu VITE_Zmień nazwę na VITE_MOJA_ZMIENNA i zrestartuj serwer
Vite nie startuje, błąd o wersji NodeVite 8 wymaga Node 20.19+ lub 22.12+Zaktualizuj Node
vite: command not found (w Windows: 'vite' is not recognized) przy npm run dev lub npm run buildBrak zainstalowanych zależności: nie ma katalogu node_modules, więc skrypt nie ma czego uruchomićWykonaj npm install w katalogu projektu i upewnij się, że vite jest w devDependencies
Rolldown failed to resolve import "@/greet.js"Alias @ nie istnieje domyślnie, trzeba go zdefiniowaćDodaj resolve.alias w vite.config.js (przykład niżej)
Po deployu na GitHub Pages strona jest pustaPliki są szukane pod złą ścieżką (/assets/... zamiast /repo/assets/...)W Vite ustaw base: "/nazwa-repo/", w webpacku output.publicPath

Alias @ wskazujący na katalog src ustawisz tak:

import { defineConfig } from "vite";
import path from "node:path";

export default defineConfig({
  resolve: {
    alias: { "@": path.resolve(import.meta.dirname, "src") },
  },
});

Po tej zmianie import { greet } from "@/greet.js" działa w builcie. Bez niej budowanie kończy się błędem, który sprawdziłem w Vite 8.3.5.

Ostatni wiersz tabeli (pusta strona po deployu) dotyczy Ciebie, jeśli publikujesz projekt na GitHub Pages, a szczegóły wdrożenia opisuję w poradniku o podglądzie projektu na GitHubie.

Czy na rozmowie rekrutacyjnej pytają o webpacka i Vite?

Na rozmowach rzadko pada pytanie o składnię webpack.config.js. Częściej chodzi o to, co bundler robi i czym różni się build od trybu deweloperskiego. Jeśli potrafisz to wyjaśnić na własnym projekcie, jesteś do przodu.

Co wybrać na start nauki: webpack czy Vite?

Jeśli uczysz się teraz frontendu i zaczynasz własny projekt: zacznij od Vite. Nie spędzisz pierwszego wieczoru na konfiguracji, szybciej zobaczysz efekt i bez problemu przejdziesz do Reacta czy TypeScripta. Dobrze zrozum jednak sam mechanizm: co to moduł, jak działa import, czym jest build i czym różni się od trybu deweloperskiego. Te pojęcia są identyczne w obu narzędziach, a jeśli kiedyś trafisz do firmy z projektem na webpacku, dużo łatwiej odnajdziesz się w jego konfiguracji.

Zanim sięgniesz po bundler, upewnij się, że znasz moduły ES i podstawy npm. Tego uczymy w ramach kursu JavaScript, a bardziej zaawansowane tematy budowania aplikacji znajdziesz w kursie Zaawansowany JS.

Czy istnieją inne bundlery oprócz webpacka i Vite?

Tak. Najczęściej wymieniane to:

  • Rollup: bundler nastawiony na biblioteki, wykorzystywany przez wiele narzędzi (w Vite do wersji 7),
  • esbuild: bardzo szybki bundler napisany w Go, używany często jako element innych narzędzi,
  • Parcel: bundler „zero config”, który sam wykrywa potrzebne przetwarzanie,
  • Rspack: bundler w Rust z konfiguracją zbliżoną do webpacka, więc ułatwia migrację istniejących projektów,
  • Turbopack: bundler w Rust zintegrowany z Next.js. Od Next.js 16 jest domyślnym bundlerem zarówno w next dev, jak i w next build, a webpacka włączysz tylko flagą --webpack. Starsze wersje Next.js domyślnie używały webpacka. Turbopacka nie wybierasz więc osobno jak Vite, bo jest częścią frameworka.

Nie testowałem ich w tym artykule, więc traktuj ten wykaz jako mapę, a nie rekomendację. W praktyce, zanim zaczniesz porównywać kolejne narzędzia, przećwicz podstawy na jednym z dwóch omówionych tu.

Konsultacja i warsztaty devmentor.pl

Masz pytania?

Partnerzy

Firmy, z którymi współpracujemy

To partnerzy odpowiedzialni za staże po naszych kursach. Organizują je dla najlepszych absolwentów.

Zobacz wszystkich partnerów →
  • VR Medical
  • Sophona
  • Robot Force