# HTML и статические ресурсы

## HTML

### Стартовый файл

Файл `public/index.html` — шаблон, который будет обрабатываться [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin). На этапе сборки, ссылки на все ресурсы будут внедряться автоматически. Кроме того, Vue CLI автоматически внедряет подсказки для ресурсов (`preload/prefetch`), ссылки на манифест/иконки (когда используется PWA-плагин), и ссылки на ресурсы для файлов JavaScript и CSS, созданных во время сборки.

### Интерполяции

Поскольку стартовый файл используется в качестве шаблона, можно использовать [синтаксис шаблонов lodash](https://lodash.com/docs/4.17.10#template) для интерполяции значений в нём:

- `<%= VALUE %>` для неэкранированной подстановки;
- `<%- VALUE %>` для экранированного HTML-кода;
- `<% expression %>` для потоков управления JavaScript.

В дополнение к [значениям по умолчанию, предоставляемым `html-webpack-plugin`](https://github.com/jantimon/html-webpack-plugin#writing-your-own-templates), все [переменные окружения в клиентском коде](./mode-and-env.md#испоnьзование-переменных-окружения-в-кnиентском-коде) также доступны напрямую. Например, чтобы использовать значение `BASE_URL`:

```html
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
```

См. также:
- [publicPath](../config/#publicpath)

### Preload

[`<link rel="preload">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content) — это подсказки для браузера, указывающие на ресурсы, которые необходимо загрузить в первую очередь. Запросы на такие ресурсы будут отправлены ещё на этапе загрузки страницы, до начала её рендеринга.

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

Эти подсказки внедряются [@vue/preload-webpack-plugin](https://github.com/vuejs/preload-webpack-plugin) и могут быть изменены / удалены с помощью `chainWebpack` через `config.plugin('preload')`.

### Prefetch

[`<link rel="prefetch">`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ) — это подсказки для ресурсов, которые сообщают браузеру предварительно загрузить контент, который пользователь может посетить в ближайшем будущем, пока браузер находится в режиме ожидания после загрузки страницы.

По умолчанию приложение Vue CLI автоматически генерирует prefetch-подсказки для всех JavaScript-файлов, сгенерированных для асинхронных фрагментов (в результате [разделения кода с помощью динамических импортов `import()`](https://webpack.js.org/guides/code-splitting/#dynamic-imports)).

Эти подсказки внедряются [@vue/preload-webpack-plugin](https://github.com/vuejs/preload-webpack-plugin) и могут быть изменены / удалены с помощью `chainWebpack` через `config.plugin('prefetch')`.

::: tip Примечание для многостраничных конфигураций
При использовании многостраничной конфигурации имя плагина нужно изменить в соответствии со структурой `prefetch-{pagename}`, например `prefetch-app`.
:::

Например:

```js
// vue.config.js
module.exports = {
  chainWebpack: config => {
    // удаляем prefetch плагин:
    config.plugins.delete('prefetch')

    // ИЛИ
    // изменяем его настройки:
    config.plugin('prefetch').tap(options => {
      options[0].fileBlacklist = options[0].fileBlacklist || []
      options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
      return options
    })
  }
}
```

Когда prefetch плагин отключён, вы можете вручную указывать необходимые фрагменты для prefetch с помощью инлайновых комментариев для webpack:

```js
import(/* webpackPrefetch: true */ './someAsyncComponent.vue')
```

Webpack добавит prefetch-ссылки когда родительский фрагмент будет загружен.

::: tip Совет
Использование prefetch ссылок нагружает канал связи. Если у вас большое приложение с множеством асинхронных фрагментов (chunks) и ваши пользователи в основном используют мобильные устройства (а значит, чувствительны к использованию канала связи), вы можете пожелать отключить использование prefetch ссылок и вручную выбирать фрагменты для prefetch.
:::

## Отключение генерации index.html

При использовании Vue CLI с существующим бэкендом, вам может потребоваться отключить генерацию `index.html`, чтобы сгенерированные ресурсы могли быть использованы с другим документом по умолчанию. Для этого добавьте в файл [`vue.config.js`](../config/#vue-config-js) следующее:

```js
// vue.config.js
module.exports = {
  // отключение хэшей в именах файлов
  filenameHashing: false,
  // удаление плагинов webpack связанных с HTML
  chainWebpack: config => {
    config.plugins.delete('html')
    config.plugins.delete('preload')
    config.plugins.delete('prefetch')
  }
}
```

Однако, это не рекомендуется потому что:

- Жёстко заданные имена файлов затрудняют реализацию эффективного управления кэшированием.
- Жёстко заданные имена файлов плохо работают с разделением кода, что генерирует дополнительные файлы JavaScript с различными именами файлов.
- Жёстко заданные имена файлов не работают с [современным режимом](../guide/browser-compatibility.md#современный-режим).

Вместо этого вы должны использовать опцию [indexPath](../config/#indexpath), чтобы указать сгенерированный HTML в качестве шаблона вашего фреймворка на стороне сервера.

### Создание многостраничного приложения

Не каждое приложение должно быть одностраничным (SPA). Vue CLI поддерживает создание многостраничных приложений с помощью [опции `pages` в `vue.config.js`](../config/#pages). Код приложения будет эффективно переиспользоваться между его частями для оптимизации скорости загрузки.

## Обработка статических ресурсов

Статические ресурсы могут обрабатываться двумя различными способами:

- Импорт в JavaScript или указание ссылки на них в шаблоне/CSS с использованием относительных путей. Такие ресурсы будут обрабатываться webpack.

- Расположение в каталоге `public` и добавление ссылки на них с использованием абсолютных путей. Такие ресурсы просто копируются и не обрабатываются webpack.

### Импорты относительных путей

Если вы ссылаетесь на статический ресурс, используя относительный путь (должен начинаться с `.`) внутри JavaScript, CSS или `*.vue` файлов, то он будет добавлен в дерево зависимостей webpack. В процессе компиляции все URL ресурсов, такие как `<img src="...">`, `background: url(...)` и CSS `@import` будут обрабатываться **как зависимости модуля**.

Например, `url(./image.png)` будет преобразован в `require('./image.png')`, а тег шаблона

```html
<img src="./image.png">
```

будет скомпилирован в:

```js
h('img', { attrs: { src: require('./image.png') }})
```

Внутри используется `file-loader` для определения конечного расположения файла с хэшем версии и правильный путь относительно корня, а также `url-loader` для инлайн-встраивания ресурсов, чей размер меньше 4 КБайт, чтобы уменьшить количество HTTP-запросов к серверу.

Изменить размер можно через [chainWebpack](../config/#chainwebpack). Например, чтобы установить лимит в 10 КБайт:

```js
// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('images')
        .use('url-loader')
          .loader('url-loader')
          .tap(options => Object.assign(options, { limit: 10240 }))
  }
}
```

### Правила преобразования URL

- Если в URL абсолютный путь (например, `/images/foo.png`), он будет оставлен как есть.

- Если URL начинается с `.`, он будет интерпретироваться как запрос модуля относительно текущего каталога и разрешаться на основе структуры каталогов вашей файловой системы.

- Если URL начинается с `~`, то всё что после него будет интерпретироваться как запрос модуля. Это означает, что вы можете ссылаться на ресурсы даже внутри `node_modules`:

  ```html
  <img src="~some-npm-package/foo.png">
  ```

- Если URL начинается с `@`, то он также будет интерпретироваться как запрос модуля. Это удобно, потому что Vue CLI по умолчанию добавляет псевдоним `@` для `<projectRoot>/src`. **(только в шаблонах)**

### Каталог `public`

Любые статические ресурсы в каталоге `public` просто копируются в каталог итоговой сборки и не будут обрабатываться webpack. Вы должны ссылаться на них, используя абсолютные пути.

Обратите внимание, что мы рекомендуем импортировать ресурсы как часть дерева зависимостей модуля, чтобы они обрабатывались webpack со следующими преимуществами:

- Скрипты и стили минифицируются и объединяются, уменьшая количество сетевых запросов.
- Недостающие файлы вызывают ошибку сборки вместо ошибок 404 для пользователей.
- Имена файлов в результате будут с хэшем, поэтому не нужно беспокоиться о том, что браузеры используют старые версии из кэша.

Каталог `public` предоставляется для **крайних случаев**, поэтому, когда вы ссылаетесь на него по абсолютному пути, необходимо учитывать, где будет опубликовано ваше приложение. Если публикуется не в корне домена, нужно указать префикс для URL-адресов в [publicPath](../config/#publicpath):

- В `public/index.html` или других HTML-файлах, используемых `html-webpack-plugin` в качестве шаблонов, необходимо добавлять префикс в ссылки с помощью `<%= BASE_URL %>`:

  ```html
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  ```

- В шаблонах потребуется сначала передать `BASE_URL` в компонент:

  ```js
  data () {
    return {
      publicPath: process.env.BASE_URL
    }
  }
  ```

  А затем использовать в шаблоне:

  ```html
  <img :src="`${publicPath}my-image.png`">
  ```

### Когда использовать каталог `public`

- Вам требуется файл с определённым именем в каталоге сборки.
- У вас тысячи изображений и необходимо динамически ссылаться на их пути.
- Какая-нибудь библиотека несовместима с Webpack и у вас нет другого варианта, кроме как подключения её через тег `<script>`.
