HTML soubor a obrázky

V této části si nakonfigurujeme Webpack tak, aby nám do dist složky kopíroval i HTML soubor a obrázky. Poté již budeme mít naši aplikaci v podstatě nakonfigurovanou a budeme ji moci pomocí jednoho příkazu sestavit pro produkci.

Pokud z nějakého důvodu nemáte kód z minulé části, tak si můžete stáhnout startovní kód pro tuto část. Po stažení nezapomeňte nainstalovat balíčky pomocí příkazu "npm install".

Vytvoření HTML souboru

K vytvoření HTML souboru v dist složce použijeme plugin jménem HtmlWebpackPlugin. Můžeme jej nainstalovat následujícím příkazem:

npm install --save-dev html-webpack-plugin

Po instalaci můžeme HtmlWebpackPlugin použít. Přidáme jej do pole v části plugins, kde jej nakonfigurujeme. HtmlWebpackPlugin můžeme použít i víc než jednou. Třeba pro více souborů. Proto vytváříme jeho instanci.

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: "./index.js",
    output: {
        filename: "index.js",
        path: path.resolve(__dirname, "dist"),
        clean: true
    },
    module: {
        rules: [
            {
                test: /\.css$/i,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    ["postcss-preset-env", {}]
                                ]
                            }
                        }
                    }
                ]
            },
            {
                test: /\.less$/i,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    ["postcss-preset-env", {}]
                                ]
                            }
                        }
                    },
                    "less-loader"
                ]
            }
        ]
    },
    optimization: {
        minimizer: [
            `...`,
            new CssMinimizerPlugin()
        ]
    },
    plugins: [
        new MiniCssExtractPlugin(),
        new HtmlWebpackPlugin({
            template: "./index.html"
        })
    ]
}

HtmlWebpackPlugin jsme nastavili tak, aby použil soubor index.html z naší kořenové složky. Mohli bychom toho nastavit ještě více. Například na jakém vstupním souboru je HTML soubor závislý. Protože ale máme jen jeden vstupní soubor, tak to ani nenastavujeme a automaticky se použije. Odkaz na CSS a JS soubory se do HTML souboru umístí automaticky, podle toho na kterém vstupním souboru je HTML soubor závislý. Můžeme z něj tedy tyto odkazy odstranit. Náš HTML soubor bude vypadat takto:

<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Webpack App</title>
</head>
<body>
    <div class="page">
        <header class="header">
            <h1 class="heading-primary">Webpack App</h1>
        </header>
        <div class="page__content">
            <div class="centered-flex-row u-mb-6">
                <input type="number" id="Number1" class="input">
                <select id="Operation" class="select">
                    <option value="SCITANI">+</option>
                    <option value="ODECITANI">-</option>
                    <option value="DELENI">/</option>
                    <option value="NASOBENI">*</option>
                </select>
                <input type="number" id="Number2" class="input">
                <button id="SubmitButton" class="button">=</button>
            </div>
            <p id="ErrorMessage" class="error-message u-mb-8"></p>
            <p id="ResultText" class="result-text u-mb-8">Výsledek je: <span id="ResultValue" class="result-text__value"></span></p>
            <hr class="horizontal-rule u-mb-8">
            <img src="./assets/img/image.svg" class="image">
        </div>
    </div>
</body>
</html>

Pokud spustíme Webpack, tak by se nám v dist složce měl vytvořit HTML soubor. Pokud si jej otevřete v prohlížeči, tak by aplikace měla fungovat, akorát obrázek se nepodaří načíst.

Kopírování obrázků

Ke kopírování obrázků do dist složky použijeme plugin jménem copy-webpack-plugin. Použijeme jej na obrázky, ale můžeme s jeho pomocí kopírovat i jiné typy souborů. Nainstalujeme jej následujícím příkazem:

npm install --save-dev copy-webpack-plugin

CopyPlugin v naší konfiguraci můžeme přidat do pole v části plugins. Tam si vytvoříme jeho instanci a nastavíme si jej. Do vlastnosti patterns předáváme pole objektů, kde vždy každý objekt určuje, co se má odkud kam kopírovat. Kopírujeme všechny soubory ze složky assets/img do složky dist. Překopíruje se i struktura složek, takže nám v dist složce vznikne složka assets a v ní složka img s obrázkem.

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
    entry: "./index.js",
    output: {
        filename: "index.js",
        path: path.resolve(__dirname, "dist"),
        clean: true
    },
    module: {
        rules: [
            {
                test: /\.css$/i,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    ["postcss-preset-env", {}]
                                ]
                            }
                        }
                    }
                ]
            },
            {
                test: /\.less$/i,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    ["postcss-preset-env", {}]
                                ]
                            }
                        }
                    },
                    "less-loader"
                ]
            }
        ]
    },
    optimization: {
        minimizer: [
            `...`,
            new CssMinimizerPlugin()
        ]
    },
    plugins: [
        new MiniCssExtractPlugin(),
        new HtmlWebpackPlugin({
            template: "./index.html"
        }),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "assets/img/*").replace(/\\/g, "/"),
                    to: path.resolve(__dirname, "dist")
                }
            ]
        })
    ]
}

Jak můžete v ukázce vidět, tak u cesty odkud se mají soubory kopírovat měníme pomocí metody replace znaky "\\" za znak "/". To je proto, aby to fungovalo ve Windowsu, jak jsem si našel v dokumentaci. Pokud máte jiný operační systém a háže vám to chybu nebo to nefunguje, tak zkuste volání této metody odstranit.

Aplikaci teď můžeme sestavit pomocí našeho skriptu zavoláním "npm run build". Ve složce dist by se nám měla objevit složka assets obsahující složku img s obrázkem. Když si teď sestavenou aplikaci spustíte v prohlížeči, tak se již podaří načíst i obrázek.

S konfigurací pro sestavení naší aplikace pro produkci jsme hotovi. Dost jsme ji optimalizovali. Sloučili jsme JavaScript kód do jednoho souboru, CSS kód také, naše styly jsme automaticky prefixnuly aby novější CSS vlastnosti fungovali i v prohlížečích, které je zatím podporují jen experimentálně a také jsme naše soubory zminifikovali, aby se načetli co nejrychleji. Pokud bychom ale na naší aplikaci chtěli dál pracovat, tak není moc komfortní vždy po nějaké změně psát "npm run build" a čekat až se aplikace sestaví. Proto si v příští části vytvoříme konfiguraci pro vývoj, kterou budeme používat, když budeme aplikaci vyvíjet.