Я часто расстраиваюсь при отладке проблем с конфигурацией. Это приводит к тому, что я совершаю глупые ошибки, бессистемно меняя параметры конфигурации в надежде, что одна из них сработает. Я решил разорвать круговорот и попытаться понять, что происходит. В этой статье я буду называть webpack-dev-server WDS.
Во-первых, следует помнить о трех важных вещах:
- WDS не автоматически перестраивается при изменении файлов конфигурации. Итак, если вы что-то меняете, и кажется, что ничего не меняется, это наблюдение верно
- WDS не просто компилирует ваш пакет, а затем обслуживает его из файлов. Скорее, он хранит ваш пакет в памяти. Это означает, что если вы пытаетесь выяснить, куда направляются ваши скомпилированные файлы, вы не увидите их в каталоге. Чтобы узнать, куда они направляются, перейдите на
localhost:8080/webpack-dev-server
- Ничего не изменилось, хотя вы можете загрузить свой сайт и компиляция прошла успешно? Есть большая вероятность, что вы действительно обслуживаете файлы пакетов, созданные не в WDS. Если вы отлаживаете конфигурацию WDS, удалите файлы встроенного веб-пакета. Таким образом, если ваша конфигурация WDS испорчена, вы не получите никаких ложных срабатываний. Загвоздка в том, что после правильной настройки WDS вам необходимо убедиться, что ваши созданные файлы попадают в нужное место.
Документы слишком расплывчаты? Прочтите код.
Когда меня постоянно расстраивает что-то подобное, я пытаюсь заставить себя понять это на более глубоком уровне. Итак, к первоисточнику.
Больше всего меня сбивает с толку вопрос о том, где, по мнению WDS, находится ваш файл (поскольку вы не можете просто посмотреть каталог), и чем это отличается от обычной сборки.
WDS предоставляет вам эту странную страницу, которая эффективно показывает вам список каталогов ваших созданных файлов.
Похоже, что бизнес этого маршрута - writeDirectory
функция, которая принимает baseUrl
и basePath
. Внизу мы видим, что writeDirectory
вызывается с publicPath
и outputPath
соответственно. Эта функция получает список файлов в basePath и выполняет итерацию по ним, рекурсивно вызывая себя, если один из этих файлов на самом деле является другим каталогом.
Этот фрагмент кода показывает, как на самом деле работают пути WDS, в частности отношения между outputPath и publicPath. Во-первых, некоторые важные части моей конфигурации:
output: { path: path.resolve(__dirname, 'dist'), publicPath: 'dist' }, plugins: [ new HtmlWebpackPlugin({ template: 'public/indexTemplate.html', filename: 'dist/index.html' favicon: 'favicon.ico' }) ], devServer: { historyApiFallback: { index:'index.html', rewrites: [ { from: /list\/*/, to: 'index.html' } ] }, https: false, publicPath: '/dist/' }
Очевидно, что эта конфигурация немного запуталась, но я пришел сюда из более разумной рабочей конфигурации. Как видите, я использую html-webpack-plugin, и именно с этого началась вся эта путаница, потому что это означало, что мне нужно было получить индекс из dist
вместо public
.
Давайте еще раз посмотрим на отображаемую страницу:
Эта первая ссылка, мой пакет, на самом деле указывает на
http://localhost:8080/dist/da2c93b562075b4cbd7a.js
Как dist
туда попал? Что ж..
res.write('<li><a href="'); res.write(baseUrl + item); res.write('">'); res.write(item); res.write('</a></li>');
baseUrl
(помните, это publicPath
) добавляется к URL-адресу, но не к тексту. Если я щелкну по этой ссылке, пакет действительно есть. В этом есть смысл, хотя, если publicPath
был '/'
вместо /dist/
, это означает, что пакет будет построен для dist/bundle.js
, но доступен в WDS в localhost:8080/bundle.js.
Исправляем конфиг
Худшая часть этой конфигурации - это то, что я использовал filename: 'dist/index.html
для html-webpack-plugin
конфигурации. Это означает, что файл действительно доступен по адресу localhost:8080/dist/dist/index.html
. Это может быть особенно запутанным, если вы экспериментируете с конфигурацией, так как в случае publicPath: '/'
у вас будет index.html
, доступный по адресу localhost:8080/dist/index.html
, что почти логично.
Итак, мы удаляем dist
из html-webpack-plugin
filename
, потому что outputPath
уже помещает его в dist/
.
С этим изменением я теперь могу получить доступ к своему встроенному index.html
по адресу localhost:8080/dist/index.html
, что по-прежнему не то, что я хочу, я действительно хочу, чтобы он был по адресу /
. Но если мы вспомним ту строку, в которой создается ссылка, res.write(baseUrl + item)
, зная, что baseUrl
на самом деле publicPath
, это может произойти только тогда, когда WDS publicPath
будет /
.
Успех! Или вроде того. Теперь я получаю index.html
, просто перейдя к localhost:8080/
(который запросит index.html
, потому что index
обладает магическими свойствами). Тем не мение..
html-webpack-plugin
генерирует URL-адрес для пакета, но включает dist
в URL-адрес. Почему?
Оказывается, я изменил только publicPath в WDS. В обоих случаях должно быть /
. Избавьтесь от проблем и не устанавливайте publicPath
в конфигурации WDS.
СПА беды
Хорошо, теперь мы вернулись к проблеме, которая заставила меня изменить все в первую очередь. Когда я перехожу на другую страницу и обновляюсь, я получаю 404 из-за того, что это одностраничное приложение (SPA). Я установил правила перенаправления, но оказалось, что они не работают.
historyApiFallback: { index:'index.html', rewrites: [ { from: /list\/*/, to: 'index.html' } ] }
При запуске WDS он информирует нас о следующем:
Итак, если вывод поступает из /
и 404 возвращается к index.html
, тогда, когда я 404 на localhost:8080/list/1/1
, это должно быть переписано в localhost:8080/index.html
, который действительно загружает страницу. Итак, здесь происходит что-то, что не очевидно из предоставленной информации.
index: 'index.html'
Что в этом плохого? Это относительный путь. Относительно любого URL-адреса, по которому вы сейчас находитесь. Итак, когда появляется 404 для localhost:8080/list/1/1
, мы фактически загружаем localhost:8080/list/1/index.html
. Для меня это действительно было неочевидно. Худшая часть? Если вы посмотрите на запрос на вкладке своей сети, вы не увидите эту попытку перенаправления запроса.
Последняя ошибка
Теперь, когда publicPath
равно /
, html-webpack-plugin
сгенерирует это в вашем index.html
:
<script type="text/javascript" src="/3bf45b6412afeda22cbc.js"></script></body>
Ваш пакет построен для dist
из-за outputPath
, html-webpack-plugin
сообщает браузеру искать его по адресу /
из-за publicPath
. Как с этим справиться? Либо запустите свой сервер с dist
(кажется, имеет смысл), либо используйте другой publicPath
в конфигурации вашего prod webpack. Вам решать.
Это как раз то, что я могу себе представить на данный момент. Если вы найдете что-нибудь, что можно улучшить, я был бы более чем счастлив услышать это.
Наконец, если вам нужен разработчик-фрилансер, я ищу работу. Я специализируюсь на современной веб-разработке с использованием новейших технологий. Я также освежаю свои навыки полного стека и пытаюсь помочь скалолазам подключиться к моему веб-приложению Letclimbstuff.com. Вы можете связаться со мной по адресу [email protected] или на Codementor.