Параметр path и publicPath

output.path определяет абсолютный путь в файловой системе, куда Webpack записывает собранные файлы после выполнения сборки. Это базовая настройка, от которой зависит физическое расположение итогового бандла и всех вспомогательных ассетов.

Ключевое ограничение: значение output.path всегда должно быть абсолютным путём. Относительные пути не допускаются, так как Webpack должен точно понимать, куда писать файлы независимо от текущей рабочей директории процесса.

Типичный пример:

const path = require('path');

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

Здесь используется path.resolve, который формирует абсолютный путь на основе текущего расположения конфигурационного файла. Конструкция __dirname гарантирует стабильность независимо от того, откуда запускается сборка.

Роль в процессе сборки

Во время компиляции Webpack формирует граф модулей, после чего сериализует результат в набор файлов. Именно output.path определяет:

  • куда записывается основной bundle
  • где размещаются чанки при code splitting
  • куда сохраняются ассеты (изображения, шрифты, медиа)
  • куда пишутся source map файлы (если включены)

Если директория не существует, Webpack создаёт её автоматически.

Связь с режимами разработки и продакшена

В development-режиме output.path часто указывает на локальную папку вроде dist или build, но физическая запись файлов может быть частично абстрагирована webpack-dev-server, который отдаёт файлы из памяти.

В production-режиме значение становится критически важным, так как именно сюда попадают финальные артефакты, которые затем публикуются на сервере или CDN.


output.publicPath

output.publicPath определяет базовый URL, по которому приложение будет обращаться к собранным файлам во время выполнения в браузере.

Если output.path отвечает за файловую систему, то publicPath отвечает за сетевой путь (URL).

Пример:

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/assets/'
  }
};

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

/assets/main.js
/assets/0.chunk.js
/assets/image.png

Разделение ответственности path и publicPath

Важно различать эти параметры:

  • output.path — где файлы физически лежат на диске
  • output.publicPath — откуда браузер их загружает

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


Сценарии использования publicPath

Относительный путь

output: {
  publicPath: './'
}

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

Минус такого подхода — зависимость от текущего URL страницы, что может приводить к ошибкам при роутинге SPA.


Абсолютный путь от корня домена

output: {
  publicPath: '/'
}

Самый распространённый вариант для SPA-приложений. Все ресурсы загружаются от корня домена:

https://example.com/main.js

CDN-адрес

output: {
  publicPath: 'https://cdn.example.com/assets/'
}

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

Это особенно важно для:

  • кеширования статических ресурсов
  • распределённых систем доставки контента
  • ускорения загрузки через географически близкие узлы

Динамический publicPath

В некоторых случаях publicPath нельзя зафиксировать на этапе сборки. Тогда используется runtime-определение:

__webpack_public_path__ = window.CDN_URL;

или:

__webpack_public_path__ = '/assets/';

Это позволяет менять источник загрузки файлов в зависимости от окружения, пользователя или конфигурации сервера.


Влияние на code splitting и чанки

При использовании динамического импорта:

import('./module.js');

Webpack создаёт отдельный чанк. Путь к нему формируется на основе publicPath.

Если publicPath указан неверно, браузер попытается загрузить chunk по неправильному адресу, что приводит к ошибкам:

ChunkLoadError: Loading chunk failed

Взаимодействие с HtmlWebpackPlugin

При генерации HTML-файла через плагин:

new HtmlWebpackPlugin({
  template: './src/index.html'
});

publicPath используется для автоматической вставки <script> и <link> тегов:

<script src="/assets/main.js"></script>

Если publicPath меняется, HTML автоматически адаптируется без ручного редактирования путей.


Поведение в webpack-dev-server

В dev-сервере publicPath определяет виртуальный базовый URL, с которого сервер отдаёт бандлы из памяти.

Пример:

devServer: {
  static: './dist',
  devMiddleware: {
    publicPath: '/assets/'
  }
}

В этом случае ресурсы доступны по:

http://localhost:8080/assets/main.js

При этом физически файлов на диске может не быть — они находятся в памяти.


Особенности работы с изображениями и ассетами

При использовании Asset Modules:

module: {
  rules: [
    {
      test: /\.(png|jpg|svg)$/,
      type: 'asset/resource'
    }
  ]
}

Webpack генерирует URL для каждого файла на основе publicPath:

output: {
  publicPath: '/static/'
}

Результат:

/static/image.hash.png

Если publicPath не задан, используется значение по умолчанию — относительный путь.


Частые ошибки конфигурации

Несовпадение path и publicPath

Файлы физически лежат в /dist, но приложение пытается загрузить их с /assets/, что приводит к 404.

Отсутствие завершающего слэша

publicPath: '/assets' // потенциально проблемный вариант

Webpack может неправильно склеивать пути:

/assetsmain.js

Корректный вариант:

publicPath: '/assets/'

Использование относительного publicPath в SPA

publicPath: './'

При переходе на маршруты вида /dashboard/settings браузер может попытаться загрузить:

/dashboard/assets/main.js

что приводит к ошибкам загрузки.


Взаимосвязь с Hashing и кешированием

При использовании [contenthash]:

output: {
  filename: '[name].[contenthash].js',
  publicPath: '/assets/'
}

формируется стабильная система кеширования:

  • output.path определяет, где хранится файл
  • publicPath определяет, как он доступен извне
  • contenthash обеспечивает уникальность версии

Это позволяет CDN и браузеру эффективно кэшировать ресурсы без конфликтов при обновлениях.


Runtime поведение publicPath

Webpack внедряет механизм подстановки пути прямо в runtime загрузчик модулей. Это влияет на:

  • динамические импорты
  • загрузку CSS чанков
  • загрузку медиа через require/import
  • splitChunks

Любое изменение publicPath напрямую влияет на логику загрузчика, а не только на строки URL в HTML.


Связь с модульной системой Webpack

Внутренний runtime Webpack использует publicPath как базовый префикс:

__webpack_require__.p = "/assets/";

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


Использование в многостраничных приложениях

В MPA-сценариях часто применяются разные publicPath для разных точек входа:

output: {
  publicPath: '/app1/'
}

или через динамическую подмену в зависимости от entry.

Это позволяет размещать несколько приложений в рамках одного домена:

/app1/
/app2/

CDN и многоуровневое распределение

В продакшене часто используется комбинация:

  • output.path: локальная сборка
  • publicPath: CDN URL
output: {
  path: path.resolve(__dirname, 'dist'),
  publicPath: 'https://cdn.example.com/v1/'
}

Это обеспечивает независимость между процессом сборки и инфраструктурой доставки.

При смене CDN достаточно изменить publicPath, не трогая код приложения.


Особенности при SSR (Server Side Rendering)

В серверном рендеринге publicPath должен совпадать с тем, как сервер отдаёт статику клиенту. Несовпадение приводит к тому, что HTML сгенерирован корректно, но клиент не может загрузить JS-бандлы.

В SSR часто используется переменная окружения:

publicPath: process.env.ASSET_PREFIX

что позволяет разделить окружения:

  • локальная разработка
  • staging
  • production CDN