Chia sẻ phiên bản tài nguyên của Laravel Blade, Mix và SASS


8

Trong dự án của tôi, tôi sử dụng một số tài nguyên (chủ yếu là hình ảnh) trong cả SASS và Blade. Ngoài ra, tôi có một số tài nguyên chỉ được sử dụng trong SASS và một số tài nguyên chỉ được sử dụng trong Blade.

Ví dụ: tôi có thể sử dụng mix('images/logo.png')trong các tệp Blade và background: url('../images/logo.png')trong các tệp SASS.

Đối với cấu trúc thư mục của tôi, tôi đã làm như sau:

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

Để biên dịch tài nguyên của tôi và đặt chúng vào publicthư mục, tôi sử dụng như sau 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();

Kết quả là tôi nhận được URL đó trong app.css:

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

Trong khi tôi nhận được một cái khác trong HTML được kết xuất:

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

Chúng được coi là 2 tài nguyên khác nhau, đó không phải là điều tôi mong đợi ...

Cách giải quyết tiềm năng

Tôi phát hiện ra rằng các file CSS được tạo ra bởi Sass sử dụng một phiên bản URL ngay cả khi tôi không chỉ định version()trong webpack.mix.js. Vì vậy, tôi đã tự hỏi có lẽ tôi có thể sử dụng một số mẹo, như thế này:

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

Và sử dụng nó trong SASS như vậy:

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

Nhưng giải pháp này có rất nhiều nhược điểm, tôi bắt buộc phải sử dụng versionedchức năng này mỗi lần, mã nguồn của tôi sẽ không hoạt động dễ dàng trong các dự án khác mà không có webpack.mix.jschức năng này và tôi phải chỉnh sửa mọi tệp mà tôi sử dụng trong thư mục tài nguyên của mình để sử dụng chức năng.

Giải pháp nào khác?

Tôi nghĩ rằng nguồn gốc của vấn đề của tôi có thể đến từ cách tôi cấu trúc các tệp của mình, tôi có một resources/imagesthư mục chứa hình ảnh được sử dụng bởi SASS nhưng cũng được sử dụng bởi Blade.
Hình ảnh được sử dụng trong SASS sẽ được sao chép vào public/imagesvì đó là cách SASS hoạt động với webpack và những hình ảnh này cũng sẽ được sao chép lần thứ hai vì tôi đã sử dụng mix.copy()(vì tôi cần các tệp khác ở trong thư mục công cộng để có thể truy cập trong Blade / HTML).

Tôi khá chắc chắn rằng tôi đang nhầm lẫn ở đâu đó, tôi đã tìm trên internet một cách thích hợp để làm việc với các tài nguyên SASS và Blade trong Laravel nhưng tôi không tìm thấy bất cứ điều gì có liên quan.
Có lẽ tôi nên xem xét một cấu trúc tập tin khác? Nhưng cái nào?


1
Tôi muốn đưa ra những suy nghĩ của riêng mình trong khi tôi cũng đang đối mặt với vấn đề tương tự. Laravel Mix xử lý các tệp .blade và CSS / JS khác nhau. Bạn sẽ không nhận được hàm băm tương tự cho hình ảnh logo của mình như đối với các tài sản .blade mà nó sử dụng mix.version()và cho các tệp CSS, có trình tải tệp riêng với chức năng băm riêng. Nó không có gì chung với cấu trúc tập tin. Giải pháp đề xuất của bạn dường như là một lựa chọn tốt, tôi không nghĩ có một giải pháp riêng cho vấn đề này.
Svyat

Câu trả lời:


2

Tôi phát hiện ra rằng các tệp CSS được tạo bởi SASS sử dụng URL được phiên bản ngay cả khi tôi không chỉ định phiên bản () trong webpack.mix.js.

Viết lại url()trong các bảng định kiểu là một tính năng gói web , nó nối thêm hàm băm MD5 được tính toán của tệp vào URL. mix.version()mặt khác tạo ra một hàm băm khác nhờ các dòng đó:

/**
 * 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 đọc tệp dưới dạng một chuỗi (không phải là bộ đệm), băm nó và chỉ trích xuất 20 ký tự đầu tiên. Tôi không thể tìm ra một cách đơn giản để ghi đè hành vi này, một cách giải quyết nhanh và bẩn là xác định lại hashchức năng:

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

Một cách tốt hơn là mở rộng Laravel Mix và xác định versionMD5()phương thức của riêng bạn, bạn có thể sao chép một số mã từ tiện ích mở rộng này .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.