Mientras trabajaba en un nuevo proyecto que Laravel Nova usa para administrar , lo probé con las herramientas para webmasters de Google. Resultó que algunas de las fotos en el recurso no estaban optimizadas, su tamaño podría reducirse significativamente. Los que están en el proyecto pueden procesarse al construir el proyecto usando node.js. Hay muchos paquetes listos para esto. Todavía hay imágenes cargadas por el usuario directamente desde el panel de administración del sitio. Por supuesto, puede optimizar cada imagen antes de subirla al sitio, pero ¿por qué no hacer que este procedimiento sea automático? Entonces nació la idea de hacer un paquete para Laravel Nova: OptimalImage.
El paquete es bastante simple y, por lo tanto, no pretende ser una guía completa para crear paquetes para Laravel Nova. No aborda un tema bastante extenso sobre el trabajo con el componente visual de los componentes. Si aparece una idea interesante de un componente, con un componente visual, escribiré un artículo sobre este tema.
Formulación del problema
Desea crear un paquete que agregue un nuevo campo. Este campo diferirá del
campo habitual con la carga de imágenes en que la optimización se realizará para la imagen cargada.
Instalación y configuración del entorno.
Para repetir todos los pasos de esta guía, necesitará un proyecto con Laravel y Laravel Nova. Laravel Nova es una herramienta de pago, pero en mi opinión, su precio es bastante asequible.
Solía en el trabajo:
- 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 .
, - . . .
.
El código fuente del proyecto está disponible y se distribuye bajo la licencia MIT.
Paquete embalador
Paquete Novapackages