Статьи

4 способа улучшить приложение Vue.js с помощью веб-пакета

Webpack — важный инструмент для разработки одностраничных приложений Vue.js. Он значительно упрощает рабочий процесс разработки за счет управления сложными этапами сборки и позволяет оптимизировать размер и производительность вашего приложения.

В этой статье я объясню четыре способа, которыми Webpack может улучшить ваше приложение Vue, в том числе:

  1. Отдельные файловые компоненты.
  2. Оптимизация сборки Vue.
  3. Управление кешем браузера.
  4. Разделение кода.

Как насчет Vue-CLI?

Если вы используете шаблон для сборки своего приложения из vue-cli , предоставляется готовая конфигурация Webpack. Они хорошо оптимизированы, и я не могу предложить никаких улучшений!

Но так как они работают так хорошо из коробки, вы, вероятно, не имеете большого представления о том, что они на самом деле делают, верно? Рассмотрим в этой статье обзор конфигурации Webpack, используемой в шаблонах vue-cli, поскольку они включают те же оптимизации, которые я обсуждаю здесь.

1. Отдельные файловые компоненты

Одной из уникальных особенностей Vue является использование HTML для шаблонов компонентов. Однако они связаны с внутренней проблемой: либо ваша HTML-разметка должна быть в неудобной строке JavaScript, либо ваше определение шаблона и компонента должно быть в отдельных файлах, что затрудняет их работу.

Vue предлагает элегантное решение под названием Single File Components (SFC), которое включает в себя шаблон, определение компонента и CSS в одном аккуратном файле .vue :

MyComponent.vue

<template>
  <div id="my-component">...</div>
</template>
<script>
  export default {...}
</script>
<style>
  #my-component {...}
</style>

SFC становятся возможными с помощью плагина vue-loader Webpack. Этот загрузчик разделяет языковые блоки SFC и передает каждый к соответствующему загрузчику, например, блок скрипта переходит к babel-loader , а блок шаблона — к собственному загрузчику Vue -template-loader, который преобразует шаблон в функцию JavaScript render.

Окончательный вывод vue-loader — это модуль JavaScript, готовый для включения в ваш пакет Webpack.

Типичная конфигурация для vue-loaderвыглядит следующим образом:

module: {
  rules: [
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
        loaders: {
          // Override the default loaders
        }
      }
    },
  ]
}

2. Оптимизация сборки Vue

Сборка только во время выполнения

Если вы используете только функции рендеринга в своем приложении Vue * и не используете шаблоны HTML, вам не нужен компилятор шаблонов Vue. Вы можете уменьшить размер вашего пакета, пропустив компилятор из сборки Webpack.

* Помните, что шаблоны отдельных файлов предварительно компилируются в процессе разработки для визуализации функций!

Существует только библиотека времени выполнения библиотеки Vue.js, которая включает все функции Vue.js, кроме компилятора шаблонов, которая называется vue.runtime.js . Это примерно на 20 КБ меньше, чем полная сборка, поэтому стоит использовать, если можете.

Сборка только во время выполнения используется по умолчанию, так что каждый раз, когда вы используете import vue from 'vue';в своем проекте, это то, что вы получите. Вы можете перейти на другую сборку, используя aliasопцию конфигурации:

resolve: {
  alias: {
    'vue$': 'vue/dist/vue.esm.js' // Use the full build
  }
},

Удаление предупреждений и сообщений об ошибках в производстве

Еще один способ уменьшить размер сборки Vue.js — удалить все сообщения об ошибках и предупреждения в работе. Это приводит к увеличению размера выходного пакета ненужным кодом, а также к затратам времени выполнения, которых лучше избегать.

Если вы посмотрите исходный код Vue, вы увидите, что блоки предупреждений зависят от значения переменной среды, process.env.NODE_ENVнапример:

if (process.env.NODE_ENV !== 'production') {
  warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
}

Если для process.env.NODE_ENV задано значение, productionто такие блоки предупреждений могут автоматически удаляться из кода минификатором во время процесса сборки.

Вы можете использовать DefinePlugin для установки значения process.env.NODE_ENV и UglifyJsPlugin для минимизации кода и удаления неиспользуемых блоков:

if (process.env.NODE_ENV === 'production') {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin()
  ])
}

3. Управление кэшем браузера

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

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

Файл продавца

