README.md

Подготовка проекта с webpack с нуля

1. Создание проекта и установка webpack

Необходимые предустановленные инструменты
* NodeJS
* менеджер пакетов NPM
* терминал
* текстовый редактор, например, VS Code
* браузер
* git

Версии инструментов могут различаться от проекта к проекту, необязательно использовать последние версии

Через терминал создадим папку проекта:

mkdir webpack-project

Зайдём в проект и проинициализируем git:

cd webpack-project
git init

Создадим файл .gitignore и запишем туда файлы, которые не должны отслеживаться git:

Через терминал

touch .gitignore

Либо создать через файловый менеджер внутри редактора кода, если он есть.

Запишем и сохраним в .gitignore следующую запись:

node_modules

Теперь, инициализируем npm:

npm i -y

В корне проекта создается файл package.json с настройками по умолчанию, на что указывает опция -y. Подробно о файле package.json читайте в документации по npm.

Теперь установим webpack и webpack-cli, последний нужен для запуска webpack из командной строки. В терминале введем следующее:

npm i -D webpack webpack-cli

i - это сокращение от install. Опция -D указывает, что установленные пакеты нужны только для режима development (режима разработки) и не будут использоваться в производственной сборке. После установки это фиксируется в фале package.json, пакеты будут прописаны в секции "devDependencies": {...}.

Так как это первые пакеты, которые были установлены в проект, то будут созданы каталог node_modules и файл package-lock.json. Каталог node_modules содержит все устанавливаемые пакеты и их зависимости. Этот каталог не рекомендуется включать в репозиторий, поэтому мы указали это в файле .gitignore. Файл package-lock.json хранит записи о точных версиях установленных зависимостей, его тоже обычно добавляют в .gitignore.

Создадим в проекте каталог src, в котором будет храниться исходный код:

mkdir src

Или через файловый менеджер редактора кода.

Создадим в src файл index.js и напишем в нём следующий код:

function component(text) {
  const element = document.createElement('h1');
  element.textContent = text;
  return element;
}

document.body.prepend(component('Проект собран на Webpack'));

Затем в редакторе откроем package.json и добавим в поле "scripts" следующую строку с именем dev:

"scripts": {
  "dev": "webpack --mode development",
  "test": "echo \"Error: no test specified\" && exit 1"
}

Запуск скрипта:

npm run dev

В результате, в корне проекта должен появиться каталог dist, в который скомпилируется файл main.js. Если сравнить содержимое файла main.js с исходным src/index.js, то увидим отличия, хотя файлы выполняют одно и то же. Итак, мы запустили webpack в режиме разработки, в результате, файл src/index.js был транспилирован в файл dist/main.js.

Перед началом выполнения, webpack будет искать в корне проекта файл настроек webpack.config.js. Так как, файл мы ещё не создали, то webpack применяет настройки по умолчанию. Он определяет точку входа src/index.js и выводит откомпилированный код в файл dist/main.js. Подробно об изменении настроек будут ниже.

Создадим в выходном каталоге файл dist/index.html. Именно этот файл браузер начинает загружать первым, а потом загружает те ресурсы, которые прописаны в этом файле. В редакторе кода откроем файл dist/index.html и запишем следующее:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Быстрый запуск Webpack</title>
  </head>
  <body>
    <p>Файл создан вручную</p>
    <script src="main.js"></script>
  </body>
</html>

В этом файле мы указали ссылку на скрипт. Этот скрипт должен быть загружен и выполнен во время выполнения файла dist/index.html. В браузере откроем файл dist/index.html и увидим следующее:

Проект собран на Webpack 
Файл создан вручную

Первая строка текста создана файлом dist/main.js, а вторая - файлом dist/index.html

На данный момент, файловая структура нашего проекта должна выглядеть так:

webpack-project
  |-dist
    index.html
    main.js
  |+node_modules
  |-src
    index.js
  |+.git
  package-lock.json
  package.json
  .gitignore

