Суббота, 22 апреля 2017 г.

Срок действия ваших ресурсов CSS и JS в далеком будущем гарантирует, что посетители загружают их из кеша как можно чаще, повышая скорость страницы и снижая затраты на пропускную способность. Но бывает сложно заставить посетителей загрузить новую версию до истечения срока действия старой. CDN усиливает проблему. Когда вы распространяете свои активы в CDN, такой как Cloudfront, серверы CDN по всему миру запрашивают новую копию только после истечения срока действия активов. Если вы хотите распространить новую версию файла в CDN до истечения срока действия старой, вам необходимо отправить запрос на аннулирование; аннулирование не происходит мгновенно и может даже стоить денег.

Вы можете решить эту проблему, добавив хэш содержимого файла к имени файла, например:

app-bundle-902805999c154c77880d.js

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

Сборщик ресурсов webpack может генерировать хэш содержимого исходного файла и добавлять его к выходному файлу, но теперь вам нужно изменить теги <script>, чтобы они указывали на новое имя файла. HTMLWebpackPlugin решает эту проблему, также генерируя тег <script>. Это также работает для включения ваших ресурсов в файл, который использует язык шаблонов, такой как Freemarker или Go templates, вместо простого HTML.

Установите HTMLWebpackPlugin:

npm i html-webpack-plugin

В файле конфигурации веб-пакета измените выходное имя, чтобы оно содержало хэш содержимого файла:

module.exports = { 
  ... 
  output: { filename: '[name]-bundle-[chunkhash].js' } 
  ... 
}

Затем импортируйте HTMLWebpackPlugin вверху конфигурации веб-пакета:

const HTMLWebpackPlugin = require('html-webpack-plugin');

и добавьте новую запись в массив plugins:

module.exports = { output: {...}, module: {...}, plugins: [new HtmlWebpackPlugin({ template: 'static/scripts-template.html', inject: false, filename: 'scripts.html'})] }

template задает путь к шаблону, который HTMLWebpackPlugin использует для создания файла, содержащего тег <script>. inject: false указывает плагину не вставлять теги include в вывод автоматически. filename задает путь, по которому HTMLWebpackPlugin генерирует собственный вывод.

В static/scripts-template.html используйте собственный интегрированный язык шаблонов HTMLWebpackPlugin для вывода нужных <script> тегов:

<% htmlWebpackPlugin.files.js.forEach(function(file) { %> <script src="<%= file %>"></script> <% }); %>

Это выводит тег <script> для каждого сгенерированного файла JavaScript. В качестве альтернативы, если вы просто хотите вывести каждый файл, который генерирует веб-пакет, включая CSS, вы можете оставить шаблон полностью пустым и установить inject: true, а HTMLWebpackPlugin автоматически вставит соответствующие теги <style> и <script>.

После запуска сборки веб-пакета сгенерированный файл scripts.html будет содержать только теги сценария. Затем вы можете импортировать его на любом языке шаблонов на стороне сервера, например, с помощью Go:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  <link href="styles.css" rel="stylesheet"></head>
  <body>
  <div id="app">
  </div>
  {{ template "scripts.html" }}
</body>
</html>

Таким образом, вы получаете преимущества кэширования хешированных имен файлов, не заменяя вручную пути в ваших HTML-файлах.

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

Первоначально опубликовано на www.ludovf.net.