Постоянная ссылка на эту статью:GitHub.com/H AOC также 942…
предисловие
Эти оптимизации применяются к
Vue CLI 2
а такжеVue CLI 3
, статья в основном основана наVue CLI 2
введение в то, какVue CLI 3
относится кwebpack
регулировка, я разместилvue-cli3-optimizationПод этот склад, и с подробными примечаниями, и дополнительным удобствомSass
в использованииloader
,использоватьSass
больше не нужно вводить переменные иmixin
Место очень хлопотное каждый раз@import
. Практические методы и эффекты этих схем оптимизации подробно описаны ниже:
Как и многие друзья, я развиваюсьVue
Проект также основан на официальномvue-cli@2
изwebpack
Шаблоны, но по мере того, как проект становится все больше и больше, зависимые сторонниеnpm
Пакетов становится все больше и больше, и файлы после сборки тоже будут становиться все больше и больше, особенноvendor.js
, даже достигая2M
о. В сочетании с одностраничным приложением это может привести к длительным белым экранам при низкой скорости интернета или ограниченной пропускной способности сервера. Чтобы решить эту проблему, я провел небольшое исследование и нашел три решения по оптимизации с очевидными эффектами без изменения бизнес-кода.CDN
+ Gzip
+ Prerender
. Я разобрал эти методы и поместил их вРепозиторий на гитхабеНа вышеизложенном намерение состоит в том, чтобы показать различные методы оптимизации в разных ветвях.Vue
Влияние на производительность проекта. Вы можете клонировать его напрямую и попробовать, и он также выигрывает от наличияgit
История, вы также можете легко просмотреть конкретные детали изменений. Ниже я покажу действие этих трех схем оптимизации на простом проекте.
Во-первых, подготовьтепростой проект
пройти черезvue-cli@2
изwebpack
Шаблон сгенерирован, только самое основноеVue
Набор из трех предметов ———vue
,vue-router
,vuex
и широко используетсяelement-ui
а такжеaxios
. Разделить два маршрута — «Домой» и «Контакты», черезaxios
Получить список контактов асинхронно и использоватьelement-ui
的表格展示。 непосредственныйbuild
, без всякой оптимизации, для справки.
1.1 Описание файла после сборки:
-
app.css
: Сжатие объединенных файлов стилей. -
app.js
: В основном включает элементы в проектеApp.vue
,main.js
,router
,store
и другие бизнес-коды. -
vendor.js
: в основном содержит зависимости проекта, такие какvuex
,axios
Дождитесь исходников сторонней библиотеки,поэтому этот файл такой большой.Следующим шагом будет изучение способов оптимизации этого куска.Ведь с развитием проекта их будет все больше и больше зависимые библиотеки. -
数字.js
: числа, начинающиеся с 0, 1, 2, 3 и т. д.js
файлы, эти файлы представляют собой блоки кода, вырезанные каждым маршрутом, потому что я разделил два маршрута и сделалОтложенная загрузка маршрута, так что есть два 0 и 1js
документ. -
mainfest.js
:mainfest
на английском естьсписок значений, который содержит логику для загрузки и обработки модуля маршрутизации.
1.2 Отключите кеш браузера и ограничьте скорость интернета доFast 3G
внизNetwork
график (работает локальноnginx
на сервере
можно увидеть неоптимизированныйbase
версия вFast 3G
Загрузка под сетью занимает около 7 секунд
два,оптимизация CDN
Для лучшего опыта разработки, перехват ошибок был
dev
а такжеbuild
дифференцированный см.git
записи, нижеследующее предназначено только для справки.
- будет зависеть от
vue
,vue-router
,vuex
,element-ui
а такжеaxios
Эти пять библиотек, все изменены, чтобы пройтиCDN
Ссылка для получения. с помощьюHtmlWebpackPlugin
, вы можете легко использовать синтаксис цикла вindex.html
вставлятьjs
а такжеcss
изCDN
Связь. здесьCDN
в основном используетсяjsDelivrкоторый предоставил.
<!-- CDN文件,配置在config/index.js下 -->
<% for (var i in htmlWebpackPlugin.options.css) { %>
<link href="<%= htmlWebpackPlugin.options.css[i] %>" rel="stylesheet">
<% } %>
<% for (var i in htmlWebpackPlugin.options.js) { %>
<script src="<%= htmlWebpackPlugin.options.js[i] %>"></script>
<% } %>
- существует
build/webpack.base.conf.js
Добавьте следующий код вCDN
В случае внедрения внешних файлов его все равно можно использовать в проектеimport
Синтаксис для введения этих сторонних библиотек, что означает, что вам не нужно менять код проекта, где имя ключаimport
изnpm
Имя пакета и значение ключа — это глобальная переменная, предоставляемая библиотекой.ссылка на документацию webpack.
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'element-ui':'ELEMENT',
'axios':'axios'
}
- удалить зависимости
npm
Мешок,npm uninstall axios element-ui vue vue-router vuex
- удалять
main.js
внутриelement-ui
связанный код.
Подробности можно посмотретьgit
история
2.1 Сравните файлы, созданные до и после добавления CDN:
Оптимизировано:
До оптимизации:Как можно заметить:-
app.css
: потому что больше не проходятimport 'element-ui/lib/theme-chalk/index.css'
, а напрямую черезCDN
импортировать по ссылкеelement-ui
стиль, делая файл маленькимbytes
уровень, так как теперь он содержит лишь небольшое количество предметовcss
. -
app.js
: Изменений почти нет, потому что это в основном код собственного бизнеса. -
vendor.js
: будет ли 5 зависеть отjs
Преобразовать все вCDN
После ссылки она уже достаточно мала1KB
, на самом деле в нем нет сторонних библиотек. -
数字.js
а такжеmainfest.js
: Эти файлы по своей природе маленькие, и изменения практически незначительны.
2.2 Аналогично, отключите кэш браузера и ограничить скорость сети кFast 3G
внизNetwork
график (работает локальноnginx
на сервере
Видно, что в том же сетевом окружении скорость загрузки увеличилась с исходных 7 секунд до нынешних 3 секунд, и улучшение очень очевидно. И что еще более важно, оригинальный способ, все
изjs
а такжеcss
Другие статические ресурсы запрашиваются нашими собственнымиnginx
Сервер, и теперь большинство статических ресурсов запрашиваются третьими лицамиCDN
ресурс,
Это может не только повысить скорость, но и значительно снизить нагрузку на полосу пропускания вашего собственного сервера при высокой степени параллелизма Представьте себе файл размером более 900 КБ на первом экране.
Теперь осталось всего 20 КБ, чтобы запросить собственный сервер!
три,Gzip-оптимизация
использоватьGzip
Есть два очевидных преимущества: во-первых, это может уменьшить пространство для хранения, а во-вторых, при передаче файлов по сети это может сократить время передачи.
3.1 Как включитьgzip
компрессия
включиgzip
Путь в основном заключается в изменении конфигурации сервера наnginx
В качестве примера сервер, на следующем рисунке используется тот же набор кода, только изменение сервераgzip
в случае состояния переключателяNetwork
Сравнительная таблица
Неоткрытыйgzip
сжатие:
включиgzip
сжатие:
включиgzip
Сжатые заголовки ответа
Из рисунка выше видно, чтоgzip
До и после разница в размере файла в три или четыре раза, а скорость загрузки также увеличилась с более чем 7 секунд до более чем 3 секунд.
прикреплятьnginx
метод конфигурации
http {
gzip on;
gzip_static on;
gzip_min_length 1024;
gzip_buffers 4 16k;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
}
3.2 Что интерфейс может сделать для gzip
мы все знаемconfig/index.js
есть одинproductionGzip
опция, так для чего она используется? мы пытаемся выполнитьnpm install --save-dev compression-webpack-plugin@1.x
, и положиproductionGzip
Установить какtrue
,опять такиbuild
, вставитьnginx
Под сервером посмотрите, в чем разница:
Мы обнаружим, что файлов стало больше после сборкиjs.gz
а такжеcss.gz
файл иvendor.js
стало меньше, что на самом деле потому, что мы включилиnginx
изgzip_static on;
опции,
еслиgzip_static
Установить какon
, то будет использоваться то же имя.gz
Файл не будет занимать ресурсы ЦП сервера для сжатия.
3.3 Быстрое построение фронтенда основано наnode
изgzip
Служить
не могу построитьnginx
Внешние партнеры среды также могут быстро запустить группу, выполнив следующие действия:gzip
изexpress
сервер
- воплощать в жизнь
npm i express compression
- Создайте новый в корневом каталоге проекта
serve.js
и вставьте следующий код
var express = require('express')
var app = express()
// 开启gzip压缩,如果你想关闭gzip,注释掉下面两行代码,重新执行`node server.js`
var compression = require('compression')
app.use(compression())
app.use(express.static('dist'))
app.listen(3000,function () {
console.log('server is runing on http://localhost:3000')
})
- воплощать в жизнь
node server.js
На картинке нижеexpress
включиgzip
Заголовки ответа:
Четыре,Пререндеринг
Всем известно: обычноеVue
После сборки одностраничного приложенияindex.html
просто пустая страница, содержащая корневой узел, когда все это необходимоjs
После завершения загрузки он начнет парсить и создаватьvnode
, а затем визуализировать реальныйDOM
. когда этиjs
Когда файл слишком большой и скорость сети очень низкая или возникает непредвиденная ошибка, появляется так называемый белый экран.Vue
Партнеры по развитию должны были столкнуться с этой ситуацией. И есть большой недостаток одностраничного приложенияSEO
Очень недружелюбно. Итак, как решить эти проблемы? ——SSR
Конечно это хорошее решение, но это также означает определенные затраты на обучение и эксплуатацию и обслуживание, а если у вас уже есть готоваяvue
одностраничное приложение, обратитесь кSSR
И это не бесшовный процесс. Такпредварительный рендерингкажется более подходящим. Просто установите одинwebpack
плагин + что-то простоеwebpack
Конфигурация может решить две вышеупомянутые проблемы.
4.1 Как преобразовать одностраничное приложение в предварительный рендеринг
- Тебе следует
router
установить какhistory
режиме и соответствующим образом настроить конфигурацию сервера,это не сложно. npm i prerender-spa-plugin --save-dev
Уведомление! ! ! Предварительный рендеринг требует загрузки
Chromium
, и по известным вам причинам материалы Google не могут быть загружены в Китае, поэтому они добавляются в корневой каталог.npmrc
Файл, чтобы использовать зеркало Taobao для загрузки.Ссылка на ссылку. Если ваш терминал можно перевести за границу, просто пропустите этот шаг, вам может понравитьсяМаленький самолет
- существует
build/webpack.prod.conf.js
Добавьте следующую конфигурацию ниже (без маршрутизации отложенной загрузки).
const PrerenderSPAPlugin = require('prerender-spa-plugin')
...
new PrerenderSPAPlugin({
staticDir: config.build.assetsRoot,
routes: [ '/', '/Contacts' ], // 需要预渲染的路由(视你的项目而定)
minify: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
decodeEntities: true,
keepClosingSlash: true,
sortAttributes: true
}
})
- Буду
config/index.js
внутриbuild
серединаassetsPublicPath
поле установлено на'/'
, это связано с тем, что при использовании предварительного рендеринга компонент маршрутизации будет скомпилирован в соответствующую папкуindex.html
, это будет зависеть отstatic
Файлы в каталоге, а если используется относительный путь, то и зависимый путь будет неправильным, что также требует, чтобы пререндеренный проект желательно размещать в корневом каталоге сайта (у меня уже есть эта яма вprerender-spa-plugin
упомянутый складISSUE
Да, но с помощьюpostProcess
, вы также можете написать регулярное выражение самостоятельно, если у вас есть это требование, вы можете обратиться к следующемуЯма, вызванная ленивой загрузкой роутинга). - Корректирование
main.js
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app', true) // https://ssr.vuejs.org/zh/guide/hydration.html
воплощать в жизньnpm run build
, ты найдешь,dist
Каталог уже не тот, что раньше, не только больше папок с тем же именем, что и указанный маршрут, но иindex.html
Статические страницы уже отображаются.
4.2 Каков эффект?
Как и прежде, мы по-прежнему отключаем кеш и ограничиваем скорость доFast 3G
(работает локальноnginx
на сервере). Видно, что вvendor.js
До завершения загрузки (около 700 кБ, в это время загружается только более 200 кБ) страница была полностью отрисована. На самом деле нужно простоindex.html
а такжеapp.css
После загрузки статическое содержимое страницы может быть хорошо отображено. Предварительный рендеринг, несомненно, является хорошим выбором для этих страниц с большим количеством статического контента.
4.3 Яма, вызванная ленивой загрузкой роутинга
Если ваш проект не реализованОтложенная загрузка маршрута, тогда вы можете быть уверены, что будете практиковать в соответствии с вышеизложенным. Но если вы используете его в своем проекте, вы должны увидетьwebpackJsonp is not defined
ошибка. это потому чтоprerender-spa-plugin
При рендеринге статической страницы она также будет выглядеть так<script src="/static/js/0.9231fc498af773fb2628.js" type="text/javascript" async charset="utf-8"></script>
такая асинхронностьscript
теги вводятся в сгенерированныйhtml
изhead
внутри этикетки. Это приводит к тому, что он предшествуетapp.js
,vendor.js
,manifest.js
(родыbody
снизу) выполнить. (async
просто не будет блокировать спинуDOM
синтаксический анализ, это не значит, что он был выполнен последним). и когда этиjs
После загрузки будетhead
Дубликаты ярлыков создают эту асинхронностьscript
Этикетка. Хотя эта ошибка не повлияет на программу, лучше всего не рендерить эти асинхронные компоненты напрямую в конечный результат.html
середина. к счастьюprerender-spa-plugin
при условииpostProcess
вариант, который может быть сгенерирован в реальномhtml
Прежде чем файл будет обработан, здесь я использую простое регулярное выражение, чтобы сделать эти асинхронныеscript
Выбраковка этикеток. Эта ветка уже используетсяОтложенная загрузка маршрута, вы можете напрямую просмотретьgit
история, файлы сравнения иbase
Ветвь изменяется, чтобы соответствующим образом скорректировать ваш проект.
postProcess (renderedRoute) {
renderedRoute.html = renderedRoute.html = renderedRoute.html.replace(/<script[^<]*src="[^<]*[0-9]+\.[0-9a-z]{20}\.js"><\/script>/g,function (target) {
console.log(chalk.bgRed('\n\n剔除的懒加载标签:'), chalk.magenta(target))
return ''
})
return renderedRoute
}
В дополнение к этому решению есть два решения, которые не рекомендуются:
- Просто не используйте ленивую загрузку маршрутизации.
- Буду
HtmlWebpackPlugin
изinject
поле установлено на'head'
,такapp.js,vendor.js,manifest.js
будет вставлен вhead
, а в асинхронномscript
над этикеткой. Но из-за обычногоscript
является синхронным, страница не может быть отображена до тех пор, пока все они не будут загружены, что нарушаетprerender
, а также нужноmain.js
Внесите следующие изменения, чтобы убедиться, чтоVue
можно найти при создании экземпляра<div id="app"></div>
, и он монтируется правильно.
const app = new Vue({
// ...
})
document.addEventListener('DOMContentLoaded', function () {
app.$mount('#app')
})
Суммировать
Хотя официальный скаффолдинг уже предоставляет множество готовых оптимизаций, таких какcss
сжать слияние,js
Сжатие и модульность, передача небольших изображенийbase64
Подождите, но мы можем сделать гораздо больше. Я не упоминал детали оптимизации на уровне кода и надеюсь предоставить вам некоторые практические решения. Вышеупомянутые три варианта более или менее принесут некоторую пользу вашему проекту. Оптимизация — это тоже метафизика, и есть много вещей, которые можно изучать. Я также надеюсь, что другие мелкие партнеры могут поделиться ценным мнением в области комментариев или непосредственно в моем проекте.vue-optimizationизbase
фиксация веткиPR
, Я приму хороший план и организую его. В настоящее время окончательный результат интеграции трех схем размещен вmasterПод веткой вы можете клонировать и развивать свой проект на этой основе.