HtmlWebpackPlugin injecte des fichiers de chemin relatif qui se cassent lors du chargement de chemins de site Web non root

115

J'utilise webpack et le HtmlWebpackPlugin pour injecter js et css groupés dans un fichier de modèle html.

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

Et il produit le fichier html suivant.

<!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>

Cela fonctionne bien lorsque vous visitez la racine de l'application localhost:3000/, mais échoue lorsque j'essaie de visiter l'application à partir d'une autre URL, par exemple, localhost:3000/items/1car les fichiers regroupés ne sont pas injectés avec un chemin absolu. Lorsque le fichier html est chargé, il recherchera le fichier js dans le /itemsrépertoire non-exist car react-router n'a pas encore été chargé.

Comment puis-je demander à HtmlWebpackPlugin d'injecter les fichiers avec un chemin absolu, afin qu'Express les recherche à la racine de mon /distrépertoire et non à /dist/items/main-...min.js? Ou peut-être puis-je modifier mon serveur express pour contourner le problème?

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

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

Essentiellement, j'ai juste besoin d'obtenir la ligne:

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

pour avoir une barre oblique au début de la source.

<script src="/main...js></script>
aherriot
la source

Réponses:

199

Essayez de définir le publicPath dans votre configuration Webpack:

output.publicPath = '/'

HtmlWebpackPlugin utilise le publicPath pour ajouter les URL des injects.

Une autre option consiste à définir le href de base dans le <head>de votre modèle html, pour spécifier l'url de base de toutes les URL relatives de votre document.

<base href="http://localhost:3000/">
Magnus Sjungare
la source
7
Merci, l'ajout output.publicPath = '/'était la solution.
aherriot le
3
Cela ne fonctionnera pas si vous utilisez un proxy inverse.
t-my
4
Vous pouvez également utiliser simplement <base href="https://stackoverflow.com/">pour éviter d'avoir à coder en dur le nom d'hôte dans le modèle HTML ou d'interpoler des variables.
Rafa
J'ai dû définir publicPath = '' et ajouter <base href = "~ / dist /"> car mon site est un projet ASP.Net MVC utilisant IIS et un répertoire virtuel.
blague plus urgente
16

En fait, je devais mettre:

output.publicPath: './';

afin de le faire fonctionner dans un chemin non ROOT. En même temps, je m'injectais:

   baseUrl: './'

dans

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

Avec les deux paramètres définis, cela a fonctionné comme un charme.

Kevin FONTAINE
la source
Cela montre URLle navigateur sur https://localhost/myproject/%3C%=%20htmlWebpackPlugin.options.baseUrl%20%%3E#/project/1. Est-ce qu'il y a un moyen de résoudre ceci?
NehaM
Où le définissez baseUrl: '.'-vous dans les options HtmlWebpackPlugin? { meta: { baseUrl: './' } }?
SomethingOn
@SomethingOn Je n'ai pas ce projet webpack sous la main pour le moment, et je pense que beaucoup de choses ont changé depuis que j'ai publié cette réponse (y compris la valeur par défaut). Alors oui, c'est certainement là qu'il doit être défini, mais './'c'est la valeur correcte.
Kevin FONTAINE
1
Maintenant, il peut injecter directement la balise de base. injecter la balise de base
Liang
2

dans la configuration du webpack

config.output.publicPath = ''

dans votre index.html

<base href="/someurl/" />

cela devrait le faire.

Hannah Rehman
la source