2. Установка и настройка html-webpack-plugin

В примере выше, мы добавляли вручную файл index.html в выходной каталог. Теперь, настроим webpack, чтобы этот HTML-файл автоматически создавался в готовой сборке из исходного шаблона. Для этого используем плагин html-webpack-plugin, который установим из терминала:

npm i -D html-webpack-plugin

Теперь настроим html-webpack-plugin в файле webpack.config.js. Но сначала создадим этот файл в корне проекта. Затем откроем файл webpack.config.js в редакторе и напишем следующий код:

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

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src', 'template.html'),
      filename: 'index.html',
    }),
  ],
};

Создадим файл src/template.html, откроем в редакторе этот файл и создадим в нём такую разметку:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Быстрый запуск Webpack</title>
  </head>
  <body>
    <p>Файл создан плагином html-webpack-plugin</p>
  </body>
</html>

Теперь, удалим каталог dist с двумя файлами, а после в терминале запустим команду:

npm run dev

Каталог dist снова будет создан, а внутри него созданы файлы index.htmlи main.js. Если откроем в браузере файл dist/index.html, то увидим:

Проект собран на Webpack
Файл создан плагином html-webpack-plugin

Таким образом, webpack с помощью плагина html-webpack-plugin сделал две вещи:

  • создал файл dist/index.html из файла src/template.html
  • в файле dist/index.html автоматически прописал путь к файлу скрипта main.js.

Минимально возможный вариант сборки webpack собран и настроен. С помощью этого шаблона можно начинать разработку проекта по следующему алгоритму: 1. Редактируем исходный код в файлах каталога src 2. Сохраняем результат 3. Выполняем сборку проекта:

npm run dev
  1. Открываем в браузере файл dist/index.html, либо если этот файл открыт, перезагружаем страницу браузера.
  2. Смотрим на полученный результат в браузере и, если надо, повторяем шаги сначала.

3. Настройка проекта под разработку

Подключаем webpack-dev-middleware

В созданной сборке нужно каждый раз запускать в терминале команду npm run dev и вручную обновлять страницу браузера. Для уменьшения количества рутинных операций, автоматизируем процесс.

В webpack доступно три способа, которые позволяют при сохранении кода автоматически его компилировать:

  1. Режим Watch
  2. webpack-dev-server
  3. webpack-dev-middleware

Мы будем использовать webpack-dev-middleware т.к. он имеет более тонкие настройки.

Установим в проект express и webpack-dev-middleware:

npm i -D express webpack-dev-middleware

Фреймворк express нам нужен для создания небольшого сервера, на котором будет запускаться наше приложение.

В корне проекта создадим файл server.js и напишем в нём следующий код:

const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

app.listen(3000, function () {
  console.log("App listening on port 3000\n");
});

В наш webpack.config.js внесём следующие изменения:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  mode: "development",

  entry: {
    index: "./src/index.js",
  },

  devtool: "source-map",

  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "src", "template.html"),
      filename: "index.html",
    }),
  ],

  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
  }
};

В файл package.json добавим новый скрипт для запуска сервера:

"scripts": {
  "start": "node server.js",
  "dev": "webpack --mode development",
  "test": "echo \"Error: no test specified\" && exit 1"
}

Запустим наш сервер, выполнив команду в терминале:

npm run start

Сервер постоянно будет запущен и перекомпилировать код каждый раз, когда мы вносим изменения в него. Теперь не нужно каждый раз выполнять команду npm run build, а в браузере проект доступен по адресу http://localhost:3000/.

Если мы внесём изменения в файл src/index.js и сохраним его, то в терминале увидим, что webpack автоматически перекомпилировал проект, но в браузере изменений не будет, пока снова не перезагрузим страницу. Это по-прежнему доставляет неудобство при разработке и может отнимать некоторое время.

Подключаем webpack-hot-middleware

Чтобы добавить горячую перезагрузку проекта на сервер воспользуемся плагином webpack webpack-hot-middleware.

