Laravel Совместное использование версий Blade, Mix и SASS - PullRequest
8 голосов
/ 15 апреля 2020

В моем проекте я использую некоторые ресурсы (в основном, изображения) как в SASS, так и в Blade. Кроме того, у меня есть некоторые ресурсы, используемые только в 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();

В результате я получаю этот URL в приложении. css:

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

В то время как я получаю другой в отображаемом HTML:

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

Они рассматриваются как 2 разных ресурса, это не то, что я ожидал ...

Потенциальный обходной путь

Я обнаружил, что CSS файлы, генерируемые SASS, используют версионный 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, будут скопированы в public/images, потому что именно так SASS работает с веб-пакетом, и эти изображения также будут скопированы во второй раз, потому что я использовал mix.copy() (потому что мне нужно другие файлы должны быть в папке publi c, чтобы быть доступными в Blade / HTML).

Я почти уверен, что где-то ошибаюсь, я искал inte rnet для правильного способа работы с ресурсами SASS и Blade в Laravel, но я не нашел ничего подходящего.
Может мне стоит рассмотреть другую файловую структуру? Но какой?

1 Ответ

2 голосов
/ 21 апреля 2020

Я обнаружил, что CSS файлы, созданные SASS, используют версионный URL, даже если я не указываю version () в webpack.mix. js.

Перезапись url() в таблицах стилей - это функция веб-пакета , которая добавляет вычисленный MD5 га sh файла к URL-адресу. mix.version() с другой стороны генерирует другое га sh благодаря этим строкам:

/**
 * 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(), вы можете скопировать некоторый код из этого расширения .

...