Подготовка проекта с 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
- Открываем в браузере файл
dist/index.html
, либо если этот файл открыт, перезагружаем страницу браузера. - Смотрим на полученный результат в браузере и, если надо, повторяем шаги сначала.
3. Настройка проекта под разработку
Подключаем webpack-dev-middleware
В созданной сборке нужно каждый раз запускать в терминале команду npm run dev
и вручную обновлять страницу браузера. Для уменьшения количества рутинных операций, автоматизируем процесс.
В webpack доступно три способа, которые позволяют при сохранении кода автоматически его компилировать:
- Режим Watch
webpack-dev-server
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/SCSSsass
- компилятор файлов .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
.