Настройка headers, compress, port, host

Параметр port определяет сетевой порт, на котором запускается сервер разработки webpack-dev-server. Через этот порт браузер получает HTML, JavaScript, CSS, source maps, HMR-обновления и другие ресурсы.

Базовая настройка:

module.exports = {
    devServer: {
        port: 3000,
    },
};

После запуска проекта сервер станет доступен по адресу:

http://localhost:3000

Использование нестандартных портов

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

module.exports = {
    devServer: {
        port: 5173,
    },
};

или:

module.exports = {
    devServer: {
        port: 9000,
    },
};

Автоматический выбор свободного порта

Webpack Dev Server умеет автоматически искать свободный порт.

module.exports = {
    devServer: {
        port: 'auto',
    },
};

Если порт 8080 занят, сервер выберет другой доступный порт:

http://localhost:8081

или:

http://localhost:49152

Подобная конфигурация особенно полезна:

  • при параллельном запуске нескольких frontend-приложений;
  • в монорепозиториях;
  • в Docker-окружениях;
  • при работе нескольких разработчиков через общие шаблоны.

Передача порта через CLI

Порт можно переопределить без изменения конфигурации:

npx webpack serve --port 3000

CLI-параметры имеют более высокий приоритет, чем настройки в webpack.config.js.

Использование переменных окружения

Часто порт зависит от среды выполнения:

module.exports = {
    devServer: {
        port: process.env.PORT || 3000,
    },
};

Пример запуска:

PORT=5000 npx webpack serve

Типичные проблемы с port

Порт уже занят

Ошибка:

Error: listen EADDRINUSE

Причина — другой процесс уже использует порт.

Решения:

npx webpack serve --port 3001

или завершение процесса, занимающего порт.

Конфликт Docker-контейнеров

Если несколько контейнеров пробрасывают один и тот же порт:

ports:
  - "3000:3000"

возникает конфликт на стороне хоста.

Решение — использовать разные внешние порты:

ports:
  - "3001:3000"

Параметр host в devServer

Параметр host определяет сетевой интерфейс, к которому привязывается сервер разработки.

По умолчанию используется:

localhost

Базовая конфигурация:

module.exports = {
    devServer: {
        host: 'localhost',
    },
};

Использование 0.0.0.0

Очень распространённая настройка:

module.exports = {
    devServer: {
        host: '0.0.0.0',
    },
};

0.0.0.0 означает прослушивание всех сетевых интерфейсов.

Сервер становится доступен:

  • локально;
  • по IP-адресу машины;
  • внутри локальной сети;
  • из Docker;
  • из виртуальных машин.

Например:

http://192.168.1.15:3000

Доступ с мобильных устройств

При тестировании адаптивности часто требуется открыть проект на смартфоне.

Конфигурация:

module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: 3000,
    },
};

После этого сайт можно открыть с телефона через локальный IP компьютера.

Использование в Docker

В контейнерах localhost обычно не работает для внешнего доступа.

Правильная настройка:

module.exports = {
    devServer: {
        host: '0.0.0.0',
    },
};

Иначе браузер на хост-машине не сможет подключиться к dev server.

Использование собственного домена

Иногда требуется локальный домен:

module.exports = {
    devServer: {
        host: 'dev.project.local',
    },
};

Для этого дополнительно настраиваются:

  • файл hosts;
  • DNS;
  • reverse proxy.

Параметр allowedHosts

При нестандартных доменах Webpack может блокировать запросы.

Настройка:

module.exports = {
    devServer: {
        host: '0.0.0.0',
        allowedHosts: 'all',
    },
};

или:

module.exports = {
    devServer: {
        allowedHosts: [
            'project.local',
            '.mydomain.com',
        ],
    },
};

Типичные проблемы с host

Недоступность из сети

Конфигурация:

host: 'localhost'

не позволяет подключаться извне.

Решение:

host: '0.0.0.0'

Ошибки WebSocket HMR

Иногда HMR не работает при проксировании или нестандартных доменах.

Тогда дополнительно настраивается:

module.exports = {
    devServer: {
        client: {
            webSocketURL: 'ws://localhost:3000/ws',
        },
    },
};

Параметр compress в devServer

Параметр compress включает gzip-сжатие HTTP-ответов.

module.exports = {
    devServer: {
        compress: true,
    },
};

Webpack Dev Server начинает отправлять ресурсы в сжатом виде:

  • JavaScript;
  • CSS;
  • HTML;
  • JSON;
  • source maps.

Принцип работы gzip

Без сжатия:

app.js → 4.8 MB

После gzip:

app.js.gz → 900 KB

Браузер автоматически распаковывает ответ.

Проверка сжатия

В DevTools браузера:

Content-Encoding: gzip

Когда compress особенно полезен

