Webpack 4 - pierwsze kroki z module bundlerem

Cześć 👋

Webpack to tzw. module bundler, pozwala nam na budowanie drzewa zależności, które ma na celu połączenie wielu modułów naszej aplikacji w jeden pakiet.

Dlaczego webpack?

Mamy dwie możliwości, żeby uruchomić naszą JavaScriptową aplikację w przeglądarce. Możemy dla każdej funkcjonalności dołączać <script> lub zawrzeć cały kod w jednym pliku .js. Takie rozwiązania, jak zapewnę się domyślasz, rodzą wiele problemów, czy to z czytelnością, rozmiarem, czy też utrzymaniem naszego kodu.

Zanim stworzono Webpacka, powstały rozwiązania, które częściowo rozwiązały powyższe problemy, niektóre z nich rodziły też nowe.

Dlatego powstał Webpack, pozwala on nie tylko bundlować pliki .js, ale również wspiera inne tzw. assety jak obrazki, fonty i arkusze stylów.

Jest to bardzo potężne narzędzie i w dobie nowoczesnych stron i aplikacji nie wyobrażam sobie pracy bez niego(lub jemu podobnych).

Założenia

Webpack opiera się o kilka konceptów:

  • Entry
  • Output
  • Loaders
  • Plugins
  • Mode

Bez zbędnego teoretyzowania, przejdźmy do praktyki, później przyjrzymy im się nieco bliżej.

Instalacja

Utwórzmy nowy projekt, zainicjujmy naszą aplikację.

npm init

Po wstępnej konfiguracji zainstalujmy niezbędne paczki:

npm install --save-dev webpack webpack-cli

Pierwszy moduł!

Na początek nie potrzebujemy żadnego pliku konfiguracyjnego, wystarczą nam tylko skrypty, a właściwie jeden:

"scripts": {
    "webpack": "webpack",
  },

Utwórzmy teraz katalog src/, a w nim plik index.js i hello.js.

// hello.js

const hello = "Hello world!";

export default hello;

// index.js
import hello from "./hello.js";

console.log(hello);

W pliku hello.js stworzyliśmy stałą hello i wyeksportowaliśmy ją, następnie w index.js importujemy tą stałą i po prostu ją wylogowujemy.

Jeśli nie wiesz czym są moduły w JavaScripcie, skorzystaj z tego materiału!

Odpalmy teraz nasz skrypt i zobaczmy co się stanie:

npm run webpack

Jeśli wszystko poszło zgodnie z planem powinieneś zobaczyć nowy folder w katalogu głównym - dist/, a w nim plik main.js. Tutaj zostały zbundlowane nasze pliki hello.js i index.js.

Za pomocą node odpalmy nasz skrypt:

node ./dist/main.js

W odpowiedzi dostajemy Hello world!, brawo właśnie napisałeś swój pierwszy moduł!

Dodawanie skryptów

Webpack daje nam jednak ostrzeżenie o braku odpowiedniego trybu, by default ustawiony jest mode production. Dodajmy odpowiednie skrypty:

"scripts": {
    "webpack": "webpack",
    "dev": "npm run webpack -- --mode development --watch",
    "prod": "npm run webpack -- --mode production"
  },

Dzięki fladze --watch Webpack będzie obserwował zmiany w naszych plikach.

Odpalmy nasz skrypt developerski:

npm run dev

Stwórzmy teraz plik multiply.js w src/, a w nim funkcję multiplyByTwo:

// multiply.js

const multiplyByTwo = (number) => {
  return number * 2;
};

export { multiplyByTwo };

Zaimportujmy ją teraz do index.js i wylogujmy z argumentem 2.

// index.js
import hello from "./hello.js";
import { multiplyByTwo } from "./multiply.js";

console.log(hello, multiplyByTwo(2));

Jeśli spojrzysz teraz do terminala, to zobaczysz drzewko zależności, o którym Ci wcześniej wspominałem.

Odpalmy teraz tryb produkcyjny:

npm run prod

Zbundlowaliśmy nasze pliki, zobaczmy czy wszystko poszło dobrze:

node ./dist/main.js

W odpowiedzi powinieneś dostać Hello world! 4.

Konfiguracja

Okej, teraz przyszła pora na bardziej skomplikowaną konfigurację, mamy kilka możliwości. Pierwsza, możliwe, że już Ci znana, to stworzenie pliku webpack.config.js, możemy również skorzystać z CLI, ale my skupimy się na tej pierwszej opcji.

touch webpack.config.js

Zanim stworzymy naszą webpackową konfigurację, omówmy sobie pokrótce czym są, wspomniane przeze mnie wcześniej, założenia, na których opiera się cała praca z Webpackiem.

Entry

Wyobraź sobie drzewko swoich plików, na samej górze takiego drzewka mamy nasz entry point, dokładnie tym był nasz index.js. Ten plik zasila naszą aplikację.

W pliku konfiguracyjnym plik wejściowy definiujemy w ten sposób:

module.exports = {
  entry: "./index.js",
};

Output

Webpack bierzę nasz plik z entry pointa i przemiela go na zbundlowaną wersję, taki przemielony kod musi gdzieś wypluć.

Takim miejscem jest właśnie output. W konfiguracji potrzebujemy podać ścieżkę i nazwę dla zbundlowanego pliku.

module.exports = {
  output: {
    path: "./dist",
    filename: "bundle.js",
  },
};

Loaders & rules

Kolejnym konceptem w Webpacku są tzw. loadery, dzięki nim Webpack wie jak i które pliki zmienić przed dodaniem ich do drzewa zależności.

Chcemy użyć Babela, TypeScripta, czy też bundlować pliki css? Nie ma problemu, dodajmy odpowiednie loadery do naszej konfiguracji:

module.exports = {
  rules: [
    { test: /\.js$/, use: "babel-loader" },
    { test: /\.ts$/, use: "ts-loader" },
    { test: /\.css$/, use: "css-loader" },
  ],
};

Gdy nasz plik będzie odpowiadał zadeklarowanym rozszerzenią, Webpack przetrasformuje go za pomocą danego loadera, zanim doda go do drzewa zależności.

Plugins

Webpack został zbudowany właśnie na pluginach! Pluginy to takie supermoce Webpacka, mają większe możliwości niż loadery, dzięki nim możemy wpływać na proces kompilacji.

Tak jak loadery, pluginy musimy najpierw zainstalować a potem dodać od naszego configu:

const MinifyPlugin = require("babel-minify-webpack-plugin");
module.exports = {
  plugins: [new MinifyPlugin(minifyOpts, pluginOpts)],
};

Każdy plugin ma swoje własne opcje, jednak każdy z nich podobnie jak klasy w js, plugin dodajemy tworząc jego nową instancję.

Podsumowanie

To tyle na dziś, przedstawiłem Ci podstawowe założenia Webpacka, w następnym wpisie stworzymy już pełnoprawną konfigurację z wykorzystaniem loaderów, pluginów i innych dóbr jakie daje nam to wspaniałe narzędzie.

Cały kod możecie znaleźć na githubie.

Do usłyszenia!

Źródła

GitHubGitHubGitHub