Одним из возможных недостатков объединения вашего одностраничного приложения с Webpack является то, что вы можете получить действительно большой пакетный файл, иногда размером в несколько мегабайт!
Проблема в том, что пользователь должен загрузить весь файл и запустить его, прежде чем он сможет увидеть что-либо на экране. Если пользователь подключен к мобильному устройству с плохим соединением, этот процесс может занять довольно много времени.
Разделение кода — это идея, что пакет может быть фрагментирован на более мелкие файлы, что позволяет пользователю загружать только тот код, который ему нужен, когда он ему нужен.
Например, глядя на эту простую веб-страницу, мы можем определить части приложения, которые нам не нужны при начальной загрузке:
Что делать, если мы задержали загрузку этих частей кода до окончания первоначального рендеринга? Это позволило бы пользователю видеть и взаимодействовать со страницей намного быстрее.
В этой статье я покажу вам, как Vue.js и Webpack можно использовать для разделения одностраничного приложения на файлы более оптимального размера, которые можно динамически загружать.
Вам также может понравиться:
Что нового в Vue?
Асинхронные компоненты
Ключом к разделению кода в приложении Vue.js являются асинхронные компоненты . Это компоненты, в которых определение компонента (включая его шаблон, данные, методы и т. Д.) Загружается асинхронно.
Допустим, вы объявляя компонент с помощью component
API, то есть Vue.component(name, definition)
. Вместо того, чтобы иметь определение объекта в качестве второго аргумента, асинхронные компоненты имеют функцию. Эта функция имеет две примечательные особенности:
- Это исполнитель обещания, то есть у него есть
resolve
аргумент. - Это фабричная функция, т.е. она возвращает объект (в данном случае определение компонента).
JavaScript
1
Vue.component('async-component', (resolve) => {
2
resolve({
3
template: '<div>Async Component</div>',
4
props: [ 'myprop' ]
5
});
6
});
Асинхронные компоненты являются первым шагом для разделения кода, потому что теперь у нас есть механизм абстрагирования разделов кода нашего приложения.
Динамическая загрузка модуля
Нам также понадобится помощь Webpack. Скажем, мы абстрагируем наше определение компонента в файл модуля ES6:
AsyncComponent.js
JavaScript
xxxxxxxxxx
1
export default {
2
template: '<div>Async Component</div>',
3
props: [ 'myprop' ]
4
}
Как мы можем получить наше приложение Vue.js, чтобы загрузить это? Вы можете попробовать что-то вроде этого:
JavaScript
xxxxxxxxxx
1
import AsyncComponent from './AsyncComponent.js'`;
2
Vue.component('async-component', AsyncComponent);
Однако это статично и разрешается во время компиляции. Нам нужен способ динамической загрузки этого в работающее приложение, если мы хотим получить преимущества разделения кода.
Импортировать()
В настоящее время невозможно динамически загрузить файл модуля с помощью JavaScript. Однако в настоящее время предлагается функция загрузки динамического модуля для ECMAScript import()
.
В Webpack уже есть реализация для него, import()
и он обрабатывает его как точку разделения кода, помещая запрошенный модуль в отдельный файл при создании пакета (на самом деле, в отдельный блок , но пока давайте думать об этом как о отдельном файле).
import()
принимает имя файла в качестве аргумента и возвращает обещание. Вот как мы могли бы загрузить наш модуль выше:
main.js
JavaScript
xxxxxxxxxx
1
import(/* webpackChunkName: "async-component" */ './AsyncComponent.js')
2
.then((AsyncComponent) => {
3
console.log(AsyncComponent.default.template);
4
// Output: <div>Async Component</div>
5
});
Примечание: если вы используете Babel, вам нужно добавить
syntax-dynamic-import
плагин, чтобы Babel мог правильно проанализировать этот синтаксис.
Теперь, когда вы строите свой проект, вы заметите, что модуль появляется в своем собственном файле:
Еще одно замечание: вы можете дать динамически импортированному блоку имя модуля, чтобы его было легче идентифицировать; просто добавьте комментарий перед именем файла так же, как в предыдущем примере.
Динамическая загрузка компонентов
Теперь соберите части вместе: поскольку import()
возвращает Promise, мы можем использовать его вместе с функциональностью асинхронного компонента Vue. Webpack будет связывать AsyncComponent отдельно и будет динамически загружать его в приложение через AJAX, когда приложение вызывает его.
main.js
JavaScript
xxxxxxxxxx
1
import Vue from 'vue';
2
Vue.component('async-component', (resolve) => {
4
import('./AsyncComponent.js')
5
.then((AsyncComponent) => {
6
resolve(AsyncComponent.default);
7
});
8
});
9
new Vue({
11
el: '#app'
12
});
index.html
HTML
xxxxxxxxxx
1
<div id="app">
2
<p>This part is included in the page load</p>
3
<async-component></async-component>
4
</div>
5
<script src="bundle.main.js"></script>
При первоначальной загрузке страница будет отображаться как:
HTML
xxxxxxxxxx
1
<div id="app">
2
<p>This part is included in the page load</p>
3
</div>
Когда main.js запускается, он инициирует запрос на модуль асинхронного компонента (это происходит автоматически, потому что import()
реализация Webpack включает код, который загрузит модуль с AJAX!).
Если вызов AJAX успешен и модуль возвращен, Promise разрешается, и компонент может быть визуализирован, поэтому Vue теперь повторно отобразит страницу:
HTML
xxxxxxxxxx
1
<div id="app">
2
<p>This part is included in the page load</p>
3
<div>Async Component</div>
4
</div>
Вот диаграмма, чтобы помочь вам визуализировать это:
Компоненты одного файла
Однако уникальный способ добиться разделения кода в Vue заключается в использовании любимого однофайлового компонента . Вот рефакторинг приведенного выше кода с использованием SFC.
AsyncComponent.vue
HTML
xxxxxxxxxx
1
<template>
2
<div>Async Component</div>
3
</template>
4
<script>
5
export default {
6
props: [ 'myprop' ]
7
}
8
</script>
Этот синтаксис для импорта еще лучше:
JavaScript
xxxxxxxxxx
1
new Vue({
2
el: '#app',
3
components: {
4
AsyncComponent: () => import('./AsyncComponent.vue')
5
}
6
});
Архитектура разделения кода
Это техническая часть пути. Теперь вопрос в том, как создать приложение для разделения кода?
Самый очевидный способ - это страница . Например, скажем, у вас есть две страницы в вашем приложении, домашняя страница и страница о программе. Эти страницы могут быть заключены в компоненты Home.vue и About.vue, и они могут быть точками разделения приложения.
Но есть и другие способы, например, вы можете разделить любые компоненты, которые отображаются условно (вкладки, модалы, раскрывающиеся меню и т. Д.) Или которые находятся ниже сгиба страницы.
В следующей статье я расскажу о различных архитектурах разделения кода для Vue.js SPA, так что следите за обновлениями!