Как указать серверу webpack для обслуживания index.html для любого маршрута


148

React router позволяет реагировать на приложения /arbitrary/route. Чтобы это работало, мне нужен мой сервер для отправки приложения React по любому подходящему маршруту.

Но сервер разработки веб-пакетов не обрабатывает произвольные конечные точки.

Здесь есть решение с использованием дополнительного экспресс-сервера. Как разрешить для webpack-dev-server разрешать точки входа из реагирующего маршрутизатора

Но я не хочу запускать другой экспресс-сервер, чтобы разрешить сопоставление маршрутов. Я просто хочу сказать, что webpack dev server должен совпадать с любым URL-адресом и отправить мне свое приложение реакции. Пожалуйста.



Ответы:


169

Я нашел самое простое решение, чтобы включить небольшой конфиг:

  devServer: {
    port: 3000,
    historyApiFallback: {
      index: 'index.html'
    }
  }

Я нашел это, посетив: PUSHSTATE С WEBPACK-DEV-SERVER .


18
Вы также можете использовать его в качестве опции CLI:--history-api-fallback
VonD

7
Мне пришлось использовать что-то подобное с более новой версией 2.devServer: { port: 3000, historyApiFallback: true },
Адриан Моиза

1
На самом деле вы должны использовать опцию cli «--history-api-fallback» и в конфигурации вашего сервера dev веб-пакетов установить разрешение для файла индекса, как описано выше в этом ответе.
Jc Figueroa

86

Параметр historyApiFallback в официальной документации для webpack-dev-server четко объясняет, как этого можно добиться, используя

historyApiFallback: true

который просто возвращается к index.html, когда маршрут не найден

или

// output.publicPath: '/foo-app/'
historyApiFallback: {
  index: '/foo-app/'
}


Но на самом деле webpack-dev-server сейчас в обслуживании. Его преемником является github.com/webpack-contrib/…a , который поддерживаетhistoryApiFallback
jacob

3
Для любого, кто читает это в 2019 году, согласно github.com/webpack-contrib/webpack-serve#webpack-serve webpack-dev-server является преемником webpack-serve, а не наоборот, как упомянуто в stackoverflow.com/questions/31945763/… .
ur5us

Комментарий ur5us на самом деле неверен. webpack-serve был запланированным преемником webpack-dev-server. Я автор webpack-serve и бывший разработчик webpack-dev-server. когда я взял отпуск, горькие члены оргкомитета осудили webpack-serve, и с тех пор я выпустил его под свою ветвь.
shellscape

23

Добавление общедоступного пути в конфигурацию помогает webpack понять настоящий root ( /), даже когда вы находитесь в подпроцессах, например./article/uuid

Поэтому измените конфигурацию вашего веб-пакета и добавьте следующее:

output: {
    publicPath: "/"
}

devServer: {
    historyApiFallback: true
}

Без publicPathресурсов не может быть загружен должным образом, только index.html.

Проверено на Webpack 4.6

Большая часть конфига (просто для лучшей картинки):

entry: "./main.js",
output: {
  publicPath: "/",
  path: path.join(__dirname, "public"),
  filename: "bundle-[hash].js"
},
devServer: {
  host: "domain.local",
  https: true,
  port: 123,
  hot: true,
  contentBase: "./public",
  inline: true,
  disableHostCheck: true,
  historyApiFallback: true
}

Вау, это сработало и для меня! historyApiFallbackТрюк работал только для последней части URL по некоторым причинам. /testбудет работать, но /test/testдаст 404.
Алекс. P.

В дополнение к historyApiFallback: {index: '/'} или historyApiFallback: true(оба работали для меня), настройка publicPathбыла также необходима в моем случае (Маршрутизатор 5.2).
Маркус Юний Брут

17

У меня так работает

devServer: {
    contentBase: "./src",
    hot: true,
    port: 3000,
    historyApiFallback: true

},

Работа над приложением по борьбе с беспорядками


14

Моя ситуация была немного другой, так как я использую угловой CLI с webpack и опцию 'eject' после выполнения команды ng eject . Я изменил извлеченный скрипт npm для 'npm start' в package.json, чтобы передать флаг --history-api-fallback

"start": "webpack-dev-server --port = 4200 --history-api-fallback "

