Laravel刀片、Mix和SASS资源版本控制共享

Laravel刀片、Mix和SASS资源版本控制共享,laravel,sass,frontend,laravel-blade,laravel-mix,Laravel,Sass,Frontend,Laravel Blade,Laravel Mix,在我的项目中,我在SASS和Blade中使用了一些资源(主要是图像)。另外,我有一些资源仅用于SASS,还有一些资源仅用于Blade 例如,我可以在刀片文件中使用mix('images/logo.png'),在SASS文件中使用background:url('../images/logo.png') 关于我的目录结构,我做了以下工作: - resources - js - sass - images // All images used by Blade, Sass,

在我的项目中,我在SASS和Blade中使用了一些资源(主要是图像)。另外,我有一些资源仅用于SASS,还有一些资源仅用于Blade

例如,我可以在刀片文件中使用
mix('images/logo.png')
,在SASS文件中使用
background:url('../images/logo.png')

关于我的目录结构,我做了以下工作:

- 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"
他们被认为是两种不同的资源,这不是我所期望的

潜在解决方案

我发现,即使我没有在
webpack.mix.js
中指定
version()。所以我想也许我可以用一些技巧,比如:

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'));
但是这个解决方案有很多缺点,每次我都必须使用
版本控制的
函数,如果没有
webpack.mix.js
函数,我的源代码在其他项目中很难工作,我必须编辑我在资源文件夹中使用的每个文件才能使用该函数

其他解决方案?

我认为问题的根源可能来自我构建文件的方式,我有一个
resources/images
文件夹,其中包含SASS使用的图像,但Blade也使用这些图像。
SASS中使用的图像将被复制到
public/Images
,因为这是SASS处理Web包的方式,这些图像也将被第二次复制,因为我使用了
mix.copy()
(因为我需要其他文件位于公用文件夹中,以便在Blade/HTML中访问)

我很确定我在某个地方搞错了,我在互联网上查找了一种在Laravel中使用SASS和刀片资源的正确方法,但没有找到任何相关信息。
也许我应该考虑另一种文件结构?但是哪一个呢

我发现SASS生成的CSS文件使用版本化URL,即使我没有在webpack.mix.js中指定version()

在样式表中重写
url()
是一个简单的过程,它将文件的计算MD5哈希附加到url<另一方面,code>mix.version()
由于

/**
*读取文件的内容。
*/
读(){
返回fs.readFileSync(this.path(),'utf8');
}
/**
*计算文件的正确版本哈希。
*/
版本({
返回md5(this.read()).substr(0,20);
}
Laravel Mix将文件读取为字符串(而不是缓冲区),对其进行散列并仅提取前20个字符。我想不出一个简单的方法来覆盖这个行为,一个快速而肮脏的解决方法是重新定义
散列
函数:

const mix=require('laravel-mix');
设md5=require('md5');
设fs=require('fs-extra');
Mix.manifest.hash=函数(文件){
设f=新文件(path.join(Config.publicPath,File));
让hash=md5(fs.readFileSync(f.path());
让filePath=this.normalizePath(文件);
this.manifest[filePath]=filePath+'?'+哈希;
归还这个;
}

更好的方法是定义自己的
versionMD5()
方法,您可以从中复制一些代码。

我想给出自己的想法,同时我也面临同样的问题。Laravel Mix以不同的方式处理.blade和CSS/JS文件。对于徽标图像,您不会得到与它使用的.blade资产相同的哈希值。对于CSS文件,它有自己的文件加载器和哈希函数。它与文件结构没有任何共同之处。您提出的解决方案似乎是一个不错的选择,我认为这个问题没有本机解决方案。