Enquanto trabalhava em um novo projeto que o Laravel Nova usa para administrar , testei-o com as ferramentas para webmasters do Google. Verificou-se que algumas das fotos no recurso não foram otimizadas - seu tamanho pode ser reduzido significativamente. Aqueles que estão no projeto podem ser processados ao criar o projeto usando o node.js. Existem muitos pacotes prontos para isso. Ainda há imagens carregadas pelo usuário diretamente do painel de administração do site. Obviamente, você pode otimizar cada imagem antes de enviar para o site, mas por que não tornar esse procedimento automático. Então surgiu a ideia de fazer um pacote para o Laravel Nova: OptimalImage.
O pacote é bastante simples e, portanto, não pretende ser um guia completo para a criação de pacotes para o Laravel Nova. Ele não aborda um tópico bastante extenso sobre como trabalhar com o componente visual dos componentes. Se uma idéia interessante de um componente aparecer, com um componente visual - escreverei um artigo sobre este tópico.
Formulação do problema
Você deseja criar um pacote que adicione um novo campo. Este campo será diferente do
campo usual com o carregamento da imagem , pois a otimização será realizada para a imagem carregada.
Instalação e configuração do ambiente.
Para repetir todas as etapas deste guia, você precisará de um projeto com o Laravel e o Laravel Nova. O Laravel Nova é uma ferramenta paga, mas, na minha opinião, seu preço é bastante acessível.
Eu usei no trabalho:
- PHP 7.3.16
- Laravel 7
- Laravel Nova 3.0
.
. — :
cd /path/to/nova/project
php artisan nova:field yarbala/optimal-image
. nova-components
OptimalImage.
nova-components
.gitignore git init
cd /path/to/nova/project/nova-components/OptimalImage
git init
git add .
git commit -m "First commit"
git remote add origin git@github.com:yarbala/nova-optimal-image-field.git
git push -u origin master
spatie/laravel-image-optimizer
, require
composer.json
"spatie/laravel-image-optimizer": "^1.6"
Laravel
composer update
.
:
nova-components/OptimalImage/dist
nova-components/OptimalImage/resources
:
nova-components/OptimalImage/webpack.mix.js
nova-components/OptimalImage/package.json
nova-components/OptimalImage/mix-manifest.json
OptimalImage :
namespace Yarbala\OptimalImage;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;
class OptimalImage extends Image
{
protected function storeFile($request, $requestAttribute)
{
if (! $this->storeAsCallback) {
$fileName = $request->file($requestAttribute)->store($this->getStorageDir(), $this->getStorageDisk());
if ($fileName) {
try {
$this->optimizeImage($fileName);
} catch (FileNotFoundException $e) {
}
}
return $fileName;
}
$fileName = $request->file($requestAttribute)->storeAs(
$this->getStorageDir(), call_user_func($this->storeAsCallback, $request), $this->getStorageDisk()
);
if ($fileName) {
try {
$this->optimizeImage($fileName);
} catch (FileNotFoundException $e) {
}
}
return $fileName;
}
protected function optimizeImage($fileName)
{
}
}
Laravel\Nova\Fields\Image
.
public $component = 'optimal-image';
storeFile
Laravel\Nova\Fields\File
, Laravel\Nova\Fields\Image
. . , optimizeImage
.
optimizeImage:
namespace Yarbala\OptimalImage;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;
use Spatie\ImageOptimizer\OptimizerChain as ImageOptimizer;
use Storage;
class OptimalImage extends Image
{
protected function optimizeImage($fileName)
{
$needsUploadBack = false;
$localDisk = 'local';
$disk = $this->getStorageDisk();
if (!Storage::disk($localDisk)->exists($fileName)) {
Storage::disk($localDisk)->put($fileName, Storage::disk($disk)->get($fileName));
$needsUploadBack = true;
}
$path = Storage::disk($localDisk)->path($fileName);
app(ImageOptimizer::class)->optimize($path);
if ($needsUploadBack) {
Storage::disk($disk)->put($fileName, Storage::disk($localDisk)->get($fileName));
Storage::disk($localDisk)->delete($fileName);
}
}
}
Storage, Spatie\ImageOptimizer . - local
.
:
class OptimalImage extends Image
{
public function localDisk(string $disk)
{
return $this->withMeta(['localDisk' => $disk]);
}
protected function getLocalDisk()
{
return $this->meta['localDisk'] ?? 'local';
}
}
OptimalImage :
<?php
namespace Yarbala\OptimalImage;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Laravel\Nova\Fields\Image;
use Spatie\ImageOptimizer\OptimizerChain as ImageOptimizer;
use Illuminate\Support\Facades\Storage;
class OptimalImage extends Image
{
protected function storeFile($request, $requestAttribute)
{
if (! $this->storeAsCallback) {
$fileName = $request->file($requestAttribute)->store($this->getStorageDir(), $this->getStorageDisk());
if ($fileName) {
try {
$this->optimizeImage($fileName);
} catch (FileNotFoundException $e) {
}
}
return $fileName;
}
$fileName = $request->file($requestAttribute)->storeAs(
$this->getStorageDir(), call_user_func($this->storeAsCallback, $request), $this->getStorageDisk()
);
if ($fileName) {
try {
$this->optimizeImage($fileName);
} catch (FileNotFoundException $e) {
}
}
return $fileName;
}
protected function optimizeImage($fileName)
{
$needsUploadBack = false;
$localDisk = $this->getLocalDisk();
$disk = $this->getStorageDisk();
if (!Storage::disk($localDisk)->exists($fileName)) {
Storage::disk($localDisk)->put($fileName, Storage::disk($disk)->get($fileName));
$needsUploadBack = true;
}
$path = Storage::disk($localDisk)->path($fileName);
app(ImageOptimizer::class)->optimize($path);
if ($needsUploadBack) {
Storage::disk($disk)->put($fileName, Storage::disk($localDisk)->get($fileName));
Storage::disk($localDisk)->delete($fileName);
}
}
public function localDisk(string $disk)
{
return $this->withMeta(['localDisk' => $disk]);
}
protected function getLocalDisk()
{
return $this->meta['localDisk'] ?? 'local';
}
}
. , config/image-optimizer.php :
php artisan vendor:publish --provider="Spatie\LaravelImageOptimizer\ImageOptimizerServiceProvider"
, .
, readme .
, - . . .
.
O código fonte do projeto está disponível e distribuído sob a licença MIT.
Pacote Packagist
Pacote Novapackages