Laravelブレード、ミックス、SASSリソースのバージョン管理の共有


8

私のプロジェクトでは、SASSとブレードの両方でいくつかのリソース(主にイメージ)を使用しています。また、SASSでのみ使用されるリソースと、Bladeでのみ使用されるリソースがあります。

たとえばmix('images/logo.png')、Bladeファイルやbackground: url('../images/logo.png')SASSファイルで使用できます。

私のディレクトリ構造に関しては、私は次のことをしました:

- resources
    - js
    - sass
    - images  // All images used by Blade, Sass, or both
    - fonts

リソースをコンパイルしてpublicフォルダーに配置するには、以下を使用しますwebpack.mix.js

mix.copy('resources/images/**/*.*', 'public/images');
mix.copy('resources/fonts/**/*.*', 'public/fonts');
mix.version('public/images/**/*.*');
mix.version('public/fonts/**/*.*');

mix.js('resources/js/app.js', 'public/js')
    .js('resources/js/vendor.js', 'public/js')
    .scripts([ // Old not ES6 JS
        'resources/js/tpl/core.min.js'
    ], 'public/js/core.min.js')
    .sass('resources/sass/app.scss', 'public/css')
    .sourceMaps()
    .version();

その結果、app.cssでそのURLを取得します。

background: url(/images/logo.png?0e567ce87146d0353fe7f19f17b18aca);

レンダリングされたHTMLで別のものを取得している間:

src="/images/logo.png?id=4d4e33eae039c367c8e9"

それらは2つの異なるリソースと見なされ、それは私が期待したものではありません...

潜在的な回避策

SASSによって生成されたCSSファイルは、で指定しなくても、バージョン付きURLを使用することを発見しversion()ましたwebpack.mix.js。だから私は多分私はこのようにいくつかのトリックを使うことができるのではないかと思っていました:

const sass = require('sass');

// Custom SASS function to get versioned file name
// Uses Mix version md5 hash
const functions = {
    'versioned($uri)': function(uri, done) {
        uri = uri && uri.getValue() || uri;
        const version = File.find(path.join(Config.publicPath, uri)).version();
        done(new sass.types.String(`${uri}?id=${version}`));
    }
};

mix.sass('resources/sass/all.scss', 'public/css', { 
        sassOptions: {
            functions
        }
    })
    .options({ // Do not process URLs anymore
        processCssUrls: false
    });

そして、SASSで次のように使用します。

background-image: url(versioned('/images/logo.png'));

しかし、このソリューションには多くの欠点があり、versioned関数を毎回使用する義務があります。ソースコードはwebpack.mix.js関数のない他のプロジェクトでは簡単に機能せず、使用するためにリソースフォルダーで使用するすべてのファイルを編集する必要があります関数。

他の解決策?

私の問題の原因は、ファイルを構造化した方法にあると思いますresources/images。SASSで使用されているが、Bladeでも使用されている画像を含むフォルダーがあります。
SASSで使用される画像は、SASSがpublic/imagesWebpackで動作する方法であるためコピーされます。また、これらの画像は、私が使用したためにもう一度コピーされmix.copy()ます(Bladeでアクセスするには、他のファイルをパブリックフォルダー内に置く必要があるためです) / HTML)。

LaravelでSASSおよびBladeリソースを操作する適切な方法をインターネットで調べましたが、関連するものは何も見つかりませんでした。
多分私は別のファイル構造を検討する必要がありますか?しかし、どれ?


1
私も同じ問題に直面している間、自分の考えを伝えたいです。Laravel Mixは.bladeファイルとCSS / JSファイルを異なる方法で処理します。ロゴ画像ではmix.version()、使用する.bladeアセットと同じハッシュを取得できません。CSSファイルには、独自のハッシュ関数を備えた独自のファイルローダーがあります。ファイルの構造化との共通点はありません。あなたの提案された回避策は良いオプションのようです、私はこの問題のネイティブな解決策はないと思います。
Svyat

回答:


2

SASSによって生成されたCSSファイルは、webpack.mix.jsでversion()を指定しなくても、バージョン付きのURLを使用することを発見しました。

url()スタイルシート内での書き換えはWebpack機能であり、ファイルの計算されたMD5ハッシュをURLに追加します。mix.version()一方、これらの行のおかげで別のハッシュが生成されます:

/**
 * Read the file's contents.
 */
read() {
    return fs.readFileSync(this.path(), 'utf8');
}

/**
 * Calculate the proper version hash for the file.
 */
version() {
    return md5(this.read()).substr(0, 20);
}

Laravel Mixはファイルを(バッファーとしてではなく)文字列として読み取り、ハッシュして最初の20文字のみを抽出します。この動作をオーバーライドする簡単な方法を理解できません。hash関数を再定義することで、すばやく簡単に回避できます。

const mix = require('laravel-mix');
let md5 = require('md5');
let fs = require('fs-extra');

Mix.manifest.hash = function (file) {
    let f = new File(path.join(Config.publicPath, file));

    let hash = md5(fs.readFileSync(f.path()));

    let filePath = this.normalizePath(file);

    this.manifest[filePath] = filePath + '?' + hash;

    return this;
}

より良い方法は、Laravel Mix拡張して独自のversionMD5()メソッドを定義することです。この拡張からコードをコピーする場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.