web-dev-qa-db-ja.com

webpack css-loaderが外部スタイルシートのurl()参照内の画像を見つけられない

Node/NPM/Webpackの世界全体は初めてなので、これが明らかな場合はおobviousびします。

Webpackにバンドルされているシンプルなフロントエンドプロジェクトを構築しようとしています。ノードをインストールし、package.jsonファイルを構成しました。ルートディレクトリで「npm start」を実行すると、コンソールからエラーが表示されず、ブラウザで「localhost:3000」に移動して「hello、world」の出力を確認できます。

次のタスクは、次のような画像への参照を含むスタイルシートを含めることです。

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

このように設定すると、webpack-dev-serverを介してイメージを表示できます(Webブラウザーでlocalhost:3000に移動します)が、プロジェクトをビルドすると、イメージへのパスが間違っています。私が何を間違えているのかわからないので、誰かが私の愚かなことを知っていることを期待してStackiverseにこれを投げています。

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"
  }
}

...そして、ここに私の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' }
    ]
}

};

...そして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>

...構成ファイルで参照される「start.js」ファイル:

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

...そして最後に、cssファイル自体の内容:

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

先ほど言ったように、webpack-dev-serverの世界では、イメージへのパスは適切に解決され、DOM要素の背景として表示されます。公開された世界では、ブラウザはファイルを見つけることができないと言っており、Safariのコンソールには不正なファイルパスが明確に表示されています。

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

正しいローカルパスは次のとおりです。

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

明らかに、私は何か間違ったことをしているが、何を理解できない。どんな助けやアドバイスも大歓迎です。

ありがとう!

50
hairbo

わかった...私はちょうどそれを理解しました。問題はwebpack.config.js内の「publicPath」変数にありました。私はこれを持っていました:

publicPath: '/build/'

...振り返ってみると、これは明らかに絶対パスです。代わりにこれが必要でした:

publicPath: './build/'

...これは相対パスです。物事は今動作するようです。

UPDATE:

私はまだWebpackに慣れていないので、これはまだかなり混乱しています。そうは言っても...

私はこれについて間違った方法で行ったと思います。私のWebpackプロジェクトには、プロジェクトのルートにindex.htmlファイルがあり、webpack-dev-serverがヒットするファイルとして、およびビルドがエントリポイントとして使用するファイルとして、それを使用しようとしました。それは頭痛の終わりを引き起こしていなかったし、私が出会った解決策は本当に働いたとは思わない。それから私はこれを見つけました:

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

これにより、テンプレートからindex.htmlページを作成できます。つまり、実際にファイルとして存在する必要はありません。 webpack-dev-serverはその場で作成してメモリに保存し、「build」フォルダーに公開すると、そのフォルダー内にindex.htmlファイルが作成されます。

私がここで提起した問題を処理するための真の「正しい」方法があるかもしれませんが、これは非常にうまくいくようです。

とにかく、これは一種のとりとめのないことです。私はそれが誰かを助けることを願っています、そして/または、これについてもっと知っている誰かがここに来て、私をまっすぐにすることを願っています。

32
hairbo

私が直面したエラーは

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

これは私の問題を解決します:

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]'
    }
  ]}

Webpackを再度実行します。

すべての背景を追加: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

簡単に説明すると、ファイルローダーの機能は、ファイルを新しいパスにコピーし、CSSにそのパスを入れます。私の場合、CSSファイルはパブリックフォルダー内にネストされていますが、ファイルローダーはパブリックのルートに貼り付け、 path = [path]が定義されていても、相対パスを操作します。したがって、これを無効にすると、相対パスの問題が完全に解決され、入れ子になった画像フォルダーが追加されるため、これらのパスも解決するという課題が回避されます。そして、同じ画像の二重コピーは私が必要としないものです。

12
Rahil Lakhani