Vue.js
July 22, 2021

Vue CLI: меняем индекс-файл при сборке

Те, кто уже работал с Vue.js при помощи Vue CLI, знают, что эта надстройка над вебпаком берёт очень многие вещи на себя, упрощая процесс сборки проекта и развития его экосистемы.

Можно, к примеру, добавить плагин для PWA и без лишних телодвижений превратить своё приложение в PWA. Также Vue CLI контролирует сборку приложения, создавая файловую структуру и заполняя файл index.html

Поворотный момент

Буквально неделю назад передо мной встала задача в результате сборки проекта при помощи Vue CLI получать не html-файл, а php, в котором реализуется некая серверная логика.

Поверхностное гугление показало, что можно использовать webpack-php-loader для сборки проекта. Однако это не решало мою проблему: насколько я понял, этот лоадер запускает php на машине, на которой происходит сборка, рендерит его и на выходе всё равно выдаёт html. Мне это не подходило, так как в php я работал с юзерагентом, передаваемым конкретным пользователем.

Решение - vue.config.js

В итоге мне удалось найти инструкцию, как указать файл, который при сборке будет считаться за “шаблон”, а также как переименовать выходной файл после сборки проекта. Делается это в файле vue.config.js.

Давайте определим себе задачу: закрыть доступ пользователям Internet Explorer 9.

Вкратце, этот файл позволяет (очень сложным путём, по-моему мнению) переопределить некоторые настройки вебпака для сборки проекта. Именно здесь мы и будем работать.

Если у вас ещё нет этого файла, создайте его в корне вашего проекта (на одном уровне с package.json) и поместите туда экспортный объект в синтаксисе Node.js:

// ./vue.config.js
module.exports = {

}

Далее, в папке src вашего проекта, создайте файл-шаблон, который будет использоваться при сборке. ВАЖНО: не удаляйте оригинальный файл index.html из папки public! Он нужен нам, чтобы работать в development-режиме и сохранить всякие прелести вроде хот-релоад.

Допустим, он называется index_template.php Скопируйте в него содержимое файла ./public/index.html, добавив где нужно логику на php.

// ./src/index_template.php
<?php
  $isIE9 = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 9.') !== false;

  if ($isIE9) {
    die('Браузер не поддердживается!');
  }
?>

<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.png">
    <title>Site title</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but website doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Здесь мы просто для примера определяем, точно ли IE9 перед нами, и если да, прекращаем выполнение скрипта.

Осталось прописать настройки в vue.config.js

Первым делом сообщим, что после наполнения файла содержимым сохранять его нужно не как index.html, а как index.php:

// ./vue.config.js
module.exports = {
    indexPath: 'index.php'
}

Эта настройка создаст в папке dist файл с нужным расширением.

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

// ./vue.config.js
module.exports ={
    indexPath: 'index.php',
    // Добавляем это:
        chainWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
          config
            .plugin('html')
            .tap(args => {
              args[0].template = './src/index_template.php'
              args[0].minify.removeAttributeQuotes = false
              return args
            })
        }
    }
}

Здесь мы обращаемся к html-загрузчику вебпака, и сообщаем, что при сборке в production шаблон теперь находится по адресу ./src/index_template.php. Также мы говорим, что при минификации кода не нужно удалять кавычки атрибутов, так как иногда это может нарушить работу php-скрипта.

На этом всё! Попробуйте запустить npm run build и вы увидите в папке dist файл index.php, полностью готовый к работе на продакшн-сервере!

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

Если у вас есть другое решение этого вопроса - я буду только рад с ним ознакомиться.