No meu projeto, uso alguns recursos (principalmente imagens) no SASS e no Blade. Além disso, tenho alguns recursos usados apenas no SASS e outros usados apenas no Blade.
Por exemplo, eu poderia usar mix('images/logo.png')
nos arquivos Blade e background: url('../images/logo.png')
nos arquivos SASS.
Quanto à minha estrutura de diretórios, fiz o seguinte:
- resources
- js
- sass
- images // All images used by Blade, Sass, or both
- fonts
Para compilar meus recursos e colocá-los na public
pasta, eu uso o seguinte 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();
Como resultado, recebo esse URL no app.css:
background: url(/images/logo.png?0e567ce87146d0353fe7f19f17b18aca);
Enquanto eu recebo outro em HTML renderizado:
src="/images/logo.png?id=4d4e33eae039c367c8e9"
Eles são considerados dois recursos diferentes, não era o que eu esperava ...
Solução potencial
Eu descobri que os arquivos CSS gerados pelo uso SASS um Versioned URL mesmo se eu não especificar version()
no webpack.mix.js
. Então eu estava pensando que talvez eu pudesse usar algum truque, como este:
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
});
E use-o no SASS da seguinte forma:
background-image: url(versioned('/images/logo.png'));
Mas esta solução tem muitas desvantagens, sou obrigado a usar a versioned
função todas as vezes, meu código-fonte não funcionará facilmente em outros projetos sem a webpack.mix.js
função e tenho que editar todos os arquivos que utilizo na minha pasta de recursos para usar a função.
Outra solução?
Acho que a origem do meu problema pode vir da maneira como estruturei meus arquivos. Tenho uma resources/images
pasta que contém imagens usadas pelo SASS, mas também usadas pelo Blade.
As imagens usadas no SASS serão copiadas public/images
porque é assim que o SASS trabalha com o webpack, e essas imagens também serão copiadas uma segunda vez porque eu as usei mix.copy()
(porque eu preciso que os outros arquivos estejam dentro da pasta pública para estarem acessíveis no Blade / HTML).
Tenho certeza de que estou enganando em algum lugar, procurei na Internet uma maneira adequada de trabalhar com os recursos SASS e Blade no Laravel, mas não encontrei nada relevante.
Talvez eu deva considerar outra estrutura de arquivos? Mas qual deles ?
mix.version()
e para arquivos CSS, há seu próprio carregador de arquivos com sua própria função de hash. Não tem nada em comum com a estruturação de arquivos. Sua solução proposta parece ser uma boa opção, não acho que exista uma solução nativa para esse problema.Respostas:
A reescrita
url()
nas folhas de estilo é um recurso do webpack , que anexa o hash MD5 calculado do arquivo ao URL.mix.version()
por outro lado, gera um hash diferente, graças a essas linhas:O Laravel Mix lê o arquivo como uma string (não como um buffer), faz o hash e extrai apenas os 20 primeiros caracteres. Não consigo descobrir uma maneira simples de substituir esse comportamento, uma solução rápida e suja é a redefinição da
hash
função:Uma maneira melhor é estender o Laravel Mix e definir seu próprio
versionMD5()
método, você pode copiar algum código dessa extensão .fonte