DevGang
Авторизоваться

Использование плагина HTML Bundler для Webpack для создания файлов HTML

Webpack работает для создания пакетов JavaScript, но не поддерживает ни файлы HTML, ни файлы CSS из коробки. Чтобы связать скомпилированный JavaScript и CSS с HTML, мы можем использовать мощный плагин html-bundler-webpack-plugin.

Установка

Первый шаг — установка плагина:

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

Установите дополнительные пакеты для стилей:

npm install css-loader sass-loader sass --save-dev

Простой статический сайт

Мы создали несколько статических файлов, чтобы продемонстрировать, как плагин обрабатывает ссылки в HTML на исходные файлы сценариев, стилей и изображений:

src/js/main.js
src/scss/styles.scss
src/views/index.html
src/images/favicon.ico
src/images/picture.png (size > 2 KB)
src/images/icon.png    (size < 2 KB)

Создайте файл index.html в каталоге src/view/:

<!doctype html>
<html lang="en">
<head>
  <title>Home</title>
  <link href="../images/favicon.ico" rel="shortcut icon">
  <link href="../scss/styles.scss" rel="stylesheet">
  <script src="../js/main.js" defer="defer"></script>
</head>
<body>
  <h1>Homepage</h1>
  <img src="../images/picture.png" alt="picture">
  <img src="../images/icon.png" alt="icon">
</body>
</html>

Чтобы связать наши файлы стилей и скриптов с HTML, мы указываем их непосредственно в HTML, используя относительные пути к исходным файлам.

При сложной файловой структуре некоторые относительные пути могут иметь вид ../../../images. Чтобы избежать таких нечитаемых путей, рекомендуется использовать псевдонимы Webpack.

Плагин позволяет нам использовать как относительные пути, так и псевдонимы Webpack.

Мы будем использовать псевдонимы, поэтому определим их в параметре resolve.alias Webpack:

{
  '@scripts': path.join(__dirname, 'src/js'),
  '@styles': path.join(__dirname, 'src/scss'),
  '@images': path.join(__dirname, 'src/images'),
}

Затем измените все относительные пути в index.html на псевдонимы:

<!doctype html>
<html lang="en">
<head>
  <title>Hello World</title>
  <link href="@images/favicon.ico" rel="shortcut icon">
  <link href="@styles/styles.scss" rel="stylesheet">
  <script src="@scripts/main.js" defer="defer"></script>
</head>
<body>
  <h1>Hello World!</h1>
  <img src="@images/picture.png" alt="picture">
  <img src="@images/icon.png" alt="icon">
</body>
</html>

Так HTML выглядит лучше и чище.

Обработка HTML-шаблонов

Webpack не знает, как обрабатывать шаблоны HTML, но плагин html-bundler-webpack-plugin может обрабатывать шаблоны и помещать сгенерированный HTML в выходной каталог.

Настройте плагин в webpack.config.js для обработки index.html:

const path = require('path');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },

  plugins: [
    new HtmlBundlerPlugin({
      entry: {
        // define templates here
        index: 'src/views/index.html',
      },
    }),
  ],
  // ...
};

Мы можем определить HTML-шаблоны в параметрах entry плагина. Ключ entry — это имя выходного файла без расширения .html, а значение — файл шаблона. Таким образом, мы можем определить множество шаблонов в опции entry.

Автоматическая обработка многих HTML-шаблонов

Существует один файл шаблона, но было бы утомительно обновлять конфигурацию Webpack каждый раз, когда шаблоны добавляются или удаляются. Вместо того, чтобы вручную добавлять другие шаблоны, давайте изменим конфигурацию, чтобы она автоматически включала все найденные шаблоны.

module.exports = {
  // ...
  plugins: [
    new HtmlBundlerPlugin({
      // relative or absolute path to templates
      entry: 'src/views/',
    }),
  ],
  // ...
};

Если параметром entry является путь, плагин автоматически находит все шаблоны и сохраняет ту же структуру каталогов в выходном каталоге. Таким образом, мы можем создать множество шаблонов в каталоге входа без перезапуска Webpack, работающего в режиме serve.

Обработка стилей

Чтобы скомпилировать файлы Sass, указанные в HTML, в CSS, добавьте правило модуля:

module.exports = {
   // ...
   module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: ['css-loader', 'sass-loader'],
      },
    ],
  },  
  // ...
};

Плагин извлекает CSS из скомпилированных файлов Sass и сохраняет в виде отдельного файла в выходной каталог.

Обработка изображений