Общие Куски плагин может отвязать ваш поставщик кода (например , зависимости , как библиотеки Vue.js, которые вряд ли изменится очень часто) из ваших приложения код (код , который может меняться при каждом развертывании).

Вы можете настроить плагин, чтобы проверить, есть ли зависимость от node_modulesпапки, и если это так, вывести его в отдельный файл vendor.js:

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    return module.context && module.context.indexOf('node_modules') !== -1;
  }
})

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

<script src="vendor.js" charset="utf-8"></script>
<script src="app.js" charset="utf-8"></script>

дактилоскопия

Когда меняется файл сборки, как мы можем разрушить кеш браузера?

По умолчанию, только когда срок действия кэшированного файла истекает, или когда пользователь вручную очищает кеш, браузер снова запрашивает файл с сервера. Файл будет загружен повторно, если сервер указывает, что файл был изменен (в противном случае сервер возвращает HTTP 304 Not Modified).

Чтобы сохранить ненужный запрос к серверу, мы можем изменять имя файла каждый раз, когда меняется его содержимое, чтобы браузер повторно загружал его. Простая система для этого — добавить «отпечаток» к имени файла, добавив хеш, например:

Название изображения

Плагин Common Chunks выдает «chunkhash», который обновляется, если содержимое файла изменилось. Webpack может добавить этот хеш к именам файлов, когда они выводятся:

output: {
  filename: '[name].[chunkhash].js'
},

Когда вы сделаете это, вы увидите, что ваши выходные файлы будут иметь имена вроде app.3b80b7c17398c31e4705.js .

Auto Inject Build Files

Конечно, если вы добавите хеш, вам придется обновить ссылку на файл в вашем индексном файле, иначе браузер не узнает об этом:

<script src="app.3b80b7c17398c31e4705.js"></script>

Это было бы чрезвычайно утомительным занятием вручную, поэтому воспользуйтесь плагином HTML Webpack, чтобы сделать это за вас. Этот плагин может автоматически вставлять ссылки на файлы сборки в ваш HTML-файл в процессе комплектации.

Начните с удаления ссылок на ваш файл сборки:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>test-6</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files should go here, but will be auto injected -->
  </body>
</html>

И добавьте плагин HTML Webpack в свою конфигурацию Webpack:

new HtmlWebpackPlugin({
  filename: 'index.html'
  template: 'index.html',
  inject: true,
  chunksSortMode: 'dependency'
}),

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

4. Разделение кода

По умолчанию Webpack выводит весь код вашего приложения в один большой пакет. Но если ваше приложение имеет несколько страниц, было бы более эффективно разделить код, чтобы код каждой отдельной страницы находился в отдельном файле и загружался только при необходимости.

Webpack имеет функцию под названием «разбиение кода», которая делает именно это. Достижение этого в Vue.js также требует асинхронных компонентов , а с Vue Router это еще проще .

Асинхронные компоненты

Вместо того чтобы иметь объект определения в качестве второго аргумента, асинхронные компоненты имеют функцию Promise, которая разрешает объект определения, например:

Vue.component('async-component', function (resolve, reject) {
  setTimeout(() => {
    resolve({
      // Component definition including props, methods etc.
    });
  }, 1000)
})

Vue будет вызывать функцию только тогда, когда компонент действительно должен быть визуализирован. Это также кеширует результат для будущих повторных рендеров.

Если мы спроектируем наше приложение так, чтобы каждая «страница» была компонентом, и мы сохранили определение на нашем сервере, то мы на полпути к разделению кода.

требовать

Чтобы загрузить код вашего асинхронного компонента с сервера, используйте requireсинтаксис Webpack . Это будет указывать Webpack собирать async-componentотдельный пакет при сборке, и, что еще лучше, Webpack будет обрабатывать загрузку этого пакета с помощью AJAX, поэтому ваш код может быть таким простым:

Vue.component('async-component', function (resolve) {
  require(['./AsyncComponent.vue'], resolve)
});

Ленивая Загрузка

В приложении Vue.js vue-router обычно является модулем, который вы используете для организации вашего SPA на несколько страниц. Ленивая загрузка — это формализованный способ разделения кода с помощью Vue и Webpack.

const HomePage = resolve => require(['./HomePage.vue'], resolve);

const rounter = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'HomePage',
      component: HomePage
    }
  ]
})