Webpack - szybki start -okładka

Webpack — szybki start i pierwsza konfiguracja

Opublikowano Kategorie Frontend, JavaScriptCzas czytania 7min

Czym jest Webpack?

Webpack jest to module bundler dla naszych aplikacji JavaScript. Inaczej mówiąc, Webpack pozwala nam wykonywać operacje na plikach.

Spektrum możliwości Webpacka tak naprawdę zależy tylko od naszych zachcianek i dostępnych pluginów oraz loaderów. Przykładowymi zadaniami, do których można wykorzystać Webpacka są: minifikacja plików (usuwanie zbędnych białych znaków), kompilacja plików .scss na .css, kompilowanie plików .vue do pliku .js, czy też połączenie wielu plików w jeden.

Wpis ten dotyczy Webpacka w wersji 4, więc jeśli korzystasz z wersji wcześniejszej, bądź późniejszej weź pod uwagę to, że artykuł może być nieaktualny.

Jak zacząć korzystać z Webpacka?

Na początku należy stworzyć nowy projekt. Gdy już mamy nowy projekt należy zainstalować niezbędne paczki: npm install webpack webpack-cli --save-dev. Mając zainstalowane paczki, możemy przejść do stworzenia pliku webpack.config.js, w którym skonfigurujemy naszego Webpacka.

Importy

Na samym początku pliku powinniśmy dodać moduły, których będziemy używać. Tutaj też dodajemy pluginy, które potrzebujemy. Pluginy i loadery należy pobrać z repozytorium npm/Yarn. W moim przypadku są to trzy pluginy oraz moduł path, którego nie potrzeba doinstalowywać.


const ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');

Następnie tworzymy obiekt module.exports, w którym znajdzie się nasza właściwa konfiguracja.

Entry

W entry podajemy plik/pliki, które stanowią nasze wejście. Stąd Webpack zaczyna swoją drogę po plikach projektu.


    entry: {
        index: path.join(__dirname, './src/public/js/index.js')
    }

Nazwa właściwości może być dowolna, ja nazwałem ją main. Gdy ładujemy tylko jeden plik, możemy napisać po prostu: entry:'./path/to/my/entry/file.js', aczkolwiek, gdy chcemy załadować więcej niż jeden plik, skorzystajmy z obiektu.

Wykorzystałem tutaj moduł path, dzięki któremu możemy dynamicznie dołączyć ścieżkę do naszego pliku wejściowego. Użyłem też tutaj __dirname, które wskazuje na katalog, gdzie zamieściliśmy naszą konfigurację.

Output

W tym obiekcie podajemy lokalizację oraz nazwę naszych plików wyjściowych. Takie pliki są plikami, które możemy wrzucić bezpośrednio na serwer i uruchomić naszą aplikację, bądź stronę internetową.


output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'src/public/dist')
    }

Jako wartość właściwości filename podajemy nazwę pliku, którą też możemy stworzyć dynamicznie. Do stworzenia takiego pliku możemy posłużyć się następującą składnią: [name].[hash].js. W miejsce name zostanie wstawiona nazwa właściwości z obiektu entry (w naszym przypadku jest to main), a w miejsce hash zostanie wygenerowany hash, który sprawi, że nazwa naszego pliku będzie unikalna! Plik wyjściowy może wyglądać na przykład tak: main.cc544c2a7f8fc593a127.js.

Module

To tutaj zaczyna się właściwa część konfiguracji. W tym obiekcie obsługujemy wszystkie pliki i przyporządkowujemy im odpowiednie loadery! Loadery są to paczki, które sprawiają, że Webpack jest w stanie pracować z plikami innymi niż pliki o rozszerzeniu .js. Do obiektu module przekazujemy tablicę rules, zawierającą reguły, dzięki którym znajdziemy w naszym projekcie pliki w odpowiednich formatach. Mogą to być pliki .jpg, .png, .txt, .css, .scss, tak naprawdę jakiekolwiek, jakie posiadają loader!

Do tablicy rules wpisujemy w obiektach kolejne reguły. Pierwszą właściwością jest test. Test jest wyrażeniem regularnym, które pomaga znaleźć plik z odpowiednim rozszerzeniem.  Drugą właściwością jest use. Tutaj możemy dodać jakiś loader lub plugin. Najprostsza reguła może wyglądać w ten sposób: { test: /\.txt$/, use: 'raw-loader' }. Jest to prosta reguła, która wyszuka pliki z rozszerzeniem .txt. Możemy też użyć pluginów.


module: {
        rules: [
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: ['css-loader', 'sass-loader']
                })
            }
        ]
    }

W tym przykładzie obsłużyłem pliki z rozszerzeniem .scss, a ponadto wyeksportowałem je do osobnego pliku .css. Co ważne, loadery, które podajemy wykonywane, są w kolejności od prawej do lewej, od ostatniego elementu w tablicy do pierwszego.

Pluginy

Webpack oferuje programistom ogromną liczbę pluginów. Pluginy odpowiadają za czynności takie jak minifikacja plików, operacje na plikach i katalogach itp. Pluginy podajemy w tablicy jako elementy tej tablicy, korzystając ze słówka new oraz nazwy pluginu. Pluginy musimy, tak jak tez loadery, pobrać za pomocą npm/Yarn. W celu optymalizacji stworzyłem dwie tablice i w zależności od mode ładuję jedną lub dwie.

