web-dev-qa-db-fra.com

webpack css-loader ne trouve pas les images dans la référence url () dans une feuille de style externe

Je suis nouveau dans le monde Node/NPM/Webpack, alors veuillez nous excuser si cela est évident.

J'essaie de construire un simple projet frontal intégré à Webpack. J'ai un noeud installé et un fichier package.json est configuré. Si j'exécute "npm start" dans mon répertoire racine, la console ne génère aucune erreur et je peux accéder à "localhost: 3000" dans un navigateur et voir ma sortie "hello, world".

Ma tâche suivante consiste à inclure une feuille de style, qui contient une référence à une image, comme ceci:

.myimg {background: url(path/to/file.jpg);}

Avec de tels éléments, je peux voir l'image via le serveur webpack-dev-server (en accédant à localhost: 3000 dans un navigateur Web), mais si je construis le projet, le chemin d'accès à l'image est incorrect. Je n'ai aucune idée de ce que je fais de mal, alors je lance ceci au Stackiverse dans l'espoir que quelqu'un sache ce que je fais de stupide.

Voici mon fichier package.json:

{
  "name": "webpack-test1",
  "version": "0.0.1",
  "description": "My project WTF.",
  "private": true,
  "scripts": {
    "start": "node server.js"
  },
  "devDependencies": {
   "css-loader": "^0.15.2",
   "file-loader": "^0.8.4",
   "style-loader": "^0.12.3",
   "url-loader": "^0.5.6"
  },
  "dependencies": {
    "webpack": "^1.9.6",
    "webpack-dev-server": "^1.8.2"
  }
}

... et voici mon fichier webpack.config.js:

var path = require('path');
var webpack = require('webpack');

module.exports = {
  entry: [
    "./src/start.js"
],
output: {
    filename: "bundle.js",
    path: path.join(__dirname, 'build'),
    publicPath: '/build/'
},
module: {
    loaders: [
        { test: /\.css$/, loader: 'style-loader!css-loader' },
        { test: /\.(png|jpg)$/, loader: 'file-loader' }
    ]
}

};

... puis le fichier index.html:

<!doctype html>
<html>
<head>
    <title>Webpack Test</title>
</head>

<body>
    <div class="imgtest">hello, world</div>
    <script src="build/bundle.js"></script>
</body>
</html>

... le fichier "start.js" référencé dans le fichier de configuration:

require('./test.css');
console.log("y u no work?");

... et enfin, le contenu du fichier css lui-même:

.imgtest { background: url(img/volcano.jpg);}

Comme je l'ai dit plus haut dans Webpack-dev-server world, le chemin d'accès à l'image est résolu correctement et s'affiche en tant qu'arrière-plan de l'élément DOM. Dans le monde publié, le navigateur me dit qu'il ne trouve pas le fichier, la console de Safari indiquant clairement un chemin de fichier incorrect:

http://localhost/build/1b05d814aa13ac035c6b122b9f5974f8.jpg

Le chemin local correct est le suivant:

http://localhost/~username/webpack1/build/1b05d814aa13ac035c6b122b9f5974f8.jpg

Clairement, je fais quelque chose de mal, mais je ne peux pas comprendre quoi. Toute aide ou conseil est apprécié.

Merci!

50
hairbo

Ok… euh. Je viens de le comprendre. Le problème était avec la variable "publicPath" dans webpack.config.js. J'ai eu ceci:

publicPath: '/build/'

... ce qui, rétrospectivement, est évidemment un chemin absolu. Ce dont j'avais besoin à la place était ceci:

publicPath: './build/'

... qui est un chemin relatif. Les choses semblent fonctionner maintenant.

UPDATE:

Je suis encore très nouveau sur Webpack, donc tout cela reste assez déroutant. Ayant dit cela...

Je pense que j'ai mal agi. Mon projet Webpack a un fichier index.html à la racine du projet et j'essayais de l'utiliser aussi bien comme fichier que le serveur webpack-dev-server tapait ET ce que la construction utiliserait comme point d'entrée. Cela me causait des maux de tête sans fin, et je ne pense pas que la solution à laquelle je suis tombée ait réellement fonctionné. Puis j'ai trouvé ceci:

https://www.npmjs.com/package/html-webpack-plugin

Cela vous permet de créer votre page index.html à partir d'un modèle, ce qui signifie qu'il n'est pas nécessaire qu'elle existe sous forme de fichier. webpack-dev-server le crée à la volée et le stocke en mémoire. Lorsque vous publiez dans votre dossier "build", un fichier index.html est créé dans ce dossier.

Il y a peut-être une vraie "bonne" façon de traiter le problème que j'ai soulevé ici, mais cela semble fonctionner vraiment très bien, et d'une manière détournée, cela résout mes problèmes, car cela élimine toute la question du chemin.

Quoi qu'il en soit, c'est un peu décousu. J'espère que cela aidera quelqu'un et/ou j'espère que quelqu'un qui en sait plus à ce sujet vient ici et me met tout de suite.

32
hairbo

L'erreur que j'avais rencontrée était

Module parse failed: PATH:\TO\IMG\XYZ.PNG  Unexpected character '�' (1:0)
 You may need an appropriate loader to handle this file type.
 SyntaxError: Unexpected character '�' (1:0)

.
.
.
.
.
@ ./~/css-loader!./~/sass-loader!./node/static/sass/style.scss 6:399692-399747

Cela résout mon problème:

module: {
.
.
.,{
       test: /\.scss$/,
       exclude: /node_modules/,
       loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader"),
       root: path.resolve('./node/static/sass')
   },
   {
     test: /\.(jpe?g|gif|png)$/,
     loader: 'file-loader?emitFile=false&name=[path][name].[ext]'
    }
  ]}

Exécutez votre webpack à nouveau.

Ajouter tout le fond: url('~/../somePath/toImage.png');

> [email protected] react-build PATH:\TO\PROJECT
> webpack --watch --display-error-details --display-cached --content-base ./

Hash: f6e4cbbf0068b5792247
Version: webpack 1.13.2
Time: 4882ms
         Asset    Size  Chunks             Chunk Names
  js/bundle.js  760 kB       0  [emitted]  main
css/bundle.css  393 kB       0  [emitted]  main
    + 180 hidden modules
Child extract-text-webpack-plugin:
        + 76 hidden modules

pour expliquer en bref, ce que fait le chargeur de fichiers - il copie le fichier dans un nouveau chemin et le place dans le css, car, dans mon cas, le fichier CSS était imbriqué dans un dossier public, alors que le chargeur le collait à la racine du public, avec path = [path] défini, il faudrait toujours manipuler le chemin relatif. Ainsi, le fait de désactiver cette fonction résout complètement mon problème de chemins relatifs et d'ajouter que j'ai un dossier d'images imbriquées, cela évite également le problème de la résolution de ces chemins. Et la double copie des mêmes images est quelque chose dont je n’ai pas besoin.

12
Rahil Lakhani