Большие SPA-приложения

Крупные бандлы загружаются быстрее:

module.exports = {
    devServer: {
        compress: true,
    },
};

Медленные сети

Сжатие уменьшает сетевой трафик при удалённой разработке.

Работа через VPN

Gzip снижает объём передаваемых данных и уменьшает задержки.

Возможные недостатки

Сжатие требует CPU-ресурсов.

На очень слабых машинах или при огромных сборках иногда отключают gzip:

module.exports = {
    devServer: {
        compress: false,
    },
};

Но в большинстве случаев compress: true является оптимальным вариантом.

Отличие dev server от production-сервера

compress влияет только на сервер разработки.

В production gzip обычно настраивается отдельно:

  • Nginx;
  • Apache;
  • CDN;
  • Express;
  • reverse proxy.

Например, production-конфигурация Nginx:

gzip on;
gzip_types text/css application/javascript;

Параметр headers в devServer

Параметр headers позволяет добавлять собственные HTTP-заголовки ко всем ответам dev server.

Базовый пример:

module.exports = {
    devServer: {
        headers: {
            'X-Custom-Header': 'webpack-dev-server',
        },
    },
};

Ответ сервера:

X-Custom-Header: webpack-dev-server

Использование CORS-заголовков

Один из самых распространённых сценариев.

module.exports = {
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
};

Это позволяет:

  • подключать frontend с другого домена;
  • тестировать микрофронтенды;
  • работать с API на другом порту;
  • избегать CORS-ошибок.

Полная настройка CORS

module.exports = {
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
            'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
        },
    },
};

Использование заголовков безопасности

Пример CSP:

module.exports = {
    devServer: {
        headers: {
            'Content-Security-Policy': "default-src 'self'",
        },
    },
};

Пример отключения кеширования:

module.exports = {
    devServer: {
        headers: {
            'Cache-Control': 'no-store',
        },
    },
};

Настройка COOP и COEP

Некоторые браузерные API требуют специальных заголовков.

Например:

  • SharedArrayBuffer;
  • WebAssembly threading;
  • высокопроизводительные worker-механизмы.

Конфигурация:

module.exports = {
    devServer: {
        headers: {
            'Cross-Origin-Opener-Policy': 'same-origin',
            'Cross-Origin-Embedder-Policy': 'require-corp',
        },
    },
};

Использование функции

Заголовки можно генерировать динамически:

module.exports = {
    devServer: {
        headers: () => {
            return {
                'X-Build-Time': Date.now().toString(),
            };
        },
    },
};

Массив заголовков

Webpack поддерживает альтернативный синтаксис:

module.exports = {
    devServer: {
        headers: [
            {
                key: 'X-Version',
                value: '1.0.0',
            },
            {
                key: 'X-Environment',
                value: 'development',
            },
        ],
    },
};

Комплексная настройка devServer

Типичная современная конфигурация:

module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: 3000,
        compress: true,

        headers: {
            'Access-Control-Allow-Origin': '*',
            'Cache-Control': 'no-store',
        },

        allowedHosts: 'all',
        hot: true,
        open: true,
    },
};

Такая конфигурация обеспечивает:

  • доступ из локальной сети;
  • gzip-сжатие;
  • работу CORS;
  • отключение кеширования;
  • поддержку HMR;
  • автоматическое открытие браузера.

Взаимодействие параметров между собой

host и port формируют адрес сервера:

http://host:port

Например:

host: '0.0.0.0',
port: 3000

означает:

http://192.168.1.10:3000

compress влияет на передачу контента по этому адресу.

headers модифицирует HTTP-ответы, отправляемые сервером.

Все параметры работают одновременно внутри единого экземпляра webpack-dev-server.


Конфигурация для микрофронтендов

При использовании Module Federation часто требуется:

module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: 3001,

        headers: {
            'Access-Control-Allow-Origin': '*',
        },

        allowedHosts: 'all',
    },
};

Причины:

  • разные приложения работают на разных портах;
  • frontend загружается с других origin;
  • требуется сетевой доступ между контейнерами.

Конфигурация для Docker

module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: 8080,
        compress: true,

        headers: {
            'Access-Control-Allow-Origin': '*',
        },

        watchFiles: ['src/**/*'],
    },
};

Docker Compose:

services:
  frontend:
    ports:
      - "8080:8080"

Конфигурация для удалённой разработки

module.exports = {
    devServer: {
        host: '0.0.0.0',
        port: 3000,
        compress: true,

        client: {
            overlay: true,
        },

        headers: {
            'Cache-Control': 'no-store',
        },
    },
};

Подобная конфигурация полезна:

  • при разработке на удалённом сервере;
  • в cloud IDE;
  • через SSH tunneling;
  • в Codespaces;
  • в Gitpod.