кеш браузера
Существует два типа кэширования браузера:
- Сильный кеш: Также известный как локальный кеш, не отправляйте запросы на сервер, напрямую используйте данные локального кеша клиента.
- Согласовать кеш: Также известный как кэш 304, он отправляет запрос на сервер, и сервер определяет, изменился ли запрошенный файл. Если изменений нет, будет возвращен код состояния 304, чтобы проинформировать клиента о необходимости напрямую использовать локальный кеш; если произошли изменения, запрошенный файл будет возвращен напрямую.
Процесс работы механизма кэширования браузера выглядит следующим образом:
Сильный кеш (локальный кеш)
Сильный кеш — самый тщательный кеш без отправки запроса на сервер, обычно используется для статических ресурсов, таких как css, js и изображения. После того, как браузер отправит запрос, он сначала определит, есть ли локальный кеш. Если кеша нет, отправьте запрос напрямую на сервер, если есть, определите, попадет ли кеш в сильный кеш, если попадет, используйте напрямую локальный кеш, если нет, отправьте запрос на сервер. сервер. Есть два способа определить, нужно ли попадать в локальный кеш:Expiresа такжеCache-Control.
Expires
Expires — это заголовок ответа http1.0, означающий время истечения срока действия локального кеша ресурса, которое устанавливается сервером. Если заголовок ответа, возвращаемый сервером в браузер, содержит поле Expires, браузер сравнивает текущее время со значением поля Expires при отправке запроса, чтобы определить, является ли кэш ресурса недействительным. Как показано ниже:
Dateпредставляет время, когда был запрошен ресурс,ExpiresПредставляет время истечения срока действия кэша ресурсов. Вы можете видеть, что сервер устанавливает время кэширования ресурсов на 5 минут. До 2017-02-10 07:53:19 запрос этого ресурса попадал в локальный кеш. Запросы сверх этого времени не попадают.
Cache-Control
Cache-Control — это новое поле в http1.0. Так как Expires устанавливает конкретное время истечения срока действия ресурса, если время сервера отличается от времени клиента, это вызовет путаницу в кеше.Например, считается, что время клиента скорректировано, поэтому разумнее установить срок действия срок ресурса. http1.1 добавлено поле max-age Cache-Control. Значение, представленное max-age, — это продолжительность периода действия ресурса, которая является относительной продолжительностью в секундах.
Cache-Control: max-age = 300 устанавливает время истечения ресурса на 5 минут. Когда браузер снова отправит запрос, он добавит время первого запроса к значению поля max-age и сравнит его с текущим временем, чтобы определить, нужно ли попадать в локальный кеш. max-age использует время клиента и более надежен, чем Expires. Если max-age и Expires присутствуют одновременно, max-age имеет приоритет. Cache-Control предоставляет больше полей для управления кэшированием:
- без хранения, не оценивает сильный кеш и кеш согласования, сервер напрямую возвращает полный ресурс
- без кеша, кеш не требует строгого суждения каждый раз, когда браузер отправляет запрос на проведение консультации для определения кеша
- общедоступный, указывающий, что ответ может быть кэширован любым буфером
- частный, обычно кешируется только для одного пользователя, не позволяет кешировать его какому-либо общему кешу, обычно используется для личной информации пользователя.
Согласовать кеш
Оценка согласованного кеша производится на стороне сервера, и основанием для оценки того, попал ли он, является то, изменился ли ресурс между этим запросом и последним запросом. Никакие изменения не попадают, изменения пропускают. Существует два способа определить, изменился ли файл:Last-Modified, If-Modified-Sinceа такжеEtag, если не совпадает.
Last-Modified, If-Modified-Since
Last-Modified — это поле заголовка ответа в http1.0, которое представляет время последнего изменения запрошенного ресурса. If-Modified-Since — это заголовок запроса http1.0, а значение If-Modified-Since — это значение Last-Modified, возвращенное сервером в последнем запросе. Когда браузер запрашивает ресурс в первый раз, сервер возвращает значение Last-Modified, и браузер кэширует это значение. Когда браузер запрашивает ресурс во второй раз, Last-Modified, используемый для кэширования, назначается If-Modified-Since и отправляется на сервер. Сервер определяет, равны ли If-Modified-Since и локальный сервер Last-Modified. Если они равны, ресурс не изменился и кеш согласования попал; если они не равны, ресурс изменился и кеш согласования не попал.
Видно, что запрос возвращает код состояния 304, указывающий, что Last-Modified ресурса не изменился, поэтому Last-Modified и If-Modified-Since этого запроса согласованы.
Etag, если не совпадает
Last-Modified и If-Modified-Since используют время, предоставленное сервером, поэтому они относительно надежны. Однако из-за точного времени модификации или того факта, что файлы генерируются регулярно, могут возникать определенные ошибки. Поэтому в http1.1 добавлены поля Etag и If-None-Match, чтобы улучшить оценку кэша согласования. Etag — это уникальный идентификатор ресурса, созданный в соответствии с содержимым файла ресурса. Как только содержимое ресурса изменится, Etag изменится. Идентификаторы на основе содержимого более надежны, чем идентификаторы на основе времени модификации. Значение If-None-Match — это значение Etag, возвращенное сервером по последнему запросу. Процесс оценки Etag и If-None-Match такой же, как и у Last-Modified и If-Modified-Since, а приоритет Etag и If-None-Match выше.
Проблемы, возникающие в технике
Преимущество сильного кэширования очевидно, нет необходимости отправлять запросы на сервер, что экономит много времени и трафика. Но есть проблема, что делать, если я хочу обновить ресурс в пределах срока действия кеша? Я также столкнулся с другой проблемой в проекте. В проекте есть четыре среды: тестовая среда, среда разработки, среда онлайн-подтверждения и онлайн-среда. Доменные имена четырех сред одинаковы, что приведет к проблеме совместного использования кеша четырех среды. Например, если сначала выполняется доступ к тестовой среде, index.js изменяется на браузер, а затем переключается на онлайн-среду. Онлайн-среда запросит index.js. В это время браузер будет использовать index.js из тестовая среда в локальном кеше, в результате чего код перепутался.
Суть проблемы в том, как аннулировать сильный кеш. Обычное решение — обновить имя файла, если имя файла отличается, браузер повторно запросит ресурс. Мы хотим убедиться, что имена файлов различаются в новых выпусках и разных средах. Один из методов добавляет номер версии к имени файла:
index.js?version=1
index.css?version=1
webpack предоставляет простой способ настройки кэширования.
// webpack.config.js
module.exports = {
entry: "main.js",
output: {
path: "/build",
filename: "main.[hash].js"
}
};
С помощью заполнителя хэша каждый раз, когда создается упакованный файл, из содержимого файла создается уникальный хеш, который добавляется к имени выходного файла. Если имеется несколько файлов ввода, вывод можно задать с помощью заполнителя имени:
// webpack.config.js
module.exports = {
entry: {
main:"main.js",
sub:"sub.js"
},
output: {
path: "/dist",
filename: "[name].[hash].js"
}
};
Проблема в настоящее время заключается в том, что хэш в настоящее время генерируется на основе содержимого двух файлов, а хэш, используемый двумя именами файлов, одинаков. Если изменить только один из main.js и sub.js, будут изменены имена обоих файлов, и оба файла будут повторно запрошены, что приведет к пустой трате ресурсов. webpack предоставляет chunkhash для замены хэша в ситуациях с несколькими входами. chunkhash — это хеш-значение, сгенерированное отдельно для каждого файла записи, что позволяет избежать описанной выше ситуации.
Webpack упаковывает динамически генерируемые имена файлов, нам нужно динамически вставлять ссылки на файлы в файл запуска html.html-webpack-pluginможет помочь мне решить эту проблему хорошо.html-webpack-plugin
HTML-файл может быть сгенерирован динамически, а файл ресурсов, упакованный и сгенерированный webpack, может быть динамически вставлен в HTML-файл.
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
entry: 'main.js',
output: {
path: '/dist',
publicPath: '/dist',
filename: 'main.[hash].js'
},
plugins: [new HtmlWebpackPlugin()]
};
По умолчанию вwebpackConfig.output.path
генерируется по путиindex.html
, сгенерированный HTML-файл выглядит следующим образом:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script src="main.2a6c1fee4b5b0d2c9285.js"></script>
</body>
</html>
Обычно файлы запуска html имеют настраиваемый контент, поэтомуhtml-webpack-plugin
Предоставляет функцию шаблона, в поле шаблона задается путь к шаблону,html-webpack-plugin
Используя шаблон в качестве шаблона, динамически добавьте путь к ресурсу, упакованный и сгенерированный webpack.
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
entry: 'main.js',
output: {
path: '/dist',
publicPath: '/dist',
filename: 'main.[hash].js'
},
plugins: [new HtmlWebpackPlugin(
{
template:'index.html'
}
)]
};
Исходное содержимое index.html (\index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>stat-front</title>
<link rel="stylesheet" href="//at.alicdn.com/t/font_ejl5slgdvtg74x6r.css">
</head>
<body>
<div id="app" class="app-root">
<router-view></router-view>
</div>
<!-- built files will be auto injected -->
</body>
</html>
Сгенерированное содержимое index.html (\dist\index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>stat-front</title>
<link rel="stylesheet" href="//at.alicdn.com/t/font_ejl5slgdvtg74x6r.css">
</head>
<body>
<div id="app" class="app-root">
<router-view></router-view>
</div>
<!-- built files will be auto injected -->
<script src="main.2a6c1fee4b5b0d2c9285.js"></script>
</body>
</html>
В начале статический index.html находится в корневом каталоге,webpack-dev-server
Установленный путь запуска — index.html в корневом каталоге.Если вы хотите запустить сгенерированный index.html, вам также необходимо установитьwebpackConfig.output.publicPath
:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
entry: 'main.js',
output: {
path: '/dist',
publicPath: '/',
filename: 'main.[hash].js'
},
plugins: [new HtmlWebpackPlugin(
{
template:'index.html'
}
)]
};
Таким образом, ресурсы, сгенерированные webpack-dev-server в памяти, сохраняются в корневом каталоге, а сгенерированный index.html будет запущен вместо оригинального index.html.