"scripts": {
"ng": "ng",
"start": "webpack-dev-server --port=4200 --history-api-fallback",
"build": "webpack",
"test": "karma start ./karma.conf.js",
"lint": "ng lint",
"e2e": "protractor ./protractor.conf.js",
"prepree2e": "npm start",
"pree2e": "webdriver-manager update --standalone false --gecko false --quiet",
"startold": "webpack-dev-server --inline --progress --port 8080",
"testold": "karma start",
"buildold": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"},

6

Если вы решите использовать webpack-dev-server, вы не должны использовать его для обслуживания всего приложения React. Вы должны использовать его, чтобы служить вашимbundle.js файла, а также для статических зависимостей. В этом случае вам потребуется запустить 2 сервера, один для точек входа Node.js, которые фактически будут обрабатывать маршруты и обслуживать HTML, а другой - для пакета и статических ресурсов.

Если вы действительно хотите использовать один сервер, вы должны прекратить использование webpack-dev-serverи начать использовать webpack-dev-middleware на вашем сервере приложений. Он будет обрабатывать пакеты «на лету» (я думаю, что он поддерживает кеширование и оперативную замену модулей) и гарантирует, что ваши вызовы bundle.jsвсегда будут актуальными.


2
Я использую webpack-dev-server только для разработки горячих перезагрузок исходных карт и т. Д. В противном случае у меня есть статический веб-сайт, где я могу разместить файлы из любого места.
eguneys

3

Вы можете включить historyApiFallbackобслуживание index.htmlвместо ошибки 404, если в этом месте не найден другой ресурс.

let devServer = new WebpackDevServer(compiler, {
    historyApiFallback: true,
});

Если вы хотите обслуживать разные файлы для разных URI, вы можете добавить основные правила перезаписи к этой опции. index.htmlБудет по- прежнему служили для других путей.

let devServer = new WebpackDevServer(compiler, {
    historyApiFallback: {
        rewrites: [
            { from: /^\/page1/, to: '/page1.html' },
            { from: /^\/page2/, to: '/page2.html' },
            { from: /^\/page3/, to: '/page3.html' },
        ]
    },
});

2

Я знаю, что этот вопрос для webpack-dev-server, но для всех, кто использует webpack-serve 2.0. с веб-пакетом 4.16.5 ; webpack-serve позволяет добавлять дополнения. Вам нужно создать serve.config.js:

const serve = require('webpack-serve');
const argv = {};
const config = require('./webpack.config.js');

const history = require('connect-history-api-fallback');
const convert = require('koa-connect');

serve(argv, { config }).then((result) => {
  server.on('listening', ({ server, options }) => {
      options.add: (app, middleware, options) => {

          // HistoryApiFallback
          const historyOptions = {
              // ... configure options
          };

          app.use(convert(history(historyOptions)));
      }
  });
});

Ссылка

Вам нужно будет изменить скрипт разработки с webpack-serveна node serve.config.js.


2

Для меня у меня были точки "." на моем пути, например, /orgs.csvпоэтому я должен был поместить это в мой веб-пакет Confg

devServer: {
  historyApiFallback: {
    disableDotRule: true,
  },
},

0

Я согласен с большинством существующих ответов.

Одна ключевая вещь, которую я хотел бы упомянуть, - если вы сталкиваетесь с проблемами при ручной перезагрузке страниц по более глубоким путям, где он сохраняет все, кроме последнего раздела пути, и привязывает к имени jsфайла вашего пакета, вам, вероятно, понадобится дополнительная настройка (особенно publicPathнастройка ).

Например, если у меня есть путь, /foo/barи мой пакетный файл называется bundle.js. Когда я пытаюсь вручную обновить страницу, я получаю сообщение 404, /foo/bundle.jsкоторое не может быть найдено. Интересно, что если вы попытаетесь перезагрузить с пути, /fooвы не увидите никаких проблем (это потому, что резервный обрабатывает его).

Попробуйте использовать нижеприведенное в сочетании с существующей webpackконфигурацией, чтобы решить эту проблему. output.publicPathэто ключевой элемент!

output: {
    filename: 'bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'public')
},
...
devServer: {
    historyApiFallback: true
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.