Webpack a Koa.js - Balíčkování klientských skriptů

Prakticky každý web obsahuje CSS styly a JS skripty a ty je třeba servírovat na klienta perfektně připravené. Webpack s tím dokáže pomoct.

Základní požadavky - proč je potřeba balíčkovač

Balíčkovač assetů (stylů, obrázků a javascriptů) má za cíl řešit následující problémy, které dříve či později nastanou:

  • Import prerekvizit do kódu a jejich následné načítání (import/require/export)
  • Spojit spousty souborů do několika málo balíčků, které si prohlížeč snáze stáhne
  • Zmenšit zdrojový kód odstraněním mezer, komentářů a podobně
  • Přeložit ES6 JavaScript do ES5 a doplnit kód o polyfily kvůli kompatibilitě se staršími prohlížeči
  • Umožnit zakomponování NPM modulů do klientského kódu
  • Přeložit LESS nebo SASS styly do CSS podoby
  • Umožnit debugování javascriptu v prohlížeči
  • Překládat JSX (React) nebo TypeScript (Angular)

To vše Webpack zvládá. Existují sice alternativy jako JSPM, SystemJs, nebo Steal.js, ale Webpack je ze všech možných variant tou nejflexibilnější.

Buildujeme JavaScript

Začneme pěkně od podlahy instalací samotného Webpacku. Balíček není v produkci potřebný, tudíž použíjeme --save-dev:

npm install --save-dev webpack  

Aby Webpack správně fungoval, je třeba ho nakonfigurovat. K tomu slouží webpack.config.js, který umístíme do kořenového adresáře projektu. Jeho základní podoba může vypadat takto:

const path = require('path');

module.exports = {  
    entry: {
        // adresa kořenového skriptu projektu
        main: './public/lib/main'
    },
    output: {
        // uložiště produkčních skriptů
        path: path.join(__dirname, 'public/dist'),
        // formát názvu souboru
        filename: '[name].bundle.js'
    }
};

K buildu je možné využít samotný CLI nástroj Webpacku, ale pro jednodušší konfiguraci procesu vytvoříme buld skript: bin/build. Ten rozšíři konfiguraci o Uglify plugin, který výrazně zmenší a znečitelní zdrojový kód pro použití v produčním prostředí:

#!/usr/bin/env node
'use strict';

const webpack = require('webpack');  
const webpackConfig = require('../webpack.config');  
const UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

const uglify = new UglifyJsPlugin({ minimize: true });  
webpackConfig.plugins.push(uglify);

const compiler = webpack(webpackConfig);  
compiler.run((err, stats) => {  
    if (err) {
        console.log('Build failed', err);
    } else {
        console.log('Build is done.', stats);
    }
});

K pohodlnému spouštění pak lze do package.json přidat direktivu pro build skript:

"scripts": {
  "build": "node ./bin/build"
},

A následně build spustit příkazem npm run build, čímž ze souboru /public/js/lib/main.js vznikne jeho kompilát /public/dist/main.bundle.js.

Vyvíjíme a nasazujeme klientský JavaScript s Koa.js

Pro vývoj využijeme modul koa-webpack-dev, který zajistí automatický rebuild v případě změny zdrojových souborů a výkonný modul koa-static-cache. Ten na produkčním prostředí zajistí načítání vybuildovaného kódu.

npm install --save-dev koa-webpack-dev  
npm install --save koa-static-cache  

Nakonec v rámci kořenového skriptu Koa.js aplikace app.js vytvoříme podmínku, která v případě vývojového prostředí nasadí Webpack Dev server. KoaStaticCache je pak nastavena, aby na vývojovém prostředí nebylo nutné při změně souborů restartovat aplikaci (buffer pro cachovaní obsahu a dynamic pro vypnutí cachování stromu souborů).

const publicPath = path.join(__dirname, 'public');  
const koaStaticCache = require('koa-static-cache');  
const isProduction = process.env.NODE_ENV === 'production';

if (!isProduction) {  
    const koaWebpackDev = require('koa-webpack-dev');
    const webpackConfig = require('./webpack.config');

    Object.assign(webpackConfig, {
        devtool: 'eval-cheap-module-source-map'
    });

    app.use(koaWebpackDev({
        config: webpackConfig,
        webRoot: publicPath
    }));
}

app.use(koaStaticCache(publicPath, {  
    buffer: isProduction,
    dynamic: !isProduction,
    filter: (file) => file.match(/^(?!lib|less|components)/)
}));

Kritickým místem Webpacku jsou source mapy. Jde o soubor, který umožňuje vývojáři ladit vybuildovaný JavaScript, stejně jako by šlo o samostatné soubory. Vytváření takových map je relativně náročný proces a proto nastavení devtool pak u velkých projektů výrazně ovlivňuje výkon WebPacku. Záleží na preferencích každého z vás. Více o možnostech najdete v dokumentaci Webpacku.

Kam dále

David Menger

Read more posts by this author.