Webpack Dev Server поддерживает запуск локального сервера по протоколу HTTPS. Это особенно важно в современных frontend-приложениях, поскольку многие браузерные API работают только в защищённом контексте.
К таким API относятся:
При обычном HTTP часть функциональности либо полностью блокируется браузером, либо работает с ограничениями.
Webpack Dev Server позволяет запускать локальный сервер через TLS/SSL и использовать сертификаты аналогично production-среде.
В Webpack Dev Server HTTPS активируется через параметр
server.
Пример для Webpack 5:
module.exports = {
devServer: {
server: 'https'
}
};
После запуска dev server приложение будет доступно по адресу:
https://localhost:8080
https: trueВ старых конфигурациях использовалась запись:
devServer: {
https: true
}
В Webpack 5 предпочтительным считается новый синтаксис через
server.
Современный вариант:
devServer: {
server: 'https'
}
Webpack Dev Server создаёт локальный HTTPS-сервер поверх Node.js TLS API.
При запуске:
Если сертификат самоподписанный, браузер обычно показывает предупреждение безопасности.
Самоподписанный сертификат — сертификат, подписанный не центром сертификации (CA), а самим владельцем.
Для локальной разработки это нормальная практика.
Такие сертификаты:
Но браузер не доверяет таким сертификатам автоматически.
Если указать:
devServer: {
server: 'https'
}
Webpack Dev Server способен автоматически создать временный сертификат.
Проблемы такого подхода:
Для полноценной разработки обычно создают собственный локальный сертификат.
openssl genrsa -out localhost.key 2048
openssl req -new -x509 \
-key localhost.key \
-out localhost.crt \
-days 365
В процессе OpenSSL запросит параметры:
Country Name
State
Locality
Organization
Common Name
Для локальной разработки особенно важен параметр:
Common Name
Обычно указывается:
localhost
После генерации появляются файлы:
certs/
├── localhost.crt
└── localhost.key
.key — приватный ключ;.crt — публичный сертификат.Приватный ключ нельзя публиковать в репозитории.
const fs = require('fs');
const path = require('path');
module.exports = {
devServer: {
server: {
type: 'https',
options: {
key: fs.readFileSync(
path.resolve(__dirname, 'certs/localhost.key')
),
cert: fs.readFileSync(
path.resolve(__dirname, 'certs/localhost.crt')
)
}
}
}
};
server.optionsWebpack передаёт объект options непосредственно в
HTTPS-сервер Node.js.
Можно использовать:
server: {
type: 'https',
options: {
key,
cert,
ca,
passphrase,
requestCert
}
}
.pemВместо .crt и .key часто используются
.pem-файлы.
Пример:
server: {
type: 'https',
options: {
key: fs.readFileSync('./certs/key.pem'),
cert: fs.readFileSync('./certs/cert.pem')
}
}
После запуска:
npm run dev
или:
webpack serve
сервер становится доступен:
https://localhost:8080
При первом открытии браузер может показать:
Your connection is not private
Это связано с отсутствием доверия к сертификату.
Сертификат .crt импортируется в:
Trusted Root Certification Authorities
Через:
certmgr.msc
Сертификат импортируется в:
Keychain Access
После импорта необходимо установить:
Always Trust
В Linux доверенные сертификаты зависят от дистрибутива.
Для Ubuntu:
sudo cp localhost.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
mkcert — один из самых удобных инструментов для
локальных HTTPS-сертификатов.
Преимущества:
brew install mkcert
choco install mkcert
sudo apt install mkcert
mkcert -install
Команда создаёт локальный root certificate authority и добавляет его в систему.
mkcert localhost
Создаются файлы:
localhost.pem
localhost-key.pem
const fs = require('fs');
module.exports = {
devServer: {
server: {
type: 'https',
options: {
key: fs.readFileSync('./localhost-key.pem'),
cert: fs.readFileSync('./localhost.pem')
}
}
}
};
HMR использует WebSocket-соединение.
При HTTPS браузер требует:
wss://);Если сертификат недоверенный, возможны ошибки:
WebSocket connection failed
или:
ERR_CERT_AUTHORITY_INVALID
Иногда требуется явная настройка клиента:
devServer: {
client: {
webSocketURL: {
hostname: 'localhost',
port: 8080,
protocol: 'wss'
}
}
}
Это особенно важно:
Webpack Dev Server часто работает за Nginx.
Схема:
Browser
↓ HTTPS
Nginx
↓ HTTP
Webpack Dev Server
В этом случае HTTPS может завершаться на proxy-сервере.
Иногда HTTPS нужен непосредственно внутри webpack-dev-server:
Browser
↓ HTTPS
Webpack Dev Server
Такой подход удобен:
По умолчанию используется:
localhost
Но можно указать собственный hostname:
devServer: {
host: 'local.project.test',
server: {
type: 'https',
options: {
key,
cert
}
}
}
Сертификат должен совпадать с hostname.
Например:
local.project.test
Если сертификат выпущен для localhost, браузер выдаст
ошибку:
NET::ERR_CERT_COMMON_NAME_INVALID
Современные браузеры используют SAN вместо Common Name.
При генерации сертификатов необходимо указывать:
DNS:localhost
DNS:local.project.test
Без SAN сертификат может считаться невалидным.
При использовании Docker сертификаты обычно монтируются в контейнер:
volumes:
- ./certs:/app/certs
Webpack читает сертификаты из контейнера:
fs.readFileSync('/app/certs/localhost.key')
В WSL возможны проблемы:
Обычно сертификат необходимо импортировать и в Windows.
Webpack Dev Server способен работать через HTTP/2.
Пример:
devServer: {
server: {
type: 'https'
}
}
Node.js автоматически поддерживает ALPN negotiation.
HTTP/2 даёт:
Некоторые cookie работают только через HTTPS:
Set-Cookie: session=123; Secure
Без HTTPS браузер игнорирует такие cookie.
Локальный HTTPS позволяет тестировать production-поведение авторизации.
Service Worker требует secure context.
Работают только:
https://
или:
http://localhost
Но полноценное тестирование PWA обычно выполняется именно через HTTPS.
При HTTPS часто появляются смешанные схемы:
https://frontend.local
http://api.local
Браузер блокирует такие запросы как mixed content.
Необходимо:
Пример proxy:
devServer: {
proxy: {
'/api': {
target: 'https://backend.local',
secure: false
}
}
}
secure: falseОпция:
secure: false
отключает проверку SSL-сертификата backend-сервера.
Полезно для локальных self-signed сертификатов.
Типичная ошибка:
Mixed Content: The page was loaded over HTTPS,
but requested an insecure resource
Причины:
Все ресурсы должны использовать HTTPS.
В браузере можно просмотреть:
Это помогает диагностировать ошибки TLS.
Браузер не доверяет сертификату.
Hostname не совпадает с сертификатом.
Проблемы TLS или wss://.
Некорректная конфигурация TLS.
Ошибка TLS-рукопожатия в Node.js.
Обычно используется структура:
project/
├── certs/
│ ├── localhost.key
│ └── localhost.crt
├── webpack.config.js
└── package.json
.gitignore:
certs/*.key
certs/*.pem
certs/*.crt
Особенно важно исключать приватные ключи.
Пути к сертификатам можно задавать через .env.
Пример:
SSL_KEY=./certs/dev.key
SSL_CERT=./certs/dev.crt
Конфигурация:
const fs = require('fs');
server: {
type: 'https',
options: {
key: fs.readFileSync(process.env.SSL_KEY),
cert: fs.readFileSync(process.env.SSL_CERT)
}
}
В monorepo сертификаты часто выносятся в общий каталог:
tools/certs/
Это позволяет использовать один локальный CA для нескольких приложений.
Иногда создаются сертификаты:
*.local.test
Это удобно для микрофронтендов и мультидоменной разработки.
TLS добавляет:
Но для локальной разработки нагрузка обычно незначительна.
Наиболее стабильная схема:
mkcert;wss://;Такой подход максимально близок к production-среде и снижает количество проблем при деплое.