Mode

Mode jest to inaczej tryb, w jakim pracuje nasza aplikacja. Dokumentacja Webpacka mówi nam o trzech trybach: production, development, oraz none. Tryb production tworzy wersję produkcyjną aplikacji, czyli taka, która ostatecznie ląduje na serwerze, natomiast tryb development tworzy wersję developerską, czyli taką, z którą pracuje programista. W moim przypadku stworzyłem dwie tablice z pluginami, z czego jedna to rozszerzenia, które ładujemy zawsze, natomiast druga zawiera pluginy, które wykorzystuję tylko w wersji produkcyjnej.


const devMode = process.env.NODE_ENV === 'development';

const prodPlugins = [
    new UglifyJsPlugin()
];

const basicPlugins = [
    new CleanWebpackPlugin('src/public/dist'),
    new ExtractTextPlugin('style.css')
];

Zmienna devMode zwraca true w przypadku, gdy zmienna środowiskowa process.env.NODE_ENV ma wartość development. Potem znajdują się dwie tablice z rozszerzeniami. Do niektórych pluginów możemy też dodać argumenty. W naszym przypadku w pluginie CleanWebpackPlugin podajemy ścieżkę do katalogu, który ma zostać opróżniony z plików. Natomiast plugin ExtractTextPlugin* jako parametr otrzymuję nazwę pliku css, który zostanie stworzony. Następnie wracamy do naszego obiektu module.exports, gdzie dołączamy nasze pluginy.

*Edit 22.07.2018

Jak słusznie zauważył jeden z czytelników ExtractTextPlugin nie jest zalecany dla Webpacka w wersji 4. Zamiast niego należy użyć mini-css-extract-plugin.


plugins: devMode ? basicPlugins : basicPlugins.concat(prodPlugins)

W zależności od trybu dołączamy odpowiednie pluginy.

Plik wynikowy

Mamy już omówione wszystkie cztery aspekty budowania naszej konfiguracji webpacka. Plik wynikowy powinien wyglądać mniej więcej tak, jak na poniższym przykładzie.


const ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');

const devMode = process.env.NODE_ENV === 'development';

const prodPlugins = [
    new UglifyJsPlugin()
];

const basicPlugins = [
    new CleanWebpackPlugin('src/public/dist'),
    new ExtractTextPlugin('style.css')
];


module.exports = {
    entry: {
        index: path.join(__dirname, './src/public/js/index.js'),
        room: path.join(__dirname, './src/public/js/room.js')
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'src/public/dist')
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: ['css-loader', 'sass-loader']
                })
            }
        ]
    },
    plugins: devMode ? basicPlugins : basicPlugins.concat(prodPlugins)
};

Jest to podstawowa konfiguracja Webpacka, która pozwoli Ci na komfortową pracę.

package.json

Ostatnim krokiem jest dodanie odpowiednich poleceń do pliku package.json. W scripts dodajemy dwa polecenia. Jedno z nich odpowiada za uruchomienie projektu w wersji developerskiej, a drugie w wersji produkcyjnej. Ponadto wersja developerska obsługuje dynamiczny podgląd zmian w pliku, przez co po zapisie pliku od razu możemy obserwować zmiany w naszym projekcie.


 "scripts": {
   "dev": "webpack --watch --mode development --hot",
   "prod": "webpack --mode production --progress"
 },


Teraz uruchamiając polecenie npm run dev lub npm run build nasz webpack będzie działał poprawnie!

Jako zadanie domowe, dodaj do tej konfiguracji plugin minifikujący wynikowy plik CSS oraz obsługę plików w formatach .jpg , .gif oraz .png.

Źródła i materiały dodatkowe

Dominik Szczepaniak

Zawodowo Senior Software Engineer w CKSource. Prywatnie bloger, fan włoskiej kuchni, miłośnik jazdy na rowerze i treningu siłowego.

Inne wpisy, które mogą Cię zainteresować

Zapisz się na mailing i odbierz e-booka

Odbierz darmowy egzemplarz e-booka 106 Pytań Rekrutacyjnych Junior JavaScript Developer i realnie zwiększ swoje szanse na rozmowie rekrutacyjnej! Będziesz też otrzymywać wartościowe treści i powiadomienia o nowych wpisach na skrzynkę e-mail.

Subscribe
Notify of
guest

2 komentarzy
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Krzysztof Pawłowski
Krzysztof Pawłowski
6 years ago

Na githubowym repozytorium extract-text-webpack-plugin zaleca się użycie mini-css-extract-plugin jeżeli mamy webpacka 4.

Dominik Szczepaniak
6 years ago

Tak, zdaję sobie z tego sprawę, jednakże miałem z nim pewien problem, który jest opisany tutaj: https://stackoverflow.com/questions/50416293/webpack-minicssextractplugin-doesnt-extract-file
Stąd też zdecydowałem się na użycie starszej wersji pluginu.
Dodam adnotację do artykułu i dziękuję za zauważenie błędu 🙂