Como dizer ao servidor de desenvolvimento webpack para servir index.html para qualquer rota

148

O roteador de reação permite que os aplicativos de reação sejam manipulados /arbitrary/route. Para que isso funcione, preciso que meu servidor envie o aplicativo React em qualquer rota correspondente.

Mas o servidor de desenvolvimento webpack não lida com pontos finais arbitrários.

Há uma solução aqui usando servidor expresso adicional. Como permitir que o webpack-dev-server permita pontos de entrada do react-router

Mas não quero iniciar outro servidor expresso para permitir a correspondência de rota. Eu só quero dizer ao servidor de desenvolvimento webpack para corresponder a qualquer URL e me enviar meu aplicativo de reação. por favor.

eguneys
fonte

Respostas:

169

Encontrei a solução mais fácil para incluir uma pequena configuração:

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

Encontrei isso visitando: PUSHSTATE WITH WEBPACK-DEV-SERVER .

cmfolio
fonte
18
você também pode usá-lo como uma opção CLI:--history-api-fallback
VonD 5/17
7
Eu tive que usar algo como isto com a mais recente versão 2.devServer: { port: 3000, historyApiFallback: true },
Adrian Moisa
1
De fato, você precisa usar a opção cli "--history-api-fallback" e, na configuração do servidor de desenvolvimento webpack, defina a resolução para o arquivo de índice, conforme descrito nesta resposta acima.
JC Figueroa
86

A opção historyApiFallback na documentação oficial do webpack-dev-server explica claramente como você pode obter isso usando

historyApiFallback: true

que simplesmente retorna ao index.html quando a rota não é encontrada

ou

// output.publicPath: '/foo-app/'
historyApiFallback: {
  index: '/foo-app/'
}
GG
fonte
Mas, na verdade, o webpack-dev-server está em manutenção agora. É do sucessor é github.com/webpack-contrib/... , que suportahistoryApiFallback
jacob
3
Para quem estiver lendo isso em 2019, de acordo com github.com/webpack-contrib/webpack-serve#webpack-serve, webpack-dev-server será o sucessor webpack-serve, e não o contrário, como mencionado em stackoverflow.com/questions/31945763/… .
ur5us 11/01/19
O comentário de ur5us é realmente falso. O webpack-serve foi o sucessor planejado do webpack-dev-server. Sou o autor do webpack-serve e antigo mantenedor do webpack-dev-server. quando tirei um tempo de folga, os membros da organização amarga preteriram o webpack-serve e, desde então, o libertei.
shellscape 18/03/19
23

Adicionar caminho público à configuração ajuda o webpack a entender o root ( /) real, mesmo quando você está em sub-roteiros, por exemplo./article/uuid

Portanto, modifique sua configuração do webpack e adicione o seguinte:

output: {
    publicPath: "/"
}

devServer: {
    historyApiFallback: true
}

Sem publicPathrecursos, pode não ser carregado corretamente, apenas index.html.

Testado no Webpack 4.6

Parte maior da configuração (apenas para ter uma imagem melhor):

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
}
Jurosh
fonte
Uau, isso funcionou para mim também! O historyApiFallbacktruque só funcionou para a última parte do URL por algum motivo. /testfuncionaria, mas /test/testdaria 404.
Alex. P.
Além de historyApiFallback: {index: '/'} ou historyApiFallback: true(ambos funcionaram para mim), definir o publicPathtambém foi essencial no meu caso (roteador 5.2).
Marcus Junius Brutus
17

Funciona para mim assim

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

},

Trabalhando no aplicativo anti-motim

user2088033
fonte
14

Minha situação era um pouco diferente, pois estou usando a CLI angular com o webpack e a opção 'eject' após executar o comando ng eject . Modifiquei o script npm ejetado para 'npm start' no package.json para passar no sinalizador --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"},
Brandon Søren Culley
fonte
6

Se você optar por usar webpack-dev-server, não deverá usá-lo para veicular todo o aplicativo React. Você deve usá-lo para servir seu bundle.jsarquivo, bem como as dependências estáticas. Nesse caso, você teria que iniciar 2 servidores, um para os pontos de entrada do Node.js., que realmente processam rotas e veiculam o HTML e outro para os recursos estáticos e de pacote configurável.

Se você realmente deseja um servidor único, deve parar de usar o webpack-dev-servere começar a usar o webpack-dev-middleware no servidor de aplicativos. Ele processará os pacotes "on the fly" (acho que suporta o armazenamento em cache e as substituições de módulos quentes) e certifique-se de que suas chamadas bundle.jsestejam sempre atualizadas.

André Pena
fonte
2
Estou usando o webpack-dev-server apenas para o desenvolvimento de mapas de fonte de recarga a quente, etc. Caso contrário, tenho um site estático onde posso hospedar os arquivos de qualquer lugar.
eguneys
3

Você pode ativar historyApiFallbacka index.htmlexibição do erro 404 em vez de nenhum outro recurso neste local.

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

Se você deseja fornecer arquivos diferentes para URIs diferentes, você pode adicionar regras básicas de reescrita a essa opção. O index.htmlainda será servido para outros caminhos.

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

Eu sei que esta pergunta é para o webpack-dev-server, mas para quem usa o webpack-serve 2.0. com webpack 4.16.5 ; O webpack-serve permite complementos.Você precisará criar 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)));
      }
  });
});

Referência

Você precisará alterar o script dev de webpack-servepara node serve.config.js.

yotke
fonte
2

Para mim eu tinha pontos "." no meu caminho, por exemplo, /orgs.csventão eu tive que colocar isso no meu webpack confg.

devServer: {
  historyApiFallback: {
    disableDotRule: true,
  },
},
GentryRiggen
fonte
0

Eu concordo com a maioria das respostas existentes.

Uma coisa importante que eu gostaria de mencionar é que, se você encontrar problemas ao recarregar manualmente as páginas em caminhos mais profundos, onde ele mantém a seção inteira, exceto a última, e o nome do seu jsarquivo de pacote, você provavelmente precisará de uma configuração extra (especificamente a publicPathconfiguração )

Por exemplo, se eu tiver um caminho /foo/bare meu arquivo bundler for chamado bundle.js. Quando tento atualizar manualmente a página, recebo um ditado 404 que /foo/bundle.jsnão pode ser encontrado. Curiosamente, se você tentar recarregar a partir do caminho, /foonão verá problemas (isso ocorre porque o fallback lida com isso).

Tente usar o abaixo em conjunto com a sua webpackconfiguração existente para corrigir o problema. output.publicPathé a peça chave!

output: {
    filename: 'bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'public')
},
...
devServer: {
    historyApiFallback: true
}
O chimpanzé louco
fonte