Плагин разрешает ссылки на изображения, указанные в HTML, и позволяет Webpack копировать эти изображения в выходной каталог. Мы можем определить хешированное имя выходного файла для изображений, используя generator.filename в правиле:

module.exports = {
   // ...
   module: {
    rules: [
      {
        test: /\.(ico|png|jp?g|svg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'img/[name].[hash:8][ext]',
        },
      },
    ],
  },  
  // ...
};

Чтобы оптимизировать загрузку небольших изображений, мы можем встроить изображения прямо в HTML, используя type: 'asset' и parser.dataUrlCondition.maxSize в правиле:

module.exports = {
   // ...
   module: {
    rules: [
      {
        test: /\.(ico|png|jp?g|svg)$/,
        type: 'asset',
        generator: {
          // save images to file
          filename: 'img/[name].[hash:8][ext]',
        },
        parser: {
          dataUrlCondition: {
            // inline images < 2 KB
            maxSize: 2 * 1024
          }
        },
      },
    ],
  },  
  // ...
};

Плагин автоматически встраивает изображения меньше, чем maxSize.

Выходные имена файлов для JS и CSS

По умолчанию обработанные файлы JS и CSS будут сохранены в выходном каталоге под нехешированными именами файлов. Но рекомендуется использовать хешированные имена выходных файлов.

Мы можем определить имена выходных файлов для JS и CSS в параметрах плагина:

module.exports = {
  // ...
  plugins: [
    new HtmlBundlerPlugin({
      entry: {
        index: 'src/views/index.html',
      },
      js: {
        // output filename for JS
        filename: 'js/[name].[contenthash:8].js',
      },
      css: {
        // output filename for CSS
        filename: 'css/[name].[contenthash:8].css',
      },
    }),
  ],
  // ...
};

Необязательно, вы можете встроить JS и CSS в HTML, используя параметры плагина js.inline и css.inline.

Живая перезагрузка

Чтобы включить перезагрузку браузера после изменений, добавьте опцию devServer в конфиг Webpack:

module.exports = {
  // enable HMR with live reload
  devServer: {
    static: path.join(__dirname, 'dist'),
    watchFiles: {
      paths: ['src/**/*.*'],
      options: {
        usePolling: true,
      },
    },
  },
};

Окончательная конфигурация веб-пакета

const path = require('path');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  mode: 'development',

  output: {
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },

  resolve: {
    alias: {
      '@scripts': path.join(__dirname, 'src/js'),
      '@styles': path.join(__dirname, 'src/scss'),
      '@images': path.join(__dirname, 'src/images'),
    },
  },

  plugins: [
    new HtmlBundlerPlugin({
      // path to templates
      entry: 'src/views/',
      js: {
        // output filename for JS
        filename: 'js/[name].[contenthash:8].js',
      },
      css: {
        // output filename for CSS
        filename: 'css/[name].[contenthash:8].css',
      },
    }),
  ],

  module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: ['css-loader', 'sass-loader'],
      },
      {
        test: /\.(ico|png|jp?g|svg)/,
        type: 'asset',
        generator: {
          // save images to file
          filename: 'img/[name].[hash:8][ext]',
        },
        parser: {
          dataUrlCondition: {
            // inline images < 2 KB
            maxSize: 2 * 1024,
          },
        },
      },
    ],
  },

  // enable HMR with live reload
  devServer: {
    static: path.resolve(__dirname, 'dist'),
    watchFiles: {
      paths: ['src/**/*.*'],
      options: {
        usePolling: true,
      },
    },
  },
};

Заключение

Сгенерированный HTML содержит выходные имена обработанных файлов и встроенное маленькое изображение. Все обработанные файлы помещаются в выходном каталоге dist/.

<!doctype html>
<html lang="en">
<head>
  <title>Home</title>
  <link href="img/favicon.34fd67a8.ico" rel="shortcut icon">
  <link href="css/styles.f042b772.css" rel="stylesheet">
  <script src="js/main.b35246f4.js" defer="defer"></script>
</head>
<body>
  <h1>Homepage</h1>
  <img src="img/picture.7b396424.png" alt="picture">
  <!-- src contains "data:image/png;base64,iVBORwSU..." -->
  <img src="..." alt="icon">
</body>
</html>

С помощью всего лишь одного плагина html-bundler-webpack-plugin вы можете очень легко настроить Webpack для создания статических HTML-файлов.

Посмотреть исходный код на GitHub

Попробуйте в браузере

Источник:

#JavaScript #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу