предисловие
Фреймворк Vue помогает нам справляться с самой грязной и утомительной частью манипуляций с DOM при разработке интерфейса с помощью двусторонней привязки данных и технологии виртуального DOM.Нам больше не нужно думать о том, как манипулировать DOM и как манипулировать DOM больше всего. эффективно; но у проекта Vue все еще есть проблемы, такие как оптимизация первого экрана проекта и оптимизация конфигурации компиляции Webpack, поэтому нам все еще нужно уделить внимание оптимизации производительности проекта Vue, чтобы проект имеет более эффективную производительность и лучший пользовательский опыт. Эта статья подытожена автором через практику оптимизации реальных проектов.Я надеюсь, что у читателей появится вдохновение после прочтения этой статьи, чтобы помочь им оптимизировать свои собственные проекты. Содержание данной статьи разделено на следующие три части:
- Оптимизация уровня кода Vue;
- Оптимизация уровня конфигурации WebPack;
- Оптимизация на уровне базовых веб-технологий.
Я много работал над организацией в течение долгого времени, и я надеюсь вручную поставить лайк и поощрить ~
Адрес гитхаба:GitHub.com/ревматизм123/…, в котором собраны все блоги автора, и приглашаем подписаться и отметиться ~
1. Оптимизация на уровне кода
1.1, V-IF и V-Show различают использование сценариев
v-ifданастоящийусловный рендеринг, так как он гарантирует, что слушатели событий и подкомпоненты внутри условного блока будут правильно уничтожены и перестроены во время перехода;ленивый: если условие ложно при начальном рендеринге, ничего не делайте — блок условий не начнет рендеринг, пока условие не станет истинным в первый раз.
v-showГораздо проще, элемент всегда отображается независимо от начальных условий и просто переключается на основе свойства отображения CSS.
Поэтому v-if подходит для сценариев, которые редко меняют условия во время выполнения и не требуют частого переключения условий; v-show подходит для сценариев, требующих очень частого переключения условий.
1.2. Различайте сценарии использования вычисляемого и наблюдаемого
вычислено:Это вычисляемое свойство, зависит от значений других свойств, и вычисленное значение кэшируется.Только когда значение свойства, от которого оно зависит, изменяется, вычисляемое значение будет пересчитано при следующем получении вычисленного значения;
смотреть:Еще роль «наблюдения», аналогичная обратному вызову мониторинга некоторых данных, всякий раз, когда отслеживаемые данные изменяются, обратный вызов будет выполняться для последующих операций;
Сценарии применения:
-
Когда нам нужно выполнить числовое вычисление и зависеть от других данных, мы должны использовать вычисленный, потому что мы можем использовать функцию кэширования вычисленного, чтобы избежать повторного вычисления каждый раз, когда мы получаем значение;
-
Когда нам нужно выполнять асинхронные или дорогостоящие операции при изменении данных, мы должны использовать наблюдение, использование параметра наблюдения позволяет нам выполнять асинхронные операции (доступ к API), ограничивать частоту выполнения операции, и пока мы не получим окончательный результат, установить промежуточное состояние. Это все вещи, которые вычисляемые свойства не могут сделать.
1.3, обход v-for должен добавлять ключ к элементу и избегать одновременного использования v-if
(1) v-for обход должен добавить ключ к элементу
Когда данные списка просматриваются и визуализируются, необходимо установить уникальное значение ключа для каждого элемента, чтобы внутренний механизм Vue.js мог точно найти данные списка. Когда состояние обновляется, новое значение состояния сравнивается со старым значением состояния, чтобы быстрее найти различия.
(2) v-для обхода избегайте одновременного использования v-if
v-for имеет более высокий приоритет, чем v-if.Если вам нужно каждый раз проходить весь массив, это повлияет на скорость, особенно когда нужно отрисовать небольшую часть, при необходимости его следует заменить на вычисляемое свойство.
рекомендовать:
<ul>
<li
v-for="user in activeUsers"
:key="user.id">
{{ user.name }}
</li>
</ul>
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
Не рекомендуется:
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id">
{{ user.name }}
</li>
</ul>
1.4, длинный список оптимизаций производительности
Vue перехватит данные через Object.defineProperty, чтобы реализовать реакцию представления на изменения данных. Однако иногда наши компоненты представляют собой просто отображение данных и не будут меняться. Нам не нужен Vue для перехвата наших данных. В случае отображения данных это может значительно сократить время инициализации компонентов, так как же предотвратить захват наших данных Vue? Объект можно заморозить с помощью метода Object.freeze, и после того, как объект будет заморожен, его нельзя будет изменить.
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
1.5. Уничтожение событий
Когда компонент Vue уничтожается, он автоматически очищает свое соединение с другими экземплярами, отвязывает все свои инструкции и прослушиватели событий, но только для событий самого компонента. Если вы используете addEventListene и другие методы в js, он не будет автоматически уничтожен, нам нужно вручную удалить прослушиватели этих событий при уничтожении компонента, чтобы избежать утечек памяти, таких как:
created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
1.6 Ленивая загрузка ресурсов изображений
Для страниц со слишком большим количеством изображений, чтобы ускорить скорость загрузки страницы, нам много раз нужно сначала загрузить изображения, которые не отображаются в видимой области на странице, а затем загрузить их после прокрутки до видимой области. Таким образом, производительность загрузки страниц будет значительно улучшена, а также улучшится взаимодействие с пользователем. В нашем проекте мы используем плагин Vue vue-lazyload:
(1) Установите плагин
npm install vue-lazyload --save-dev
(2) Ввести и использовать в файле ввода man.js
import VueLazyload from 'vue-lazyload'
Затем используйте его непосредственно в vue
Vue.use(VueLazyload)
или добавить пользовательские параметры
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
(3) Измените атрибут src тега img непосредственно на v-lazy в файле vue, тем самым изменив режим отображения изображения на отображение отложенной загрузки:
<img v-lazy="/static/img/1.png">
Вышеупомянутое простое использование плагина vue-lazyload.Если вы хотите увидеть больше параметров плагина, вы можете проверить vue-lazyloadгитхаб-адрес.
1.7 Маршрутизация ленивой загрузки
Vue является одностраничным приложением, и может быть импортировано много маршрутов.Таким образом, файл, упакованный с помощью webpcak, очень большой.При входе на домашнюю страницу загружается слишком много ресурсов, и на странице появляется белый экран, который не способствует пользовательскому опыту. Было бы более эффективно, если бы мы могли разделить компоненты, соответствующие разным маршрутам, на разные блоки кода, а затем загружать соответствующие компоненты при доступе к маршруту. Это значительно улучшит скорость отображения над сгибом, но скорость других страниц может снизиться.
Ленивая загрузка маршрута:
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
1.8. Внедрение сторонних плагинов по запросу
Нам часто нужно внедрять сторонние плагины в проект. Если мы сразу введем весь плагин, это приведет к тому, что проект будет слишком большим. Мы можем использоватьbabel-plugin-component
, и тогда можно будет ввести только необходимые компоненты, чтобы уменьшить размер проекта. Ниже приведен пример внедрения библиотеки компонентов element-ui в проект:
(1) Сначала установитеbabel-plugin-component
:
npm install babel-plugin-component -D
(2) Затем измените .babelrc на:
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
(3) Внесите некоторые компоненты в main.js:
import Vue from 'vue';
import { Button, Select } from 'element-ui';
Vue.use(Button)
Vue.use(Select)
1.9 Оптимизация производительности бесконечного списка
Если ваше приложение имеет очень длинные или бесконечные списки прокрутки, вам нужно использовать оконную технологию для оптимизации производительности, нужно только отрисовывать небольшую область контента, сокращать время на повторный рендеринг компонентов и создавать узлы dom. Вы можете обратиться к следующим проектам с открытым исходным кодомvue-virtual-scroll-list а также vue-virtual-scrollerоптимизировать этот бесконечный список сценариев.
1.10 Рендеринг на стороне сервера SSR или предварительный рендеринг
Рендеринг на стороне сервера означает, что Vue рендерит весь фрагмент html из тега на стороне клиента для завершения работы на стороне сервера, а процесс возврата сформированного на стороне сервера html-фрагмента непосредственно клиенту называется серверным. рендеринг.
(1) Преимущества рендеринга на стороне сервера:
-
Улучшение SEO: поскольку содержимое страницы SPA получается через Ajax, и сканер поисковой системы не ждет асинхронного завершения Ajax перед обходом содержимого страницы, поэтому в SPA страница, полученная через Ajax, не может быть просканирована. содержание; и SSR напрямую возвращает отображаемую страницу с сервера (данные уже включены в страницу), поэтому сканер поисковой системы может сканировать отображаемую страницу;
-
Более быстрое время поступления контента (более быстрая загрузка на первом экране): SPA будет ждать загрузки всех js-файлов, скомпилированных с помощью Vue, прежде чем начать рендеринг страницы.Это занимает определенное время для загрузки файлов и т. д., поэтому первый экран рендеринг требует определенного времени; SSR напрямую рендерит страницу сервером и возвращает ее для отображения напрямую, не дожидаясь загрузки js-файлов и повторного рендеринга, поэтому SSR имеет более быстрое время поступления контента;
(2) Недостатки рендеринга на стороне сервера:
-
Дополнительные условия разработки: например, рендеринг на стороне сервера поддерживает только две функции-ловушки, beforeCreate и created, из-за чего некоторым внешним библиотекам расширений потребуется специальная обработка, прежде чем они смогут работать в приложениях рендеринга на стороне сервера; и их можно развернуть в любых статических приложениях. Полностью статическое одностраничное приложение SPA на сервере отличается, и приложение для рендеринга на стороне сервера должно находиться в операционной среде сервера Node.js;
-
Большая нагрузка на сервер: рендеринг полного приложения в Node.js, очевидно, требует больше ресурсов ЦП, чем сервер, который просто обслуживает статические файлы, поэтому, если вы планируете использовать его в среде с высоким трафиком, подготовьтесь к соответствующей нагрузке на сервер и используйте ваша стратегия кэширования мудро.
Если SEO и рендеринг первого экрана вашего проекта являются ключевыми показателями для оценки проекта, то вашему проекту требуется рендеринг на стороне сервера, чтобы помочь вам достичь наилучшей начальной производительности загрузки и SEO.Подробнее о том, как реализовать Vue SSR, вы можете обратитесь к другой статье автора »Vue SSR отправляется в пит-тур". Если вашему проекту Vue нужно улучшить только несколько маркетинговых страниц (например,/, /about, /contac
т и т. д.) для SEO, то вам может понадобитьсяпредварительный рендеринг, который просто генерирует статические файлы HTML для определенного маршрута во время сборки. Преимущество в том, что проще настроить предварительный рендеринг и можно рассматривать ваш интерфейс как полностью статичный сайт, вы можете использоватьprerender-spa-pluginВы можете легко добавить предварительный рендеринг.
2. Оптимизация на уровне Webpack
2.1. Webpack сжимает изображения
В проекте vue, помимоwebpack.base.conf.js
В url-загрузчике выставляется предельный размер для обработки изображения, а изображение меньше лимита конвертируется в формат base64, а остальные не работают. Таким образом, для некоторых больших ресурсов изображений при запросе ресурсов загрузка будет очень медленной, мы можем использоватьimage-webpack-loader
Чтобы сжать изображение:
(1) Сначала установите image-webpack-loader:
npm install image-webpack-loader --save-dev
(2) Затем настройте в webpack.base.conf.js:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use:[
{
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
}
2.2 Сокращение избыточного кода с ES6 до ES5
Плагин Babel будет внедрять некоторые вспомогательные функции при преобразовании кода ES6 в код ES5, например следующий код ES6:
class HelloWebpack extends Component{...}
Следующие две вспомогательные функции необходимы для преобразования этого кода в рабочий код ES5:
babel-runtime/helpers/createClass // 用于实现 class 语法
babel-runtime/helpers/inherits // 用于实现 extends 语法
По умолчанию Babel встраивает эти коды зависимых вспомогательных функций в каждый выходной файл.Если от этих вспомогательных функций зависит несколько файлов исходного кода, код этих вспомогательных функций будет появляться много раз, что приводит к избыточности кода. Чтобы не повторять код этих вспомогательных функций, вы можете передавать их при опоре на нихrequire('babel-runtime/helpers/createClass')
способ импортировать их, чтобы они появлялись только один раз.babel-plugin-transform-runtime
Плагин используется для достижения этой функции, заменяя соответствующие вспомогательные функции операторами импорта, тем самым уменьшая размер файла кода, скомпилированного babel.
(1) Сначала установитеbabel-plugin-transform-runtime
:
npm install babel-plugin-transform-runtime --save-dev
(2) Затем измените файл конфигурации .babelrc на:
"plugins": [
"transform-runtime"
]
Если вы хотите увидеть более подробную информацию о плагине, вы можете проверить babel-plugin-transform-runtimeПодробное введение.
2.3. Извлечение общедоступного кода
Если вы не заходили на каждую страницу сторонних библиотек и общедоступных модулей, извлеченных из проекта, то в проекте будут следующие проблемы:
- Одни и те же ресурсы загружаются повторно, что приводит к трате пользовательского трафика и затрат на сервер.
- Ресурсы, которые необходимо загрузить для каждой страницы, слишком велики, что приводит к медленной загрузке первой страницы веб-страницы и влияет на взаимодействие с пользователем.
Поэтому нам нужно извлечь общий код нескольких страниц в отдельные файлы, чтобы оптимизировать вышеуказанные проблемы. Webpack имеет встроенный плагин CommonsChunkPlugin, специально используемый для извлечения общих частей в нескольких чанках.Конфигурация CommonsChunkPlugin в нашем проекте выглядит следующим образом:
// 所有在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module, count) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
);
}
}),
// 抽取出代码模块的映射关系
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
Если вы хотите увидеть более подробную информацию о плагине, вы можете проверить CommonsChunkPlugin'sПодробное введение.
2.4 Предварительная компиляция шаблона
При использовании шаблона в DOM или строкового шаблона в JavaScript шаблон компилируется в функцию рендеринга во время выполнения. Обычно это достаточно быстро, но приложений, чувствительных к производительности, лучше избегать.
Самый простой способ прекомпилировать шаблоны — использоватькомпонент одного файла- Соответствующие настройки сборки автоматически позаботятся о предварительной компиляции, поэтому встроенный код уже содержит скомпилированную функцию рендеринга вместо исходной строки шаблона.
Если вы используете webpack и хотите разделить файлы JavaScript и шаблоны, вы можете использоватьvue-template-loader, который также может преобразовывать файлы шаблонов в функции рендеринга JavaScript в процессе сборки.
2.5. Извлеките CSS компонента
При использовании однофайловых компонентов CSS внутри компонента динамически внедряется через JavaScript в виде тегов стиля. Это имеет небольшие накладные расходы во время выполнения, и если вы используете рендеринг на стороне сервера, это может вызвать «мерцание нестилизованного содержимого (fouc)». Извлечение CSS для всех компонентов в один файл позволяет избежать этой проблемы, а также позволяет лучше сжимать и кэшировать CSS.
Обратитесь к соответствующей документации для этого инструмента сборки, чтобы узнать больше:
- webpack + vue-loader(шаблон веб-пакета vue-cli предварительно настроен)
- Browserify + vueify
- Rollup + rollup-plugin-vue
2.6. Оптимизация исходной карты
После того, как мы упакуем проект, мы упакуем код нескольких разрабатываемых файлов в один файл, а после сжатия, удаления лишних пробелов и компиляции babel скомпилированный код, наконец, будет использоваться в онлайн-среде, после чего будет большой разница между обработанным кодом и исходным кодом.Когда есть ошибка, мы можем найти только местоположение сжатого кода, но не можем найти код в среде разработки, что не очень хорошо для разработки.проблема, поэтому появилась sourceMap, это решить проблему плохо отлаженного кода.
Необязательные значения SourceMap:
Рекомендуемая среда разработки: Cheap-module-eval-source-map
Рекомендуется для производственной среды: Cheap-module-source-map
Причины следующие:
-
cheap: Информация столбца в исходном коде не имеет никакого эффекта, поэтому наш упакованный файл не хочет содержать информацию, относящуюся к столбцу, только информация строки может установить зависимости до и после упаковки. Поэтому, будь то среда разработки или производственная среда, мы надеемся добавить базовый тип дешевого игнорирования информации столбца до и после упаковки;
-
module: Будь то среда разработки или формальная среда, мы все надеемся найти конкретное местоположение исходного кода ошибки. Например, если файл Vue сообщает об ошибке, мы надеемся найти конкретный файл Vue, поэтому мы также нужна конфигурация модуля;
-
soure-map: source-map будет генерировать отдельный файл soucemap для каждого упакованного модуля, поэтому нам нужно добавить атрибут source-map;
-
eval-source-map: Скорость кода упаковки eval очень высока, потому что он не генерирует файл карты, но вы можете использовать eval-source-map в сочетании с eval.Использование eval-source-map сохранит файл карты как DataURL в упакованном файле js. Не используйте eval-source-map в производственной среде, потому что это увеличит размер файла, но в среде разработки вы можете попробовать это, потому что они быстро упаковываются.
2.7.Анализ результатов строительства
Код, выводимый Webpack, был очень нечитаемым, а размер файла был очень большим, что доставляло нам много головной боли. Для более простого и интуитивно понятного анализа выходных результатов в сообществе появилось множество инструментов визуального анализа. Эти инструменты графически представляют результаты более интуитивно, позволяя нам быстро понять, в чем проблема. Далее мы объясним инструменты анализа, которые мы используем в проекте Vue:webpack-bundle-analyzer
.
мы в проектеwebpack.prod.conf.js
Чтобы настроить:
if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
воплощать в жизнь$ npm run build --report
Отчет об анализе формируется следующим образом:
2.8. Компиляция и оптимизация проектов Vue
Если ваш проект Vue скомпилирован с помощью Webpack и вам нужна чашка кофе, возможно, вам нужно оптимизировать конфигурацию проекта Webpack, чтобы повысить эффективность сборки Webpack. Для получения подробной информации о том, как оптимизировать сборку Webpack проекта Vue, вы можете обратиться к другой статье автора."Практика оптимизации Webpack проекта Vue"
3. Базовая оптимизация веб-технологий
3.1 Включить сжатие gzip
gzip — это аббревиатура GNUzip, которая впервые использовалась для сжатия файлов в системах UNIX. Кодирование gzip по протоколу HTTP — это метод, используемый для повышения производительности веб-приложений, и веб-сервер и клиент (браузер) должны совместно поддерживать gzip. Текущие основные браузеры, Chrome, Firefox, IE и т. д. поддерживают этот протокол. Обычные серверы, такие как Apache, Nginx и IIS, также поддерживают его.Эффективность сжатия gzip очень высока, обычно достигая степени сжатия 70%.То есть, если ваша веб-страница имеет размер 30 КБ, после сжатия она станет примерно 9 КБ. .
Возьмем серверную часть на примере знакомого экспресса.Открыть gzip очень просто.Соответствующие шаги следующие:
- Установить:
npm install compression --save
- Добавьте логику кода:
var compression = require('compression');
var app = express();
app.use(compression())
-
Перезапустите службу и наблюдайте за заголовком ответа в сетевой панели.Если вы видите поля в красном кружке ниже, это означает, что gzip успешно включен:
3.2, кеш браузера
Для повышения скорости загрузки страниц пользователями очень необходимо кешировать статические ресурсы.В зависимости от того, нужно ли повторно инициировать запрос к серверу, правила кэширования HTTP делятся на две категории (обязательное кэширование и сравнение кеширование). Я еще не очень четко это знаю, можете сослаться на статью автора о HTTP-кэшировании"Глубокое понимание механизма и принципа кэширования HTTP", которые здесь повторяться не будут.
3.3. Использование CDN
Когда браузер загружает с сервера CSS, js, изображения и другие файлы, он должен подключаться к серверу, а у большинства серверов пропускная способность ограничена, при превышении лимита веб-страница долго не будет отвечать. CDN может загружать файлы через разные доменные имена, поэтому количество одновременных подключений для загрузки файлов значительно увеличивается, а CDN обеспечивает лучшую доступность, меньшую задержку в сети и скорость потери пакетов.
3.4. Используйте Chrome Performance, чтобы найти узкие места в производительности
Панель «Производительность» в Chrome может записывать данные и время выполнения js за определенный период времени. Шаги для анализа производительности страницы с помощью Chrome DevTools следующие.
- Откройте Инструменты разработчика Chrome и переключитесь на панель «Производительность».
- Нажмите «Запись», чтобы начать запись
- Обновите страницу или разверните узел
- Нажмите «Стоп», чтобы остановить запись.
Подробнее о производительности можнонажмите здесь, чтобы посмотреть.
Суммировать
Эта статья состоит из следующих трех частей: оптимизация на уровне кода Vue, оптимизация на уровне конфигурации веб-пакета и оптимизация на уровне базовой веб-технологии, чтобы представить, как оптимизировать производительность проектов Vue. Надеюсь, она будет вам полезна и вдохновила после прочтения этой статьи.Если есть какие-то недочеты, прошу покритиковать и исправить!
Я много работал над организацией в течение долгого времени, и я надеюсь вручную поставить лайк и поощрить ~
Адрес гитхаба:GitHub.com/ревматизм123/…, в котором собраны все блоги автора, и приглашаем подписаться и отметиться ~