Angular2 CLI огромный вендор комплект: как улучшить размер для прод?
У меня есть простое приложение, инициализированное angular-cli
,
Он отображает несколько страниц, относящихся к 3 маршрутам. У меня есть 3 компонента. На одной из этих страниц я использую модули lodash и Angular2 Http для получения некоторых данных (используя Rxjs Observables, map и подписку). Я отображаю эти элементы с помощью простого ngFor.
Но, несмотря на то, что мое приложение действительно простое, я получаю ОГРОМНЫЙ (на мой взгляд) пакет и карты. Я не говорю о версиях GZIP, но размер до GZIP. Этот вопрос только общие рекомендации.
Результаты некоторых тестов:
нг построить
Хеш: 8efac7d6208adb8641c1 Время: блок 10129ms {0} main.bundle.js, main.bundle.map (main) 18,7 кБ {3} [начальный] [обработанный]
кусок {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 кБ {4} [начальный] [визуализированный]
chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 кБ {4} [начальный] [обработанный]
кусок {3} vendor.bundle.js, vendor.bundle.map (vendor) 3,96 МБ [начальный] [обработанный]
кусок {4} inline.bundle.js, inline.bundle.map (inline) 0 байт [entry] [rendered]
Подождите: 10 Мб вендор-пакет для такого простого приложения?
ng build --prod
Хеш: 09a5f095e33b2980e7cc Время: 23455мс чанк {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (main) 18,3 кБ {3} [начальный] [обработанный]
кусок {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css, styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (styles) 154 кБ {4} [начальный]
chunk {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.bundle.map (scripts) 128 кБ {4} [начальный] [обработанный]
chunk {3} vendor.07af2467307e17d85438.bundle.js, vendor.07af2467307e17d85438.bundle.map (vendor) 3,96 МБ [начальный] [обработанный]
кусок {4} inline.a345391d459797f81820.bundle.js, inline.a345391d459797f81820.bundle.map (inline) 0 байт [entry] [rendered]
Подожди еще раз: такой схожий по размеру вендор для прод?
ng build --prod --aot
Хеш: 517e4425ff872bbe3e5b Время: блок 22856ms {0} main.95eadabace554e3c2b43.bundle.js, main.95eadabace554e3c2b43.bundle.map (main) 130 кБ {3} [начальный] [обработанный]
кусок {1} styles.e53a388ae1dd2b7f5434.bundle.css, styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 кБ {4} [начальный] [обработанный]
chunk {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a7564.bundle.map (scripts) 128 кБ {4} [начальный] [обработанный]
кусок {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map (vendor) 2,75 МБ [начальный] [обработанный]
кусок {4} inline.97c0403c57a46c6a7920.bundle.js, inline.97c0403c57a46c6a7920.bundle.map (inline) 0 байт [entry] [rendered]
ng build --aot
Хэш: 040cc91df4df5ffc3c3f Время: 11011мс чанк {0} main.bundle.js, main.bundle.map (main) 130 кБ {3} [начальный] [обработанный]
кусок {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 155 кБ {4} [начальный] [визуализированный]
chunk {2} scripts.bundle.js, scripts.bundle.map (scripts) 128 кБ {4} [начальный] [обработанный]
кусок {3} vendor.bundle.js, vendor.bundle.map (поставщик) 2,75 МБ [начальный] [обработанный]
кусок {4} inline.bundle.js, inline.bundle.map (inline) 0 байт [entry] [rendered]
Итак, несколько вопросов по развертыванию моего приложения на Prod:
- Почему комплекты поставщиков такие огромные?
- Angular-cli правильно использует встряхивание деревьев?
- Как улучшить этот размер пакета?
- Требуются ли файлы.map?
- Функции тестирования включены в пакеты? Мне не нужны они в продуктах.
- Общий вопрос: какие рекомендуемые инструменты для упаковки продуктов? Может быть, angular-cli (с использованием веб-пакета в фоновом режиме) не подходит лучше всего? Можно ли сделать БОЛЬШЕ?
Я искал много дискуссий о переполнении стека, но не нашел ни одного общего вопроса.
16 ответов
Обновление октябрь 2018
Поскольку этот ответ получил большую популярность, я подумал, что будет лучше обновить его с помощью более новых угловых оптимизаций:
- Как сказал другой ответчик,
ng build --prod --build-optimizer
это хороший вариант для людей, использующих меньше, чем Angular v5. Для более новых версий это делается по умолчанию сng build --prod
- Другой вариант - использовать чанкинг модулей / отложенную загрузку, чтобы лучше разделить ваше приложение на более мелкие порции.
- Механизм рендеринга Ivy, пока еще не запущенный в производство, скоро предложит лучшие размеры пакетов
- Удостоверьтесь, что ваши сторонние персонажи можно потрясти деревьями. Если вы еще не используете Rxjs v6, вам следует.
- Если ничего не помогает, используйте такой инструмент, как webpack-bundle-analyzer, чтобы увидеть, что вызывает раздувание в ваших модулях.
Некоторые утверждают, что использование компиляции AOT может уменьшить размер пакета поставщика до 250 КБ. Однако в примере BlackHoleGalaxy он использует компиляцию AOT и все еще остается с размером пакета поставщика 2,75 МБ с ng build --prod --aot
, В 10 раз больше, чем предполагаемые 250 КБ. Это не является нормой для приложений angular2, даже если вы используете v4.0. 2.75 МБ по-прежнему слишком велико для тех, кто действительно заботится о производительности, особенно на мобильном устройстве.
Есть несколько вещей, которые вы можете сделать, чтобы повысить производительность вашего приложения:
1) AOT & Tree Shaking (angular-cli делает это из коробки)
2) Использование Angular Universal AKA на стороне сервера рендеринга (не в cli)
3) Web Workers (опять же, не в cli, но очень востребованная функция)
см.: https://github.com/angular/angular-cli/issues/2305
4) Сервисные работники
см.: https://github.com/angular/angular-cli/issues/4006
Вам может не понадобиться все это в одном приложении, но вот некоторые из вариантов, которые в настоящее время присутствуют для оптимизации производительности Angular. Я верю / надеюсь, что Google знает о недостатках с точки зрения производительности и планирует улучшить это в будущем.
Вот ссылка, которая более подробно рассказывает о некоторых из упомянутых выше концепций:
https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294
Используйте последнюю версию angular cli и используйте команду ng build --prod --build-optimizer Это определенно уменьшит размер сборки для prod env.
Вот что оптимизатор сборки делает под капотом:
Оптимизатор сборки выполняет две основные задачи. Во-первых, мы можем пометить части вашего приложения как чистые, это улучшает встряхивание дерева, обеспечиваемое существующими инструментами, удаляя дополнительные части вашего приложения, которые не нужны.
Второе, что делает оптимизатор сборки, - это удаление Angular-декораторов из кода времени выполнения вашего приложения. Декораторы используются компилятором, они не нужны во время выполнения и могут быть удалены. Каждое из этих заданий уменьшает размер ваших пакетов JavaScript и увеличивает скорость загрузки вашего приложения для ваших пользователей.
Примечание: одно обновление для Angular 5, ng build --prod автоматически позаботится о вышеупомянутом процессе:)
Lodash может добавить кусок кода ошибки в ваш пакет в зависимости от того, как вы импортируете из него. Например:
// includes the entire package (very large)
import * as _ from 'lodash';
// depending on your buildchain, may still include the entire package
import { flatten } from 'lodash';
// imports only the code needed for `flatten`
import flatten from 'lodash-es/flatten'
Лично я все еще хотел меньшие следы от своих служебных функций. Например flatten
может способствовать до 1.2K
в ваш пакет, после минимизации. Итак, я собрал коллекцию упрощенных функций lodash. Моя реализация flatten
способствует вокруг 50 bytes
, Вы можете проверить это здесь, чтобы увидеть, работает ли он для вас: https://github.com/simontonsoftware/micro-dash
Во-первых, пакеты поставщиков огромны просто потому, что Angular 2 опирается на множество библиотек. Минимальный размер приложения Angular 2 составляет около 500 КБ (в некоторых случаях 250 КБ, см. Нижнюю статью).
Встряхивание дерева правильно используется angular-cli
,
Не включать .map
файлы, потому что используются только для отладки. Более того, если вы используете модуль горячей замены, снимите его, чтобы осветить поставщика.
Для производства я лично использую Webpack (и angular-cli тоже полагается на него), потому что вы действительно можете configure everything
для оптимизации или отладки.
Если вы хотите использовать Webpack
Я согласен, что на первый взгляд это немного сложно, но посмотрите учебники в сети, вы не будете разочарованы.
Остальное, использовать angular-cli
, которые делают работу очень хорошо.
Использование Опережающей компиляции является обязательным для оптимизации приложений и сокращения приложения Angular 2 до 250 КБ.
Вот репозиторий, который я создал ( http://github.com/JCornat/min-angular), чтобы протестировать минимальный угловой размер пакета, и я получил 384 КБ. Я уверен, что есть простой способ оптимизировать его.
Говоря о больших приложениях, использующих https://github.com/AngularClass/angular-starter, как и в предыдущем репо, размер моего пакета для больших приложений (более 150 компонентов) увеличился с 8 МБ (4 МБ без файлов карт) до 580 КБ.
Все ответы здесь устарели. Я только что создал стандартное шаблонное приложение Angular под названием «Tour of Heroes» с помощью Angular 13 CLI. Первоначальная сборка продукта заняла 10 секунд, последующая завершилась за 3 секунды. Размер пакета до Gzip составляет 244 КБ . Для сборки я использовал команду «ng build», никаких изменений в шаблонном проекте.
По этой теме много дезинформации. Выкладываем факты.
Размер папки сборки в байтах по фреймворку, файлы .map удалены, без gzip.
- Angular 13.0.0 - 264563 (новые angular-tour-of-heroes, scss, router)
- React 17.0.2 - 167074 (npx create-response-app my-app, без маршрутизатора)
В следующем решении предполагается, что вы используете папку dist/ с помощью nodejs. Пожалуйста, используйте следующий app.js на корневом уровне
const express = require('express'),http = require('http'),path = require('path'),compression = require('compression');
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.use(compression()) //compressing dist folder
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
})
const port = process.env.PORT || '4201';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log('Running at port ' + port))
Убедитесь, что вы установили зависимости;
npm install compression --save
npm install express --save;
Теперь создайте приложение
ng build --prod --build-optimizer
Если вы хотите еще больше сжать сборку, скажем, уменьшить на 300 КБ (приблизительно), то выполните следующий процесс;
Создайте папку с именем vendor
внутри src
папка и внутри папки продавца создать файл rxjs.ts
и вставьте в него приведенный ниже код;
export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';
А затем добавить следующее в tsconfig.json
файл в вашем приложении angular-cli. Тогда в compilerOptions
Добавьте следующий JSON;
"paths": {
"rxjs": [
"./vendor/rxjs.ts"
]
}
Это сделает ваш размер сборки слишком маленьким. В моем проекте я уменьшил размер с 11 МБ до 1 МБ. Надеюсь, поможет
обновление: 23.05.2022 с угловым 14 (RC1)
g-zip
а также
ng build --prod
это два решения, которые очень полезны. Это вам очень поможет. Но что, если бы вы сделали что-нибудь, старались изо всех сил. и все равно не работает? с помощью модуля ленивой загрузки. все еще не работает?
Вот ответ для вас. В настоящее время я обновляю свой проект Angular 13 до Angular 14, используя nx, и я узнаю, что «побочный эффект ствола» вызывает ваш
main.js
увеличение пучка. Решение простое.
изменить свой
tsconfig.json
построить модуль из"module": "commonjs"
к"module": "es2020"
или esnext (вы должны использовать объяснение es2020 здесь https://angular.io/guide/migration-update-module-and-target-compiler-options)добавить в
package.json
и посмотреть результат:
Почему?
полное объяснение здесь https://webpack.js.org/guides/tree-shaking/#conclusion и здесь и здесь /questions/53683262/napilnik-v-bochke-i-tryaska-dereva/53683272#53683272 . Но я могу сократить это для вас:
у вас есть модуль "А маленький" и "Б большой". вы пишете их в библиотеке пользовательского интерфейса и экспортируете их оба в
index.ts
файл. вы импортируете A в свой проект. окончательный пакет по-прежнему включает B, который вам не нужен.
Почему?
потому что
commonjs
не умный. с использованием
es2020
лучше, они понимают, что полезно, а что нет. Но они не уверены, должны ли они быть удалены или нет. вы добавляете
sideEffects: false
сказать им: «очистить мертвый код безопасно». и они сделали это. Тогда у вас маленький пакет. это можно использовать в любой современной среде JS, включая React, VueJS
прочитайте вопрос в проекте angular о побочном эффекте ствола здесь: https://github.com/angular/angular-cli/issues/16799https://github.com/angular/angular-cli/issues/16799
p/s: мой производственный веб-сайт angular находится здесь: https://awread.vn со 100 пользователями в день.
Еще один способ уменьшить пакет, это служить GZIP вместо JS. Мы пошли от 2,6 МБ до 543ko.
Я хотел бы поделиться с вами тем, как импортируемые библиотеки увеличивают размер dist. У меня был импортированный пакет angular2-moment, тогда как я мог делать все необходимое форматирование даты и времени, используя стандартный DatePipe, экспортированный из @ angular / common.
С Angular2-момент "angular2-moment": "^1.6.0",
chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 кБ {4} [начальный] [обработанный] chunk {1} main.e7496551a26816427b68.bundle.js (основной) 2,2 МБ {3} [начальный] [предоставленный] чанк {2} styles.056656ed596d26ba0192.bundle.css (стили) 69 байт {4} [начальный] [обработанный] чанк {3} vendor.62c2cfe0ca794a5006d1.bundle.js (поставщик) 3,84 МБ [начальный] [обработанный] чанк {4} inline.0b9c3de53405d705e757.bundle.js (inline) 0 байт [entry] [rendered]
После удаления Angular2-момента и использования вместо него DatePipe
chunk {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 кБ {4} [начальный] [обработанный] chunk {1} main.f2b62721788695a4655c.bundle.js (основной) 2,2 МБ {3} [начальный] [обработанный] chunk {2} styles.056656ed596d26ba0192.bundle.css (стили) 69 байт {4} [исходный] [обработанный] chunk {3} vendor.e1de06303258c58c9d01.bundle.js (поставщик) 3,35 МБ [начальный] [обработанный] кусок {4} inline.3ae24861b3637391ba70.bundle.js (inline) 0 байт [entry] [rendered]
Обратите внимание, что комплект поставки поставщика уменьшился на половину мегабайта!
Дело в том, что стоит проверить, что могут делать стандартные угловые пакеты, даже если вы уже знакомы с внешней библиотекой.
Работает 100% ng build --prod --aot --build-optimizer --vendor-chunk=true
Это уменьшило размер в моем случае:
ng build --prod --build-optimizer --optimization
Размер после выполнения этой команды уменьшился с 1,7 МБ до 1,2 МБ, но этого недостаточно для моей производственной цели.
Я работаю на платформе мессенджера Facebook, и приложения мессенджера должны быть меньше 1 МБ для работы на мессенджере. Я пытался найти решение для эффективной встряски дерева, но все же не повезло.
If you are using Angular 8+ and you want to reduce the size of the bundle you can use Ivy. Ivy comes as the default view engine in Angular 9 Just go to src/tsconfig.app.json and add the angularCompilerOptions parameter, for example:
{
"extends": ...,
"compilerOptions":...,
"exclude": ...,
/* add this one */
"angularCompilerOptions": {
"enableIvy": true
}
}
Взято из angular docs v9 (https://angular.io/guide/workspace-config):
По умолчанию определена производственная конфигурация, и команда ng build имеет параметр --prod, который строит с использованием этой конфигурации. Производственная конфигурация устанавливает значения по умолчанию, которые оптимизируют приложение несколькими способами, такими как объединение файлов, минимизация лишних пробелов,удаление комментариев и мертвого кода, а также переписывание кода для использования коротких загадочных имен ("минификация").
Кроме того, вы можете сжать все свои развертываемые файлы с помощью @angular-builders/custom-webpack: конструктора браузера, где ваш собственный webpack.config.js выглядит так:
module.exports = {
entry: {
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash].js'
},
plugins: [
new CompressionPlugin({
deleteOriginalAssets: true,
})
]
};
После этого вам нужно будет настроить свой веб-сервер для обслуживания сжатого контента, например, с помощью nginx, который вам нужно добавить в свой nginx.conf:
server {
gzip on;
gzip_types text/plain application/xml;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1000;
...
}
В моем случае папка dist уменьшилась с 25 до 5 МБ после простого использования --prod в ng build, а затем уменьшилась до 1,5 МБ после сжатия.
Если вы бежали ng build --prod
- у вас не должно быть vendor
файлы вообще.
Если я просто бегу ng build
- Я получаю эти файлы:
Общий размер папки ~14 МБ. Ваат!:D
Но если я убегу ng build --prod
- Я получаю эти файлы:
Общий размер папки 584К.
Один и тот же код. Я включил Ivy в обоих случаях. Angular - это 8.2.13.
Итак - я думаю, вы не добавили --prod
вашей команде сборки?
Убедитесь, что у вас есть конфигурация с именем "production" для ng build --prod, поскольку это сокращение от ng build --configuration = production. Моя проблема не решена, потому что проблема находилась прямо перед экраном. Я думаю, это может быть довольно распространенным явлением... Я интернационализировал приложение с помощью i18n, переименовав все конфигурации, например, в production-en. Затем я построил с помощью ng build --prod, предполагая, что используется оптимизация по умолчанию и должна быть близка к оптимальной, но на самом деле была выполнена только сборка ng, в результате чего получился пакет 7 МБ вместо 250 КБ.
У меня угловое загрузочное приложение с пружиной 5 + (application.properties 1.3+) с помощью сжатия (ссылка прилагается ниже) смогло уменьшить размер main.bundle.ts с 2,7 МБ до 530 КБ.
Также по умолчанию --aot и --build-optimizer включены в режиме --prod, вам не нужно указывать их отдельно.