На сайте используется ряд изображений с высоким разрешением от 2500px.
pageSpeed конечно же ругается, поэтому пытаюсь использовать современный атрибут srcset
для изображений:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
img {
max-width: 100%;
margin: auto;
}
Для высоко разрешения так и использую в 2500px, а для обычного делаю эти же картинки
в уменьшенным в 2 раза разрешением.
Пример записи img для реального проекта:
В итоге по всем "возможностям" pagespeed ругается на эти изображения и ругается на
img-1-2x.jpg Т.е. на телефонах вместо того чтобы отображать img-1-1x.jpg отображается
большая картинка.
И такие проблемы только для моб. девайсов:
Для десктопа все отлично, скорость 90+!
По совету использую Echo.js lazy load, но этот lazy load на телефонах (особенно при
плохом интернете) не все фото грузит.
Update:
Как оказалось запись:
не валидна!
При использовании атрибута sizes запись должна быть подобна этой:
Просмотрев видеоурок с рекомендацией о сжатии изображения в squoosh.app, сделала
изображения с разрешением .webp. Подключила с использованием picture:
Изображения в формате .webp весят около 200-300 кб, это при том что в большом разрешении
около 2 Мб.
В итоге скорость на страницах упала до 10 - 13, и изображения отображаются только
в хроме. Стоит последняя версия firefox, но почему-то и в нем не отображаются картинки.
caniuse.com/#feat=picture
! Да и не всегда есть возможность оптимизировать все изображения, т.е. менять размеры
или разрешение, а таких картинок на сайте много.
Вопрос:
Почему срабатывает огромное разрешение для телефонов, а не уменьшенное при записи
Ответы
Ответ 1
Делайте картинки в формате webp и добавляйте их в ваш srcset, этого гугл от вас и
ждет, о чем вы бы и сами узнали, если бы развернули блок с ошибкой и прочитали что
там написано.
Для изображений в форматах JPEG 2000, JPEG XR и WebP используется более эффективное
сжатие, поэтому они загружаются быстрее и потребляют меньше трафика, чем изображения
PNG и JPEG.
Вариант с picture наиболее кроссбраузерный.
Сначала даете ему на съедение картинку в формате webp (как я вам в примере написал),
если он не поддерживает такой тип, то будет грузить jpg.
Но гугл пейдж спид это расценит как ХОРОШО.
Ответ 2
Вообще можете тестировать и оптимизировать изображения в gtmetrix, но если поищите
можете найти другие сайты для оптимизации, и еще в photoshop сохраните изображение
с таким качеством что бы было оптимально размер -> качество.
И еще один важный момент. Это для мобильного сайта.
Изображения которые не должны быть видны в мобильном. сделайте фоном блока(если это
возможно) в место тега img. И в определенный момент когда блок скрывается ОБЯЗАТЕЛЬНО
для этого разрешения экрана поставьте для этого блока с фоновым изображением background-image:
none;.
Вот таким образом в вы достаточно оптимизируете свою страницу.
Ответ 3
А если в src ставить уменьшенную картинку, или заглушку и после загрузки скриптом
менять из атрибута, причем можно и с проверкой разрешения окна и для мобильных брать
например из data-mobile меньшего размера? Не знаю такой вариант обманет ли pageSpeed.
Можно переписать на чистом JS
$(function() {
$('.big').html(function() {
$(this).attr("src", $(this).attr('data'));
});
});
Сижу на хостинге, и у некоторых пользователей очень долгая загрузка сайта.
Разбирались, и нашли почему такая проблема, но не нашли решения.
На сайт подключается стиль стандартным способом:
В стиле всего 79 строчек, но самую большую нагрузку в стилемов файле беру изображения:
background: url(../images/bg.jpg);
И вот каждая картинка грузит около 3-5 секунд (весом 900кб).
Не понимаем, с чем связана эта проблема, у 95% пользователей все окей, а у остальных
5% - такая вот беда...
При прямом открытии картинки по URL, эту картинку грузит все равно те же 5 секунд,
а остальные - шустро (200мс в среднем).
В какую сторону стоит копать в такой ситуации?
Ответы
Ответ 1
Я бы посоветовал вам оптимизировать весь статический контент на сайте.
Сжатие графики
В вашем случае кроме сжатия стилей и скриптов посоветую сжимать и графику. К примеру,
картинки можно легко сжать без потери качества только за счет удаление exif-данных.
На реальном сайте можно сократить размер картинок в среднем на 70%, что на современном
сайте равняется примерно 4 МБ. Пример на gulp:
var
gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
imageminJR = require('imagemin-jpeg-recompress'),
imageminSvgo = require('imagemin-svgo');
// Optimizing images
gulp.task('imagemin', function() {
gulp.src('./img/**/*')
.pipe(imagemin([
imageminJR({
method: 'ms-ssim'
}),
imageminSvgo({
plugins: [
{removeViewBox: false}
]
})
]))
.pipe(gulp.dest('./public/img/'))
});
А для браузеров, которые понимают легковесный формат webp (формат разработан Google),
можно сделать еще такой вариант изображений:
var
gulp = require('gulp'),
webp = require('gulp-webp');
// Generate Webp
gulp.task('webp', function() {
gulp.src('./img/**/*')
.pipe(webp())
.pipe(gulp.dest('./public/img/'))
});
Оптимизация скриптов
Сперва объедините все скрипты в один файл и минифицируйте их. Это помет сократить
количество HTTP-запросов и размер файлов:
var
gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
// Concat JS
gulp.task('js', function(){
gulp.src([
'./js/jquery.js',
'./js/wow.js',
'./js/menu.js',
'./js/scrollspy.js',
'./js/main.js',
'./js/temp/contact.bundled.js',
'./js/owl.carousel.js'
])
.pipe(concat('script.js'))
.pipe(uglify())
.pipe(gulp.dest('./public/js/'))
});
Оптимизация стилей
Кроме обычной минификации стилей можно использовать и продвинутую - объединять дубликаты
классов и @media. Пример на gulp из моего [web-starter-kit][1]:
var
gulp = require('gulp'),
stylus = require('gulp-stylus'),
// Минифицирует CSS, объединяет классы. Не ломает CSS, в отличие от cssnano,
который, к примеру, может неправильно выставлять z-index
csso = require('gulp-csso'),
// Объединяет все @media
cmq = require('gulp-combine-mq'),
// Сокращает CSS-селекторы
gs = require('gulp-selectors'),
// Проставляет вендорные префиксы
autoprefixer = require('gulp-autoprefixer'),
livereload = require('gulp-livereload'),
nib = require('nib');
// Compiling Stylus in CSS
gulp.task('css', function() {
gulp.src('./styl/*.styl')
.pipe(stylus({
use: nib()
}))
.pipe(cmq())
.pipe(csso())
.pipe(autoprefixer('last 3 versions'))
.pipe(gulp.dest('./public/css/'))
});
А если совсем делать нечего, то можно еще и селекторы сократить:
// Minify selectors
gulp.task('gs', function() {
var ignores = {
classes: ['active', 'menu', 'nav', 'slide', 'error', 'form-control',
'loader', 'showLoader', 'fadeLoader', 'webp', 'wow', 'owl-*', 'i-*'],
ids: '*'
};
gulp.src(['./public/**/*.css', './public/**/*.html'])
.pipe(gs.run({}, ignores))
.pipe(gulp.dest('./public/'))
});
Кстати, наверняка у вас есть классы, добавляющиеся через JS, поэтому предварительно
стоит все такие классы вынести в переменную ignores.
Кеширование статики на стороне пользователя
Также бы посоветовал кешировать скрипты и стили на стороне пользователя, чтобы исключить
их повторную загрузку, если они не изменились:
Header set Cache-Control "max-age=2592000"
И включить gzip сжатие на сервере:
# сжатие text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml
text/css text/javascript application/javascript application/x-javascript
Ответ 2
Сами ответили на свой же вопрос. У одних хорошо, у других плохо. Зависит от скорости
приёма клиентов, и от скорости отдачи веб-сервера. Чем дальше от сервера, тем хуже
прием. Чем меньше скорость приёма, тем медленнее скорость загрузки.
Принцип подгрузки больших элементов прост - сначала загружайте всё то, что сформирует
страницу предельно быстро - основные стили, основной каркас, минимальные иконки. А
вот большие уже элементы, к примеру Ваш фон, подгружайте отдельным стилем, к примеру
асинхронно (jQuery), тогда и клиент быстрее увидит страницу, а там уже и картинки подгрузятся.
PageSpeed Insights Рекомендует исправить обязательно:
Удалите код JavaScript и CSS, блокирующий отображение верхней части
страницы
Хотя все скрипты итак стоят внизу страницы:
Не понимаю что может быть причиной, как можно исправить?
Если дело в количестве подключаемых библиотек, то проверяла другую подобную страницу
(с десятком подключаемых скриптов) и все в порядке. async не помогает, да и проблем
с ним много.
footer.tpl:
После скриптов контента нет.
Ответы
Ответ 1
Как разобраться с блокирующим CSS я давал ответ вот тут. Дополнительно можете воспользоваться
библиотекой loadCSS для загрузки неблокирующего CSS.
Куда вы разместите в странице ваши скрипты — в начало или конец документа — не имеет
значения. В вашем случае совет следующий:
Во-первых, объединить все библиотеки-плагины и файл с их инициализацией в один файл,
назовем его, к примеру, main.js.
Во-вторых, загружать jQuery по событию load:
function dlOnload() {
var jq = document.createElement("script");
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
document.body.appendChild(jq);
}
window.addEventListener("load", dlOnload, false);
В-третьих, запускать загрузку зависимых от jQuery файлов после его загрузки:
function dlOnload() {
var jq = document.createElement("script"), mainScript;
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
document.body.appendChild(jq);
jq.onload = function() {
mainScript = document.createElement("script");
mainScript.src = "scripts/main.js";
document.body.appendChild(mainScript);
}
}
window.addEventListener("load", dlOnload, false);
И в-четвертых, всем скриптам, которым не важен порядок загрузки, добавить атрибут async.
UPD: для динамической загрузки скриптов с возможностью кэширования в localStorage
рекомендую воспользоваться basket.js. В вашем случае код будет выглядеть примерно таким
образом:
basket
.require({ url: 'path-to/jquery.js' })
.then(function () {
basket.require(
{ url: 'path-to/jquery-ui.js' },
{ url: 'path-to/jquery.fancybox.js' },
{ url: 'path-to/jquery.fancybox.pack.js' },
{ url: 'path-to/common.js' }
);
}, function (error) {
// Ошибка
console.log(error);
});
У меня есть вёрстка, там я много раз (можно сказать в 90% случаев)задавал значения
с помощью vh и vw.
Ну сверстал таким образом много секций, вижу что компьютер начинает шуметь, захожу
в диспетчер задач, смотрю 30% ЦПУ нагрузка от браузера.. Выхожу со сверстанного сайта
всё показывает норм, понижается до 3%..
Это я впервые делаю так, до этого подобного никогда не наблюдал.. И теперь возникает
вопрос, действительно ли множественное использование vh и vw так сильно повлияло на
производительность сайта??
Ответы
Ответ 1
Единицы vh и vw не влияют на производительность, скорее всего проблема в большем
количестве анимаций.
Ещё, что-то постоянно дёргает пересчёт стилей (посмотрите Performance в DevTools),
нужно дебажить.
Ответ 2
CSS , тем более такой не большой сайт не может так сильно грузить машину. Попробуй
отключить весь js и проверить еще раз. Уверен , что проблема в нем. + Надо проверить пк)
Нужно по изменению окна браузера уменьшать пропорционально или возвращать в обычное
состояние отдельные объекты svg. Напишите пример пожалуйста, чтобы хоть знать, что к чему.
Ответы
Ответ 1
Примерно так , указываем viewBox и всё остальное само становится резиновым
я не преследовал цель сделать один в один
Возьмём самый распространенный вариант - смайлики. Их очень много (~1500) и отображаются
все одновременно, как лучше их выводить?
На сервер храниться одна большая картинка (спрайт) где все смайлики расположены друг
за другом, у клиента в css расписаны расположение каждого смайлика (background-image
и background-position) и в html документе с помощью class распознаются смайлики.
На сервер хранится каждая картинка смайлика отдельно, у клиента в css расписаны путь
до каждого смайлика (background-image) и в html документе с помощью class распознаются
смайлики.
На сервер хранятся изображения отдельно, у клиента только в html документе написаны
путь до смайликов (img[src]).
И какие картинки лучше использовать svg или png?
Возможно вы предложите ещё более правильный вариант, пожалуйста расскажите максимально
подробно, почему именно так?
Второй вопрос заключается в генерации этого списка смайликов, как лучше его генерировать?
Сгенерировать заранее и хранить на сервере в виде шаблона/html документа и подгружать
его через ajax и вставлять в html страницу, когда это нужно.
Хранить html код в JS коде, в виде строки и вставлять когда это нужно.
Генерировать html код из заранее составленного массива хранящийся в js коде.
Генерировать код из массива хранящейся на сервер и полученного через ajax.
Так же прошу рассказывать максимально подробно.
Под правильным вариантом подразумевается не только правильно по написанию кода, но
и по быстроте загрузки смайликов и нагрузки на обе стороны (сервер и клиент).
Ответы
Ответ 1
Куда проще пожертвовать загрузкой одним спрайтом на N Mb, чем открывать 1500 соединений.
Спрайт после первой загрузки в кэш и тяжёлое неудобство исчезнет.
В HTTP2 попроще в этом вопросе, но настроить сервер грамотно нужно для выигрыша скорости.
Выходит для спрайта лучше юзать одну картинку с background-position и классами.
Какой формат лучше - вопрос достаточно сложный, сильно зависящий от конкретной ситуации
и предпочтений, для спрайтов лично я обычно использую png - разумный баланс качества/размера.
Генерировать как картинку, которую прописать background-image, браузер сам подтянет,
JS вообще не нужен.
Use the grunt-spritesmith, Luke!
P. S. Инлайнить в css - это зарядить револьвер и поднести к ноге: поддержка сложнее,
код распухает, кэшировать картинки нельзя (можно файлы стилей, конечно, но их может
автоматически генерировать сервер, выгоды мало).
Однажды я попробовал и отказался.
Решил подробнее изучить тему мета-тэгов и наткнулся на такие тэги:
Как работают и какую задачу они решают?
Ответы
Ответ 1
Кратко - Вы сообщаете браузеру, по каким адресам могут находиться ресурсы Вашей страницы
(картики, скрипты), что бы он мог разрезолвить имена сразу. На очень медленном интернете
это может сэкономить до 0.2 секунд на каждый запрос.
Вопрос по оптимизации проекта. Использую grunt.js, все скрипты и плагины объединяю
и сжимаю в один файл, правильно ли это? Либо нужно подключать отдельно плагины, а все
вызовы плагинов и простые скрипты объединять уже в 1 файл?
Ответы
Ответ 1
Вы все верно делаете. Конкатенация скриптов и стилей уменьшает количество запросов
на сервер, а также конечный размер CSS и JS, что делает загрузку сайтов более быстрой,
вследствие чего показатель отказов падает, позиции в поисковой выдаче растут, глубина
просмотров растет, а клиент счастлив.
Оптимизация стилей
Кроме обычной минификации стилей можно использовать и продвинутую - объединять дубликаты
классов и @media. Пример на gulp из моего web-starter-kit:
var
gulp = require('gulp'),
stylus = require('gulp-stylus'),
// Минифицирует CSS, объединяет классы. Не ломает CSS, в отличие от cssnano,
который, к примеру, может неправильно выставлять z-index
csso = require('gulp-csso'),
// Объединяет все @media
cmq = require('gulp-combine-mq'),
// Сокращает CSS-селекторы
gs = require('gulp-selectors'),
// Проставляет вендорные префиксы
autoprefixer = require('gulp-autoprefixer'),
livereload = require('gulp-livereload'),
nib = require('nib');
// Compiling Stylus in CSS
gulp.task('css', function() {
gulp.src('./styl/*.styl')
.pipe(stylus({
use: nib()
}))
.pipe(cmq())
.pipe(csso())
.pipe(autoprefixer('last 3 versions'))
.pipe(gulp.dest('./public/css/'))
.pipe(livereload())
});
А если совсем делать нечего, то можно еще и селекторы сократить:
// Minify selectors
gulp.task('gs', function() {
var ignores = {
classes: ['active', 'menu', 'nav', 'slide', 'error', 'form-control',
'loader', 'showLoader', 'fadeLoader', 'webp', 'wow', 'owl-*', 'i-*'],
ids: '*'
};
gulp.src(['./public/**/*.css', './public/**/*.html'])
.pipe(gs.run({}, ignores))
.pipe(gulp.dest('./public/'))
});
Кстати, наверняка у вас есть классы, добавляющиеся через JS, поэтому предварительно
стоит все такие классы вынести в переменную ignores.
Сжатие графики
Кроме стилей и скриптов также посоветую сжимать и графику. К примеру, картинки можно
легко сжать без потери качества только за счет удаление exif-данных. Пример на gulp:
var
gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
imageminJR = require('imagemin-jpeg-recompress'),
imageminSvgo = require('imagemin-svgo');
// Optimizing images
gulp.task('imagemin', function() {
gulp.src('./img/**/*')
.pipe(imagemin([
imageminJR({
method: 'ms-ssim'
}),
imageminSvgo({
plugins: [
{removeViewBox: false}
]
})
]))
.pipe(gulp.dest('./public/img/'))
});
А для браузеров, которые понимают легковесный формат webp (формат разработан Google),
можно сделать еще такой вариант изображений:
var
gulp = require('gulp'),
webp = require('gulp-webp');
// Generate Webp
gulp.task('webp', function() {
gulp.src('./img/**/*')
.pipe(webp())
.pipe(gulp.dest('./public/img/'))
});
Кеширование статики на стороне пользователя
Также бы посоветовал кешировать скрипты и стили на стороне пользователя, чтобы исключить
их повторную загрузку, если они не изменились:
Header set Cache-Control "max-age=2592000"
И включить gzip сжатие на сервере:
# сжатие text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml
text/css text/javascript application/javascript application/x-javascript
Преимущества и недостатки CDN
С одной стороны cdn действительно поможет брать контент с кеша пользователя, однако
с другой - это создаст дополнительный запрос, если этого контента у пользователя нет.
Еще одна проблема может быть в том, что сервер cdn вовсе может не работать и ничего
не отдать. Вспомнить хотя бы, как несколько лет назад все сервисы Google перестали
работать и тысячи сайтов сломались из-за того, что не могли загрузить шрифты с Google Font.
В будущем, когда HTTP/2 будет достаточно распространен, скрипты можно будет загружать
в несколько потоков и конкатенация будет необязательной. Хотя и тогда конечный размер
сжатых в один файлов будет эффективней, чем сжатых по отдельности.
Объясните, пожалуйста, значение термина Critical rendering path.
Ответы
Ответ 1
Critical rendering path — путь, который проходит браузер до того, как страница отрисовывается
в браузере.
Этот путь в общем виде состоит из таких шагов (без детализации работы на сетевом уровне):
Получение ответа от сервера — HTML. Браузер парсит HTML, чтобы построить DOM
Построение объектной модели CSS — CSSOM.
Выполнение скриптов (поэтому, в основном, их надо помещать в конце документа).
Построение дерева рендера на основе DOM и CSSOM.
Отрисовка страницы.
Если рассматривать этот путь в разрезе CSS, то CSS является блокирующим рендер ресурсом,
т. е. если во время разбора HTML браузер встречает ссылку на CSS-файл, то продвижение
по пути останавливается и браузер начинает скачивать файл и разбирать его. Для оптимизации
этого процесса рекомендуется помещать CSS, достаточный для отображения первого экрана,
в внутрь тега и переносе оставшихся стилей/скриптов
в нижнюю часть, после контента. Мне кажется, что создать крупный проект таким способом
вообще не возможно, так как потребуется очень кропотливо вытаскивать стили из разных
участков сайта и в итоге получится "каша".
4) Шрифты из Google Fonts лучше сохранять к себе? Или простого импорта достаточно?
Насколько влияет на скорость загрузки количество подключаемых стилей шрифтов?
Иногда в дизайне используются заголовки с засечками, а основной шрифт - без. Выходит,
нужно подключать 2 разных шрифта, да еще и с разными стилями, что резко повышает количество
файлов подгружаемых в целом.
Список можно продолжать, но, это вот прям основное, что терзает мою душу.
Ответы
Ответ 1
Если исходить из влияния на продвижение сайта этих факторов, то по собственному опыту
могу порекомендовать:
Форматы картинок на продвижение не влияют. Влияют подписи, title и shema.
Инкубаторские сайты, типа Bootstrap, продвигаются хуже. Кастомизируйте верстку.
Быстрое отображение первого экрана для продвижения не критично. Важнее скорость отдачи
документа, его вес и отсутствие ошибок. У Google под ускоренную загрузку специально
есть технология Amp. В Yandex аналог это Турбо-страницы.
Шрифты лучше грузить с серверов Google, поскольку они находятся в CDN. То есть ближе
к пользователю, чем ваш сайт.
Ответ 2
Некоторые вещи лучше делать как удобнее, так как время программиста и вообще человека
очень ценно. Если делать какие-то сложные манипуляции с картинками, стилями, которые
существенно затруднят задачу поддержания и разработки сайта, то этого делать точно
не стоит.
Для автоматизации работы со стилями и библиотеками, особенно если нужно всё собрать
в одном файле, можно использовать сборщики. Например webpack, или rollup. Заметим что
в них входят алгоритмы вырезания неиспользованного кода. TreeShake и DeadCodeElimination.
Так же если сразу работать со стилями правильно, то потом выносить из одного места
в другое не придётся.
Фреймворки бывают разные, например есть фреймворки для создания одностраничных приложений,
например Vue.js. По сути создать одностраничник без использования специальных фреймворков
не получится, я пробовал ))
А без таких фреймворков как bootstrap вполне можно обойтись. Думаю тут каждая ситуация
индивидуальная.
Конечно использование большой библиотеки ради пары функций из неё, по моему мнению
смысла нету, лучше тогда эти функции копировать себе, или написать свои версии, в интернете
легко найти код наиболее употребимых функций.
Выпиливать из библиотек лишние функции это издевательство над собой... конечно если
фреймворки разрешает покомпонентную сборку, то почему бы и нет, но вручную делать точно
не стоит, так как это часы, дни и недели потраченного времени в пустую, при этом при
выходе новой версии пакета всё придётся делать повторно.
И ещё, лично моё мнение что прямо уж из-за каждого байта библиотек бороться не стоит,
ведь внешние, подключаемые библиотеки на один клиент подгружаются только один раз,
а дальше они берутся из кэша, пока кэш не сбросится.
Ответ 3
Дополню насчет иконок.
Первое - запихать их в SVG и вставлять в нужное место с помощью use xlink.
Плюс: универсальность.
Минусы: не поддерживается в старых браузерах, занимает сравнительно много места в
коде, некоторые трудности при задавании цвета.
Второе - запихать иконки в фонт (файл шрифта), подгрузить этот фонт в стилях, а в
коде задавать элемент с нужным символом.
Плюсы: универсально, удобно, быстро, легко менять цвет, поддерживается даже антиквариатом.
Минусы: требует усилий по изначальному созданию фонта, в код нужно добавлять элемент
или псевдоэлемент с символом, нельзя сделать разноцветными.
Третье - сложить иконки в одну большую картинку и подставлять нужную с помощью background-position
или другими ухищрениями.
Плюсы: можно использовать многоцветные иконки.
Минусы: изменить цвет нельзя (или путем хитрых манипуляций с фильтрами), манипулирование
размерами затруднено, возня с позиционированием не очень удобна.
Какой метод использовать - зависит от ситуации. Например, если есть ограничение на
размеры стилей, то удобнее фонт.
Ответ 4
Отсрочьте загрузку контента, когда есть такая возможность.
Используйте отдельные JS и CSS файлы
Используйте системы кэширования
Избегайте изменения размеров изображений в HTML
Не используйте изображения для показа текста
Оптимизируйте размеры изображения благодаря использованию правильного формата файла
Оптимизируйте метод написания кода
Загружайте JavaScript в конце документа
Используйте сеть доставки контента (Content Delivery Network, CDN)
Оптимизируйте веб-кэширование
обо всем это Вы можете подробно почитать на Хабре
Какими способами и инструментами можно оптимизировать загрузку мобильных версий сайта
применительно к адаптивному веб-дизайну? Иногда необходимо переделывать фронтэнд без
возможности изменений серверной стороны, поэтому ищу лучшее решение с учетом этого момента.
Ситуация 1. Есть 2 js и 2 css файла. Как можно сделать, чтобы грузился только js
#1 и css #1, в зависимости от screen.width например?
Ситуация 2. В dom есть элементы с классом .only-desktop, в которых находятся изображения.
Какой наиболее быстрый и правильный способ предотвратить загрузку изображений в .only-desktop?
Ответы
Ответ 1
Здесь официальное руководство от google, с примерами.
Для начала воспользуйтесь одним из готовых решений, примеры прилагаются. HeadJs,
пожалуй, проще всего.
Сложные правила для media queries становятся сильно проще, если использовать какой-либо
препроцессор стилей и миксины
Пример для раздельных Javascript с помощью enquire:
Этот пример подразумевает, что вы используете require или webpack, поддерживающие
сборку догружаемых модулей. Конечно, вы можете использовать любой доступный способ
инжекции скриптов и ресурсов.
Тем же способом можно подгрузить enquire, или любую другую из вышеперечисленных библиотек
из cdn, не меняя серверную часть.
Согласно этому исследованию, самым эффективным путём запрета загрузки изображений
является каскадная перезапись свойства посредством @media queries
Ответ 2
Это похоже на какую-то преждевременную оптимизацию. Если у вас действительно такой
большой сервис, то тогда проще генерировать макеты под девайсы на серверной стороне,
как это делает например apple.
Подгружать css в зависимости от разрешения, можно указав атрибут media
в теге link
Для JavaScript можно использовать такой хак
Вы писали про modernizr.js, посмотрите на yepnopejs с помощью него, вы сможете загружать
необходимые вам стили и js файлы в зависимости от условий.
Чтобы изображения не загружались сразу, используйте атрибут fake-src и туда пишите
url для фото, потом с помощью JS подставлять url изображения из fake-src в src.
Ответ 3
Вы можете выставить media queries для загрузки файлов в зависимости от разрешения
экрана (Ситуация 1) или для загрузки классов внутри файла стилей (Ситуация 2).
Или я не правильно понял ваш вопрос?
Ответ 4
добавляейте атрибуты async или defer в зависимости от того что нужно
Сайт - доска объявлений, все изображения хранятся в одной папке, количество порядка
40 тысяч. Выводятся изображения напрямую, просто через урл (src="/imgs/1253573.jpg")
Если ли смысл раскидать на поддиректории (по подразделам сайта например), большой
ли будет выигрыш в ресурсах или скорости загрузки? Есть ли какие рекомендации на количество
файлов в директории, после которых уменьшается скорость или увеличивается нагрузка?
Ответы
Ответ 1
Введение
Разбивать однозначно стоит, если кол-во файлов превысит 5-7 тысяч. При 10к файлов
в одной папке файловой системе уже обычно "стает плохо" - открытие файла отрабатывает
дольше, растет нагрузка на диск. При 10к файлов в папке просто удалить все файлы уже
было накладно (то есть, просто rm * уже просто так не работает - баш пытается развернуть
* в список имен, этот список собрается долго, но потом он оказывается слишком длинным
и баш не может выполнить команду. Правда где то в 2011-2012 это чуточку пофикисили,
но все равно тяжело). У меня был опыт с подобным и несколько попыток переписать "правильно".
Теория
Стоит понимать, что разные файловые системы по разному реагируют. Например, ntfs
при открытии папки пытаются обновить время последнего доступа. Если файлов много, то
это на долго.
Сколько же теоретически можно вместить?
ntfs. Теоретический предел 2 в 32. Реальный - порядка 100k. Но пишут, что все тупит
сильно. Также в msdn написано, что GetTempFileName не будет работать, если в каталоге
с временными файлами больше 65535 файлов.
ext3. тут все сложно, максимальное кол-во файлов нужно смотреть.
ext4 - также, как и у ntfs, 4миллиарда.
Можно ещё почитать другой вопрос на SO - Максимальное количество файлов в папке Linux
и Windows
Способ первый
Способ складывания по датам плох - он не равномерный. То есть, будут папки, где лежит
много файлов и папок, где файлов почти нет. Так как папки в большинстве файловых систем
не бесплатны. Второй недостаток - сложность шардирования. То есть, если размер файлов
начинает превышать размер файловой системы, то начинаются проблемы. Ещё один недостаток
- дубликаты. Их очень сложно отслеживать. Но у этого способа есть только один хороший
плюс - легко найти старые файлы.
Способ второй
Но есть лучше способ, проверенный и используемый многими. Перед помещением файла
в "хранилище", для файла считается md5/sha1. Теперь, на основании этого хеша формируется
"путь для хранения". Я применял такой - первые два символа определяют папку, в котрой
создается папка, имя которой совпадает с следующими двумя символами. А сам файл храниться
внутри папки. Пример. Допустим есть файл "test.jpg" и md5 сумма от его содержимого
такая "b3e6b7290309113a2d2b392bf1e2084e". Само хранилище находиться в /srv/archiv.
Значит этот файл будет храниться по такому пути
/srv/archiv/b3/e6/b7290309113a2d2b392bf1e2084e_test.jpg
Я все таки оставил оригинальное имя файла. Иногда оно нужно. Но можно сохранять имена
файлов в базу, тогда можно будет и не писать его.
Плюсы этого способа.
равномерное распределение файлов по каталогам (обеспечивается хэш функцией).
легко разнести файлы по серверам. К примеру, первые два символа могут определять
имя сервера в кластере (а сами кластера подмонтированы внутрь).
легко выявляются дубликаты - у них будет одинаковый хэш.
если допустить, что файловая система легко держит 1000 файлов в папке, то вся система
сможет удерживать около 65миллионов файлов (256*256*1000). Если брать минимальные файлы
(по 4к), то это как минимум 250 гигабайт (плюс накладные расходы файловой системы,
обычно это 10-20 процентов от размера).
использование в паре с этим способом ещё и базы данных сильно расширяет возможности.
Минусы:
хэширование не бесплатно.
теоретически может оказаться, что у двух разных файлов может оказаться одинаковый хэш.
сложно удалить "старые файлы", но find может помочь.
Готовые решения
Есть пример реализации на php - хабр.
На посмотреть:
Хранение и доставка контента, Олег Илларионов (ВКонтакте)
Организация хранения данных, Кортунов
Ответ 2
Доброго! Я считаю, что разбить по директориям следует, но не по разделам сайта, а
по датам. И обязательно в американском формате: 2016-11-21 (или помесячно, как предлагает
Сергей). Применить nginx для обработки статики обязательно (этих самых картинок) -
тогда они будут отдаваться пользователю гораздо быстрее
Ответ 3
Всё зависит от файловой системы и ее настроек. Например в ext4 могут закончится inodes
см https://toster.ru/q/122827 или https://www.linux.org.ru/forum/general/4496222
Ответ 4
Более целесообразно сделать в таком виде: /2014/02/*.*.
Так более структурированно.
А на самом деле, по-моему, без разницы.
Есть практика, когда в директории более 400 000 файлов лежит, и ничего. Конечно,
если зайдешь через FTP и сделаешь просмотр файлов, ответ будет долгим...
Ответ 5
Если именем файла являются последовательные числа, предлагаю просто разбить по 1000
файлов в папке. Ну или подобрать желаемое значение на основе замеров производительности.
Для того, что складывается как архив и никогда не удаляется, такой способ подойдёт
идеально: равное число файлов в папках; просто понять, куда класть, просто достать
на основе id из базы.
Если файлы всё же удаляются, можно попробовать поменять местами результат и остаток
от деления, например, файл 12345 разместить как 345/12 вместо 12/345. По теории вероятностей
папки получатся примерно одинаковыми независимо от удалений (ну нельзя же сказать,
что файлы с чётными id удаляют чаще, чем с нечётными?).
На сайте backend отрабатывает за 50 мс, а фронт забирает кучу времени. В итоге полсекунд
на отображение страницы с использованием кэша, без кэша 700 мс. Есть правила и способы увеличить скорость отображения?
Для бека используется Laravel.
Ответы
Ответ 1
Оптимизация js одна из острых тем. Что Вы можете сделать:
1) Вы можете использовать встроенный профилировщик хрома http://prntscr.com/ejumd
и проанализировать какой скрипт/метод у Вас больше всего загружается и оптимизировать.
1.1) Есть например гугловский механизм PageSpead
2) Минимизация скриптов. По хорошему Вы можете минимизировать скрипты и стили с помощью инструментов для сборки grunt, gulp .
3) Если даже минимизация не помогает. Можно использовать AMD для асинхронной загрузки модулей. Для этого можно использовать, например, webpack
Ответ 2
Я бы посоветовал вам оптимизировать весь статический контент на сайте.
Сжатие графики
В вашем случае кроме сжатия стилей и скриптов посоветую сжимать и графику. К примеру
картинки можно легко сжать без потери качества только за счет удаление exif-данных. На реальном сайте можно сократить размер картинок в среднем на 70%, что на современном сайте равняется примерно 4 МБ. Пример на gulp:
var
gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
imageminJR = require('imagemin-jpeg-recompress'),
imageminSvgo = require('imagemin-svgo');
// Optimizing images
gulp.task('imagemin', function() {
gulp.src('./img/**/*')
.pipe(imagemin([
imageminJR({
method: 'ms-ssim'
}),
imageminSvgo({
plugins: [
{removeViewBox: false}
]
})
]))
.pipe(gulp.dest('./public/img/'))
});
А для браузеров, которые понимают легковесный формат webp (формат разработан Google), можно сделать еще такой вариант изображений:
var
gulp = require('gulp'),
webp = require('gulp-webp');
// Generate Webp
gulp.task('webp', function() {
gulp.src('./img/**/*')
.pipe(webp())
.pipe(gulp.dest('./public/img/'))
});
Оптимизация скриптов
Сперва объедините все скрипты в один файл и минифицируйте их. Это помет сократить количество HTTP-запросов и размер файлов:
var
gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
// Concat JS
gulp.task('js', function(){
gulp.src([
'./js/jquery.js',
'./js/wow.js',
'./js/menu.js',
'./js/scrollspy.js',
'./js/main.js',
'./js/temp/contact.bundled.js',
'./js/owl.carousel.js'
])
.pipe(concat('script.js'))
.pipe(uglify())
.pipe(gulp.dest('./public/js/'))
});
Оптимизация стилей
Кроме обычной минификации стилей можно использовать и продвинутую - объединять дубликаты классов и @media. Пример на gulp из моего [web-starter-kit][1]:
var
gulp = require('gulp'),
stylus = require('gulp-stylus'),
// Минифицирует CSS, объединяет классы. Не ломает CSS, в отличие от cssnano
который, к примеру, может неправильно выставлять z-index
csso = require('gulp-csso'),
// Объединяет все @media
cmq = require('gulp-combine-mq'),
// Сокращает CSS-селекторы
gs = require('gulp-selectors'),
// Проставляет вендорные префиксы
autoprefixer = require('gulp-autoprefixer'),
livereload = require('gulp-livereload'),
nib = require('nib');
// Compiling Stylus in CSS
gulp.task('css', function() {
gulp.src('./styl/*.styl')
.pipe(stylus({
use: nib()
}))
.pipe(cmq())
.pipe(csso())
.pipe(autoprefixer('last 3 versions'))
.pipe(gulp.dest('./public/css/'))
});
А если совсем делать нечего, то можно еще и селекторы сократить:
// Minify selectors
gulp.task('gs', function() {
var ignores = {
classes: ['active', 'menu', 'nav', 'slide', 'error', 'form-control'
'loader', 'showLoader', 'fadeLoader', 'webp', 'wow', 'owl-*', 'i-*'],
ids: '*'
};
gulp.src(['./public/**/*.css', './public/**/*.html'])
.pipe(gs.run({}, ignores))
.pipe(gulp.dest('./public/'))
});
Кстати, наверняка у вас есть классы, добавляющиеся через JS, поэтому предварительно стоит все такие классы вынести в переменную ignores.
Кеширование статики на стороне пользователя
Также бы посоветовал кешировать скрипты и стили на стороне пользователя, чтобы исключить их повторную загрузку, если они не изменились:
Header set Cache-Control "max-age=2592000"
И включить gzip сжатие на сервере:
# сжатие text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript
Ответ 3
Детали конкретно вашего случая вам надо смотреть в DevTools / Timeline и пользоватьс
каждым из методов с оглядкой туда, потому что общие советы по оптимизации в конкретном случае могут только навредить. К советам выше могу добавить следующие:
Посмотреть в таймлайне детали вашего critical rendering path. Постараться его максимально сократить:
Убрать с него блокирующий CSS. Выделить, например, при помощи critical стили дл
первого экрана и поместить их инлайном в →