Freigabe von Laravel Blade-, Mix- und SASS-Ressourcenversionen

8

In meinem Projekt verwende ich einige Ressourcen (hauptsächlich Bilder) sowohl in SASS als auch in Blade. Außerdem habe ich einige Ressourcen, die nur in SASS verwendet werden, und einige, die nur in Blade verwendet werden.

Zum Beispiel könnte ich mix('images/logo.png')in Blade-Dateien und background: url('../images/logo.png')in SASS-Dateien verwenden.

In Bezug auf meine Verzeichnisstruktur habe ich Folgendes getan:

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

Um meine Ressourcen zu kompilieren und in den publicOrdner zu legen, gehe ich wie folgt vor 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();

Im Ergebnis erhalte ich diese URL in app.css:

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

Während ich einen anderen in gerendertem HTML bekomme:

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

Sie werden als 2 verschiedene Ressourcen betrachtet, das habe ich nicht erwartet ...

Mögliche Problemumgehung

Ich entdeckte , dass CSS - Dateien von SASS Verwendung erzeugt eine versionierte URL , auch wenn ich nicht angeben , version()in webpack.mix.js. Also habe ich mich gefragt, ob ich vielleicht einen Trick wie diesen gebrauchen könnte:

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
    });

Und verwenden Sie es in SASS wie folgt:

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

Diese Lösung hat jedoch viele Nachteile: Ich muss die versionedFunktion jedes Mal verwenden, mein Quellcode funktioniert in anderen Projekten ohne die webpack.mix.jsFunktion nicht einfach und ich muss alle Dateien bearbeiten, die ich in meinem Ressourcenordner verwende, um sie zu verwenden die Funktion.

Andere Lösung?

Ich denke, die Ursache meines Problems könnte in der Art und Weise liegen, wie ich meine Dateien strukturiert habe. Ich habe einen resources/imagesOrdner, der Bilder enthält, die von SASS, aber auch von Blade verwendet werden.
In SASS verwendete Bilder werden kopiert, public/imagesda SASS auf diese Weise mit Webpack funktioniert, und diese Bilder werden auch ein zweites Mal kopiert, weil ich sie verwendet habe mix.copy()(da sich die anderen Dateien im öffentlichen Ordner befinden müssen, um in Blade zugänglich zu sein / HTML).

Ich bin mir ziemlich sicher, dass ich mich irgendwo irre. Ich habe im Internet nach einer geeigneten Möglichkeit gesucht, mit SASS- und Blade-Ressourcen in Laravel zu arbeiten, aber ich habe nichts Relevantes gefunden.
Vielleicht sollte ich eine andere Dateistruktur in Betracht ziehen? Aber welcher ?

Marc
quelle
1
Ich möchte meine eigenen Gedanken äußern, während ich mich dem gleichen Problem stelle. Laravel Mix behandelt .blade- und CSS / JS-Dateien unterschiedlich. Sie erhalten nicht den gleichen Hash für Ihr Logo-Bild wie für .blade-Assets, die es verwendet, mix.version()und für CSS-Dateien gibt es einen eigenen File Loader mit eigener Hashing-Funktion. Es hat nichts mit der Dateistrukturierung zu tun. Ihre vorgeschlagene Problemumgehung scheint eine gute Option zu sein. Ich glaube nicht, dass es eine native Lösung für dieses Problem gibt.
Svyat

Antworten:

2

Ich habe festgestellt, dass von SASS generierte CSS-Dateien eine versionierte URL verwenden, auch wenn ich in webpack.mix.js keine version () angegeben habe.

Das Umschreiben url()in Stylesheets ist eine Webpack-Funktion , bei der der berechnete MD5-Hash der Datei an die URL angehängt wird. mix.version()Auf der anderen Seite wird dank dieser Zeilen ein anderer Hash generiert :

/**
 * 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 liest die Datei als Zeichenfolge (nicht als Puffer), hasht sie und extrahiert nur die ersten 20 Zeichen. Ich kann keinen einfachen Weg finden, um dieses Verhalten zu überschreiben. Eine schnelle und schmutzige Problemumgehung ist die Neudefinition der hashFunktion:

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

Eine bessere Möglichkeit besteht darin , Laravel Mix zu erweitern und Ihre eigene versionMD5()Methode zu definieren. Möglicherweise kopieren Sie Code aus dieser Erweiterung .

Rasierer
quelle