В терминале введём команду установки плагина:

npm i -D webpack-hot-middleware

Внесём следующие изменения в файл webpack.config.js:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const webpack = require('webpack');

module.exports = {
  mode: "development",

  entry: {
    index: [
      "webpack-hot-middleware/client?path=/__what&timeout=2000&reload=true",
      "./src/index.js"]
  },

  devtool: "source-map",

  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "src", "template.html"),
      filename: "index.html",
    }),
    new webpack.HotModuleReplacementPlugin(),
  ],

  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
  }
};

И в файл server.js:

const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");
const webpackHotMiddleware = require("webpack-hot-middleware");

const app = express();
const config = require("./webpack.config.js");
const compiler = webpack(config);

app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

app.use(
  webpackHotMiddleware(compiler, {
    path: "/__what",
    heartbeat: 10 * 1000,
  })
);

app.listen(3000, function () {
  console.log("App listening on port 3000\n");
});

Теперь после изменений в index.js и сохранения перезагрузка проекта в браузере будет происходить автоматически.

Подключаем Babel

Большинство новых браузеров поддерживают все новые возможности JavaScript ES6-ES13. Но, многие из этих возможностей не поддерживаются старыми браузерами, которые до сих пор используются в мире. Поэтому, если важно сохранять поддержку этих браузеров, то самый распространенный способ - применить Babel.

Babel - это компилятор, который адаптирует новые функции JavaScript для устаревших браузеров.

Для работы Babel требуется два пакета @babel/core и @babel/preset-env, а чтобы Babel работал с webpack, требуется загрузчик babel-loader. Установим эти три пакета одной командой:

npm i -D @babel/core @babel/preset-env babel-loader

Конфигурацию для Babel зададим в файле .babelrc. В корне проекта создадим файл его. Откроем его в редакторе и внесем следующий код:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false
      }
    ]
  ]
}

Для того, чтобы при компиляции для production в наш код не попадал вспомогательный код для разработки, разделим конфиг webpack на две части. Создадим в корне проекта папку webpack, перенесём в неё webpack.config.js и переименуем в webpack.dev.js. Добавим в него следующие изменения:

// пакет для автоматического создания index.html из шаблона с 
// подключением нашего скрипта программы
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const webpack = require('webpack');

module.exports = {
  // включает режим разработки
  mode: "development",
  
  // входной файл
  // настройка горячей перезагрузки
  entry: {
    index: [
      "webpack-hot-middleware/client?path=/__what&timeout=2000&reload=true",
      path.join(__dirname, "../src", "index.js")
    ]
  },

  // включаем в браузере исходную карту для отслеживания ошибок в файлах
  devtool: "source-map",

  // создаём модуль с правилами
  // для всех фалов с расширением .js будет применяться плагин babel-loader
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ["babel-loader"]
      }
    ]
  },

  // выходной файл
  // указываем имя файла и путь, где он будет лежать
  // publicPath указывает базовый путь для всех ресурсов приложения
  // используется вместе в server.js
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
  },

  // подключаем плагин автоматического создания index.html
  // указываем путь до шаблона template.html
  // указываем имя выходного файла как index.html
  // подключаем плагин горячей перезагрузки
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "../src", "template.html"),
      filename: "index.html",
    }),
    new webpack.HotModuleReplacementPlugin(),
  ],
};

Мы создали объект module, для которого задали правило rules. Для вебпака любой файл - это модуль, будь то скрипт, стили, шрифт или изображение. Здесь, для всех модулей (читай, файлов) с расширением .js webpack будет применять плагин babel-loader. Правило не действует на каталог node_modules, что указывается в свойстве module.rules.exclude.

В файле server.js изменим путь до файла конфига:

const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");
const webpackHotMiddleware = require("webpack-hot-middleware");

const app = express();
const config = require("./webpack/webpack.dev.js");
const compiler = webpack(config);

app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

app.use(
  webpackHotMiddleware(compiler, {
    path: "/__what",
    heartbeat: 10 * 1000,
  })
);

