web-dev-qa-db-ja.com

Webpack [url / file-loader]はURLの相対パスを解決していません

相対パスに関するWebpackの問題に直面しています。シナリオを説明してみましょう:

Workspace directoryに2つの個別のプロジェクトがあります:

  1. Project-A [Gulpを使用したバンドル]:安定して動作している
  2. Project-B [Webpackを使用したバンドル]:新しいプロジェクト

両方のプロジェクトで同じスタイリングを使用しているため、のSCSSファイル[標準変数、事前定義されたレイアウト、モーダル、クラスなどで構成される]を再利用したかったので、プロジェクトAプロジェクトB

enter image description here

ここで、Project-B index.scssにProject-A index.scssを別のパーシャルとしてインポートしようとしている場合[背景画像のURLの依存性をコメントアウト]、webpackは必要なCSS出力ファイルを生成します。

// Import Project A SCSS [Common Varibles, Classes, Styling etc] 
@import "../../../../Project_A/assets/stylesheets/index";

しかし、Project-Aのindex.scssがそれぞれの相対パスから背景画像をさらに参照しているため、webpackビルドがエラーをスローしています

「ファイル/ディレクトリがXYZ/Project-B/Source/Stylesheetsに見つかりません」。

正確なエラーブロック:

./src/assets/stylesheets/index.scssでのエラーモジュールのビルドに失敗しました:ModuleNotFoundError:モジュールが見つかりません:エラー: 'file'または 'diWorkSpace\Project_B\src\assets\stylesheetsを解決できません

スクリーンショット: **enter image description here**

WebpackがProject-A内のアセットの相対パスを解決できず、「Project B」内をまだ確認できない理由を理解できません

これが、シミュレートされた問題のコードリポジトリURLです。 https://github.com/raviroshan/webpack-build-issue/tree/master/WorkSpace

再現手順

  1. リポジトリをダウンロードします。
  2. Project_Bフォルダー内を参照し、NPMインストールを実行します。
  3. 「webpack」を実行します。相対画像のURLコードがコメント化されているため、正しくビルドされます。
  4. コードのコメント行を元に戻します: https://github.com/raviroshan/webpack-build-issue/blob/master/WorkSpace/Project_A/assets/stylesheets/index.scss#L27
11
Ravi Roshan

それで、最後に、多くの苦労の後、適切な[〜#〜]ソリューション[〜#〜]を得ました。

CSSローダーの問題であることが判明しました。つまり、現在のファイルに対応するURLを解決できません。

resolve-url-loaderを使用してこの問題を解決しました。 https://www.npmjs.com/package/resolve-url-loader

 // Old Loader Config in Webpack-entry
 loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!sass-loader?sourceMap')

 // New [Fixed] Loader Config in Webpack-entry
 loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!resolve-url-loader!sass-loader?sourceMap')

これが更新されたコードレポとソリューションです: https://github.com/raviroshan/webpack-build-issue

:-loaderを省略しないでくださいWebpack.config.jsは常に長い形式のローダー名(つまり、-loaderサフィックス)を使用する必要があります。

Resolve-urlと呼ばれる別のパッケージがあり、Webpackはresolve-url-loaderと混同できます。

8
Ravi Roshan

css-loaderフォルトで、_@import_とurl()のパスを解決する方法のようです。すべてのパス(インポートされたスタイルシートからのパスも含む)を、メインのCSSファイル(_/Project_B/src/assets/stylesheets/index.scss_)を基準にして解決しようとします。

泣かないで!解決策があります!

多分それは完璧ではないかもしれませんが、私がこれまで持ってきた中で最高のものです。

アセットへのパスを保持するグローバル変数_$assetsPath_を作成します現在のスタイルシートに対して。次に、この変数をすべてのurl()値の前に追加します。

_/Project_A/assets/stylesheets/index.scss_に次のように記述します。

_/*/ Using !default we can override this variable even before the following line: /*/
$assetsPath: '../' !default;

.container {
    /*/ ... /*/
    .content-wrapper {
        /*/ ... /*/
        background-image: url($assetsPath + "images/content-bg.jpg");
    }
}
_

_/Project_B/src/assets/stylesheets/index.scss_に次のように記述します。

_/*/ The following variable will override $assetsPath defined in the imported file: /*/
$assetsPath: '../../../../Project_A/assets/';

/*/ Import Project A SCSS [Common Varibles, Classes, Styling etc] /*/
@import "../../../../Project_A/assets/stylesheets/index";
_

余波

Project-AをGulpにバンドルすると、Project-Aのコードは次のようになります。

_        /*/ ... /*/
        background-image: url("../images/content-bg.jpg");
_

ただし、Project-BをWebpackにバンドルすると、Project-Aのコードは次のようになります。

_        /*/ ... /*/
        background-image: url("../../../../Project_A/assets/images/content-bg.jpg");
_

したがって、あなたは保存されます

間違いなく私はこの問題を詳しく見ていきます。 _url-loader_が_@import_ステートメントのパスを尊重し、それに応じて参照されるアセットにそれを適用する場合は、これらすべてを回避できます。何かが足りないか、バグと見なす必要があります。

素敵な一日をお過ごしください。
〜Wiktor

3
Wiktor Bednarz

ファイルローダーで相対パスを取得するには、publicPathを相対パスとして設定する必要があります。

2
Khalid Azam