HtmlWebpackPlugin injeta arquivos de caminho relativo que se quebram ao carregar caminhos de sites não raiz

116

Estou usando o webpack e o HtmlWebpackPlugin para injetar js e css empacotados em um arquivo de modelo html.

new HtmlWebpackPlugin({
   template: 'client/index.tpl.html',
   inject: 'body',
   filename: 'index.html'
}),

E produz o seguinte arquivo html.

<!doctype html>
<html lang="en">
  <head>
    ...
    <link href="main-295c5189923694ec44ac.min.css" rel="stylesheet">
  </head>
  <body>
    <div id="app"></div>
    <script src="main-295c5189923694ec44ac.min.js"></script>
  </body>
</html>

Isso funciona bem ao visitar a raiz do aplicativo localhost:3000/, mas falha quando tento visitar o aplicativo de outra URL, por exemplo, localhost:3000/items/1porque os arquivos agrupados não são injetados com um caminho absoluto. Quando o arquivo html for carregado, ele procurará o arquivo js dentro do /itemsdiretório inexistente porque o react-router ainda não foi carregado.

Como posso fazer com que o HtmlWebpackPlugin injete os arquivos com um caminho absoluto, para que o express os procure na raiz do meu /distdiretório e não em /dist/items/main-...min.js? Ou talvez eu possa alterar meu servidor expresso para solucionar o problema?

app.use(express.static(__dirname + '/../dist'));

app.get('*', function response(req, res) {
  res.sendFile(path.join(__dirname, '../dist/index.html'));
});

Basicamente, eu só preciso pegar a linha:

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

para ter uma barra no início da fonte.

<script src="/main...js></script>
aherriot
fonte

Respostas:

199

Tente definir o publicPath na configuração do seu webpack:

output.publicPath = '/'

HtmlWebpackPlugin usa o publicPath para preceder os urls das injecções.

Outra opção é definir o href de base no <head>de seu modelo html, para especificar o url de base de todos os urls relativos em seu documento.

<base href="http://localhost:3000/">
Magnus Sjungare
fonte
7
Obrigado, adicionar output.publicPath = '/'foi a solução.
aherriot
3
Isso não funcionará se você estiver executando por meio de proxy reverso.
t-my
4
Você também pode usar simplesmente <base href="https://stackoverflow.com/">para evitar a necessidade de codificar o nome do host no modelo HTML ou de interpolar variáveis.
Rafa
Tive que definir publicPath = '' e adicionar <base href = "~ / dist /">, pois meu site é um projeto ASP.Net MVC usando IIS e um diretório virtual.
piada mais urgente
16

Na verdade, eu tive que colocar:

output.publicPath: './';

para que ele funcione em um caminho não-ROOT. Ao mesmo tempo, eu estava injetando:

   baseUrl: './'

para dentro

<base href="<%= htmlWebpackPlugin.options.metadata.baseUrl %>">

Com ambos os parâmetros definidos, funcionou perfeitamente.

Kevin FONTAINE
fonte
Isso mostra o URLnavegador como https://localhost/myproject/%3C%=%20htmlWebpackPlugin.options.baseUrl%20%%3E#/project/1. Existe alguma maneira de resolver isto?
NehaM
Onde você baseUrl: '.'está definindo nas opções HtmlWebpackPlugin? { meta: { baseUrl: './' } }?
Algo em
@SomethingOn Não tenho esse projeto de webpack em mãos agora e acho que muitas coisas mudaram desde que postei esta resposta (incluindo o valor padrão). Portanto, sim, certamente é aqui que deve ser definido, mas './'é o valor correto.
Kevin FONTAINE
1
Agora ele pode injetar tag base diretamente. injetar tag de base
Liang
2

na configuração do webpack

config.output.publicPath = ''

em seu index.html

<base href="/someurl/" />

Isso deve servir.

Hannad Rehman
fonte