You've successfully subscribed to Заметки Разработчиков
Great! Next, complete checkout for full access to Заметки Разработчиков
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info is updated.
Billing info update failed.

tips and tricks

Оптимизация изображений

Размер изображений составляет существенную часть от размера страницы. Вот уже второй день вожусь с оптимизацией изображений в блоге. До этого я использовал скрипт, который позволяет сжать jpg и png без потерь. Теперь решил пойти еще дальше и использовать Webp формат. WebP - это формат сжатия изображений, разработанный компанией Google. Он

Размер изображений составляет существенную часть от размера страницы. Вот уже второй день вожусь с оптимизацией изображений в блоге. До этого я использовал скрипт, который позволяет сжать jpg и png без потерь.

Теперь решил пойти еще дальше и использовать Webp формат.

WebP - это формат сжатия изображений, разработанный компанией Google. Он использует современный алгоритм сжатия, который обеспечивает более эффективное сжатие, чем форматы JPEG и PNG, что может привести к быстрее загрузке веб-страниц и экономии интернет-трафика.

В итоге пришел к такому кейсу:

  1. Прогоняю скриптом сжатия без потерь.
  2. Прогоняю скриптом для преобразования в webp. Сохраняю все изображения в отдельную папку.
  3. Nginx пытается сначала найти webp изображение, если не получается, то берет сжатый png или jpg

А вот и сам скрипт для преобразования в webp:

#!/bin/bash
file=webp.flag

if [ -f "$file" ]; then
  option="-newer $file"
fi

find ./struchkov.dev/www/images/ -type f -iregex '.*\.\(jpg\|jpeg\|png\)' $option -exec sh -c '
  webp_file="${1/\/images\//\/images\/webp\/}"
  webp_dir="$(dirname "$webp_file")"
  mkdir -p "$webp_dir"
  cwebp -mt -af -progress -m 6 -q 85 -pass 10 "$1" -o "${webp_file%.*}.webp"
' _ {} \;

touch "$file"
echo "$(date)" > "$file"

Также как и в первом скрипте, я использую файл-флаг, чтобы не преобразовывать файлы, которые уже преобразовывались.

Далее я беру папку /struchkov.dev/www/images/, в которой лежат исходные изображения и создаю новую папку /struchkov.dev/www/images/webp. Внутри папки webp структура папок и файлов такая же, как и в папке images. Только формат у файлов .webp.

За преобразование отвечает команда cwebp. Эта утилита сжимает изображения, но с потерями в качестве. Я подобрал оптимальные параметры сжатия, чтобы потеря качества была не заметна, но при этом изображения занимали меньше места.

cwebp -mt -af -progress -m 6 -q 85 -pass 10 "$1" -o "${webp_file%.*}.webp"

Подробнее об этих и других параметрах можно почитать в документации.

Nginx

Теперь сделаем так, чтобы при запросе jpg/png изображения отдавался аналогичный webp файл. Для этого в конфигурацию nginx добавляем:

location ~* ^(/blog/ru/content/images/)(.+)\.(png|jpe?g)$ {	
    expires max;
    alias /var/struchkov.dev/ghost/www/images;
    set $webp_image_subdir "/webp/";
    set $basename $2;
    try_files $webp_image_subdir$basename$webp_suffix $uri;
}

try_files сначала попытается достать webp изображение, если его нет, то возьмет сжатый оригинал формата jpg/png.

Как откатить git reset hard

Сделал "Reset current branch to here" в режиме "Hard", но забыл сделать "Shelf" для не зафиксированных изменений, над которыми работал весь день. В итоге проделанная работа за день была успешно стерта. В такие моменты  главное не поддаваться панике 😅 В Idea есть замечательная функция LocalHisotry, которая автоматически сохраняет все изменения над

Сделал "Reset current branch to here" в режиме "Hard", но забыл сделать "Shelf" для не зафиксированных изменений, над которыми работал весь день. В итоге проделанная работа за день была успешно стерта.

В такие моменты  главное не поддаваться панике 😅

В Idea есть замечательная функция LocalHisotry, которая автоматически сохраняет все изменения над файлами. Если затертых файлов было не много, то нажмите ПКМ и в меню выберете Local History —> Show History

Скорее всего вы увидите состояние файла до выполнения git reset.

Если же измененных файлов было много, то восстанавливать их по одному довольно муторно. Поэтому нажмите ПКМ по корневой папке проекта и также выберете Local History —> Show History.

Вот и все, впредь будьте внимательнее 😊

Логирование sql в SpringBoot Hibernate

Чтобы каждый раз не искать эти проперти оставлю их тут. Включение логирования sql в SpringBoot spring: jpa: show-sql: true properties: hibernate: format_sql: true Если требуется добавить вывод аргументов, то добавляем еще logging: level: org: hibernate: type: trace Включение логирования sql в Quarkus quarkus: hibernate-orm: log: sql: true format-sql: true

Чтобы каждый раз не искать эти проперти оставлю их тут.

Включение логирования sql в SpringBoot

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true

Если требуется добавить вывод аргументов, то добавляем еще

logging:
  level:
    org:
      hibernate:
        type: trace

Включение логирования sql в Quarkus

quarkus:
  hibernate-orm:
    log:
      sql: true
      format-sql: true
      bind-parameters: true

Параллельная сборка модулей в Maven

Небольшая хитрость, которая может ускорить сборку многомодульного maven проекта. Это параллельная сборка модулей. mvn -T 1C clean install Но есть одно условие. Ваш проект должен содержать модули, которые не зависят друг от друга последовательно. Объясню на примере проекта, который состоит из 18 модулей. Оранжевыми прямоугольники я выделил модули, которые могут

Небольшая хитрость, которая может ускорить сборку многомодульного maven проекта. Это параллельная сборка модулей.

mvn -T 1C clean install
1C означает использовать 1 поток на 1 ядро процессора

Но есть одно условие. Ваш проект должен содержать модули, которые не зависят друг от друга последовательно.

Объясню на примере проекта, который состоит из 18 модулей. Оранжевыми прямоугольники я выделил модули, которые могут собираться параллельно, так как они не зависят друг от друга.

По факту эти группы модулей зависят только друг от друга. Сначала собирается группа domain, от нее зависит группа context, потом core и так далее. Без context не собрать core, думаю суть понятна. Но вот модули core не зависят друг от друга, и могут собираться параллельно.

Для примера вот время сборки в последовательном режиме:

А вот в параллельном:

Выигрыш почти в два раза.

И на последок, вот как можно настроить этот параметр в Idea, чтобы не приходилось запускать сборку из консоли каждый раз. Эту настройку нужно делать в каждом проекте, она не глобальная.