app.listen(3000, function () {
  console.log("App listening on port 3000\n");
});

В папке webpack создадим второй файл конфига webpack.prod.js и добавим в него следующие код:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const webpack = require('webpack');

module.exports = {
  mode: "production",

  entry: {
    index: [
      path.join(__dirname, "../src", "index.js")
    ]
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ["babel-loader"]
      }
    ]
  },

  output: {
    filename: "[name].js",
    path: path.join(__dirname, "..", "dist"),
    publicPath: "./",
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "../src", "template.html"),
      filename: "index.html",
    }),
  ],
};

В этом конфиге мы не используем настройки и плагины, которые нужны только для разработки, таким образом в сбилденный код не попадёт ничего лишнего.

В файле package.json добавим ещё один скрипт для сборки проекта в production:

  "scripts": {
    "start": "node server.js",
    "dev": "webpack --mode development",
    "build": "webpack --config webpack/webpack.prod.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  }

Если перед запуском сборки посмотреть файл dist/index.js, то увидим код, который примерно выглядит так:

document.body.prepend(function(e){const t=document.createElement("h1");return t.textContent="Проект собран на Webpack",t}());

В терминале запустим команду:

npm run build

Снова откроем файл dist/index.js, код в нём уже выглядит по-другому:

(()=>{var e;document.body.prepend(("Проект собран на Webpack",(e=document.createElement("h1")).textContent="Проект собран на Webpack",e))})();

Исходный код мы не меняли, но код конечного бандла изменился. Это результат действия компилятора Babel. Второй код поймут все браузеры, которые поддерживают ES5 и выше.

На данный момент, файловая структура нашего проекта должна выглядеть так:

webpack-project
  |-dist
    index.html
    main.js
  |+node_modules
  |-src
    template.html
    index.js
  |-webpack
    webpack.dev.js
    webpack.prod.js
  |+.git
  server.js
  package-lock.json
  package.json
  .babekrc
  .gitignore

Подключаем стили

Для написания стилей будем использовать препроцессор Sass, который расширяет возможности CSS и упрощает создание CSS-кода, а также преобразует SCSS в понятный браузеру код CSS. Однако, не весь современный код CSS распознают устаревшие браузеры. Поэтому, будем дополнительно обрабатывать этот CSS с помощью плагина postcss-preset-env, чтобы большинство браузеров понимало современные стили.

Установим необходимые пакеты:

npm i -D sass-loader postcss-loader postcss-preset-env css-loader style-loader sass

где:

  • sass-loader - загрузчик файлов Sass/SCSS
  • sass - компилятор файлов .scss в .css.
  • postcss-loader - загрузчик CSS файлов для пост-обработки. Должен работать с каким нибудь плагином.
  • postcss-preset-env - плагин для PostCSS, который конвертирует современный CSS в код, понятный большинству браузеров, включением необходимых полифилов.
  • css-loader - загрузчик CSS-файлов
  • style-loader - загрузчик стилей в DOM

Если требуется использовать только CSS и не пользоваться преимуществами SCSS и PostCSS, то установите только css-loader и style-loader.

Создадим файл src/main.scss и внесём в него следующее:

$font-size: 1rem;
$font-color: lch(28 99 35);

html {
  font-size: $font-size;
  color: $font-color;
}

В файле используются переменные Sass и LCH цвета, которые поддерживаются не всеми браузерами, но PostCSS транспилирует эти цвета в понятные любому браузеру.

В файле src/index.js сделаем импорт файла main.scss:

import './main.scss';

Такой импорт стилей в скрипте не поддерживается языком JavaScript, а возможен благодаря webpack.

В webpack.dev.js и webpack.prod.js добавим следующие изменения:

...
module.exports = {
  mode: ...,
  entry: {
    ...
  },

  ...

  // для всех файлов с расширением .scss и .css будут применяться плагины
  // sass-loader, postcss-loader, css-loader и style-loader
  module: {
    rules: [
      {
        ...
      },
      {
        test: /\.(scss|css)$/,
        use: [
          "style-loader",
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      }
    ]
  },
  output: {
    ...
  },

  plugins: [
    ...
  ],
};

Указываем вебпаку, какие загрузчики стилей применять. Причем, порядок их перечисления в массиве свойства use важен, так как загрузчики используются вебпаком от последнего к первому:

  • Так что, последним в списке должен быть sass-loader, который загружает файлы SCSS и передает компилятору sass, а этот компилирует код в CSS.
  • Затем идет postcss-loader, который загружает CSS для PostCSS, а этот, применяя плагины, транспилирует самые современные фичи CSS (переменные, миксины и многое другое) в то, что понятно большинству браузеров. Также, PostCSS применяет автопрефиксер и линтер к CSS.
  • Следующим идет css-loader, который интерпретирует @import и url() внутри CSS.
  • Последним будет style-loader, который внедряет CSS в DOM.

Настройки для PostCSS можно задать как в файле webpack.config.js, так и в собственном файле настроек postcss.config.js. Воспользуемся вторым способом.

Создадим в корне проекта файл postcss.config.js и запишем в файле следующий код:

module.exports = {
  plugins: {
    'postcss-preset-env': {
      browsers: 'last 2 versions',
    },
  },
};

В терминале запустим команду:

npm run server

Откроем браузер и увидим цветной текст:

Проект собран на Webpack
Файл создан плагином html-webpack-plugin

Теперь если мы сбилдим проект:

npm run build

и заглянем в каталог dist, то не обнаружим файла с расширением .css. Это связано с тем, что стили находятся в бандле dist/index.js.

Мы можем извлечь стили в отдельный файл, что позволит браузеру раздельно кэшировать JS и CSS, и если будут внесены изменения в файл CSS, то для обновления браузеру не нужно будет загружать весь бандл, а загрузится лишь обновленный файл CSS. Это положительно сказывается на скорости загрузки страниц браузером.

Чтобы сборщик мог извлекать CSS из файлов .js установим и настроим плагин mini-css-extract-plugin. Начнем с установки:

npm i -D mini-css-extract-plugin

Затем настроем плагин в файле webpack.prod.js для билда проекта:

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

module.exports = {
  mode: "production",
  entry: {
    index: ...
  },
  module: {
    rules: [
      {
        ...
      },
      {
        test: /\.(scss|css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      }
    ]
  },
  output: {
    ...
  },
  plugins: [
    new HtmlWebpackPlugin({
      ...
    }),
    new MiniCssExtractPlugin ({
      filename: "[name].css",
    }),
  ],
};

Вместо style-loader используем MiniCssExtractPlugin.loader.

Проверим работу плагина, для этого в терминале запустим:

npm run build

В каталоге dist появится файл index.css.

Подключаем изображения

Теперь настроим webpack для работы с изображениями в формате PNG, JPG, GIF и SVG. До webpack 5 для работы с изображениями использовались загрузчики raw-loader, url-loader и file-loader. Начиная с webpack 5, вместо загрузчиков изображений, значков, шрифтов и т. д. используется встроенный Asset Modules.

Для поддержки изображений устанавливать ничего не нужно, требуется только настроить webpack.dev.js и webpack.prod.js:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const webpack = require('webpack');

module.exports = {
  mode: ...,
  entry: {
    ...
  },

  ...

  // для всех фалов с расширение png, jpg, jpeg и gif
  // будет применяться правило "asset/resource", т.е.
  // модули будут выводится в указанный с помощью assetModuleFilename каталог
  // для всех фалов с расширением .svg будет применяться привило "asset/resource"
  // generator.filename переопределяет assetModuleFilename для конкретного модуля
  module: {
    rules: [
      {
        ...
      },
      {
        test: /\.(scss|css)$/,
        use: [
          ...
        ],
      },
      {
        test: /\.(png|jpg|jpeg|gif)$/i,
        type: "asset/resource",
      },
      {
        test: /\.svg$/,
        type: "asset/resource",
        generator: {
          filename: path.join("static", "icons", "[name][ext]"),
        },
      },
    ]
  },

  // assetModuleFilename - указываем выходной каталог с именем images
  // для обработанных изображений и шаблон имени [name][ext]
  // для фалов, которые соответствуют правилу type: "asset/resource"
  output: {
    ... ,
    assetModuleFilename: path.join("static", "images", "[name][ext]"),
  },

  plugins: [
    ...
  ],
};

assetModuleFilename - указывает выходной каталог с именем static/images для обработанных изображений и шаблон имени [name][ext] для файлов, которые соответствуют правилу type: "asset/resource". Если assetModuleFilename не указан, то, по умолчанию, каталогом будет dist, а имена файлов будут задаваться по шаблону [contenthash][ext].

[ext] - шаблон для расширения файла, также, включает точку.

generator.filename - переопределяет assetModuleFilename для конкретного asset-правила. Здесь, svg-файлы будут выводиться в каталог dist/static/icons

type имеет четыре типа asset:

  • asset/resource - работает так же, как и загрузчик file-loader. Модули, которые соответствуют правилу type: asset/resource будут выводится в указанный с помощью assetModuleFilename каталог.
  • asset/inline работает как загрузчик url-loader. Модули, соответствующие правилу type: "asset/inline", встраиваются в код бандла как Data URL.
  • asset/source похож на работу загрузчика raw-loader. Модули, соответствующие правилу type: "asset/source", встраиваются без преобразований (как есть).
  • asset объединяет asset/resource и asset/inline. Он работает следующим образом: если размер модуля больше 8 КБ, то он работает как asset/resource, в противном случае - как asset/inline. Размер 8 КБ задан по умолчанию, но его можно изменить с помощью свойства parser.dataUrlCondition.maxSize.

Создадим каталог src/static/images и поместим в него растровое изображения, в моём случае это the_nature.jpg, и векторное - the_brain.svg. Изображения можно выбрать любые, какие захотите.

Откроем фалй src/index.js и внесём в него следующие изменения:

import "./main.scss";

import nature from "./static/images/the_nature.jpg";
import brain from "./static/images/the_brain.svg";

function header(text, className) {
  const element = document.createElement("h1");
  element.textContent = text;
  element.className = className;
  return element;
}

function image(src, className) {
  const element = document.createElement("img");
  element.src = src;
  element.className = className;
  return element;
}

document.body.prepend(
  header("Проект собран на Webpack", "title"),
  image(nature, "image"),
  image(brain, "logo"),
);

Импортировали два изображения и добавили на нашу страницу с помощью тегов img. Указали им классы image для растрового изображения и logo для векторного.

Внесём изменения в main.css:

$font-size: 1rem;
$font-color: lch(28 100 0);

html {
  font-size: $font-size;
  color: $font-color;
}

.title {
  color: green;
}

.image {
  height: 200px;
  width: 200px;
}

.logo {
  height: 56px;
  width: 56px;
}

Запустим сервер:

npm run start

Откроем браузер и увидим, что наши изображения подключились и к ним применились стили.

Подключение шрифтов

Если мы хотим, чтобы во всех браузерах и на всех устройствах наш сайт отображал именно те шрифты, которые указаны в стилях, то нужно эти шрифты поместить на сервер сайта. Если этого не сделать, то у браузера может не оказаться нужного шрифта для отображения и он будет вынужден использовать подходящий шрифт. Это может сказаться на дизайне всего сайта.

Шрифты нашего проекта разместим в каталоге src/static/fonts, создадим этот каталог, а в нём файл fonts.scss.

В этом файле будем хранить CSS стили для шрифтов. Импортируем файл fonts.scss в src/index.js:

import "./main.scss";
import "./static/fonts/fonts.scss";

import nature from "./static/images/the_nature.jpg";
import brain from "./static/images/the_brain.svg";

// javascript коде..

Теперь, скачаем нужные шрифты и код CSS для них.

На странице google-webfonts-helper в списке слева нужно выбрать необходимый шрифт.

Справа от списка появится страница для шрифта. На этой странице можно дополнительно указать нужные кодировки и стили, которые планируется использовать в шрифте.

В секции Select charsets выберем cyrillic и latin.

В секции Select styles выберем regular, italic, 700 и 700italic

В секции Copy CSS: в поле Customize folder prefix (optional): укажем префикс пути ./ и скопируем из серого поля CSS-код в наш файл src/fonts/fonts.scss.

Нажмем на синюю кнопку в секции Download files и скачаем файл с расширением .zip.

Распакуем из zip-архива файлы шрифтов в каталог src/fonts/.

Рекомендуется оптимизировать шрифты на таких сервисах как Font2web или Transfonter, но шрифты Google уже оптимизированы, поэтому этот шаг можно пропустить.

Для обработки шрифтов вебпаком добавим следующие правила в файл webpack.dev.js и webpack.prod.js:

  module: {
    rules: [
      {
        test: /\.(woff2?|eot|ttf|otf)$/i,
        type: "asset/resource",
        generator: {
          filename: path.join("static", "fonts", "[name][ext]"),
        }
      },
    ],
  },

В файле main.scss укажем на используемый шрифт. Так, если это будет шрифт Roboto и мы хотим его использовать по всему нашему проекту, то запишем:

html {
  font-family: "Roboto";
}

Запустим сервер:

npm run server

и в браузере через инспектор кода увидим, что шрифт Roboto применился к тексту.

Копирование файлов и каталогов

Часто, возникает необходимость скопировать в готовую сборку некоторые файлы или каталоги без каких-либо преобразований. Это могут быть файлы PDF, либо файл robots.txt, который используется для ограничения доступа поисковым роботам к некоторым ресурсам сайта, файлы favicon.ico, sitemap.xml и т.п. В исходном коде такие ресурсы, обычно, помещают в каталог static, а из него эти ресурсы копируют в корень каталога dist.

Создадим каталог src/static, а в нем каталог favicon.

Воспользуемся генератором favicon.io. Настраиваем иконку под наш сайт и скачиваем архив с фалами. Распаковываем его в наш каталог src/static/favicon.

Копируем со страницы генератора favicon.io следующие строчки:

<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">

Добавим их в src/template.html и допишем путь href до каталога static/favicon:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Быстрый запуск Webpack</title>

  <link rel="apple-touch-icon" sizes="180x180" href="./static/favicon/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="./static/favicon/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="./static/favicon/favicon-16x16.png">
</head>

<body>
  <p>Файл создан плагином html-webpack-plugin</p>
</body>

</html>

В конфиге webpack.prod.js добавим следующие изменения:


...
const FileManagerPlugin = require('filemanager-webpack-plugin');

module.exports = {
  mode: "production",

  entry: {
    ...
  },

  module: {
    ...
  },

  output: {
    ...
  },

  plugins: [
    new HtmlWebpackPlugin({
      ...
    }),
    new MiniCssExtractPlugin ({
      ...
    }),
    new FileManagerPlugin({
      events: {
        onEnd: {
          copy: [
            {
              source: path.join("src", "static"),
              destination: path.join("dist", "static"),
            },
          ],
        },
      },
    }),
  ],
};

Выполним команду:

npm run build

В каталоге dist/static появился каталог favicon. При открытии в браузере файла dist/index.html мы увидим, что у вкладки появилась наша иконка.

На этом этапе настройка webpack закончена. По сути мы создали стартовый шаблон проекта для любого проекта. Теперь можно к нему подключать любой, какой вы захотите, фреймворк/библиотеку для создания пользовательского интерфейса, а также настроить для работы с TypeScript.

Подключение React к webpack описано в ветке wp-react.

Описание

Создание проекта с webpack

Конвейеры
0 успешных
0 с ошибкой