Обновление Angular с v8 до v13

Обновление Angular с v8 до v13

16 мая 2022 г.

В этом посте я расскажу, что я узнал при миграции приложений Angular с версии 8 на версию 13.


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


Я провел полтора года в подразделении, которое работало со многими приложениями и набором компонентов, созданных на Angular 8.



Angular JS


В последние 2 месяца прошлого года у нас были встречи с рабочей группой frontend, где всегда обсуждалась тема миграции приложений angular. Считается критической проблемой, особенно когда мы вспомнили о риске недавних случаев, таких как [уязвимость log4j] (https://medium.com/geekculture/log4j-vulnerability-in-detail-and-the-bigger-picture-db49f749009) в Java и разрыв библиотеки faker, который затронул проекты в AngularJS, официально не поддерживается.


Затем появилась возможность работать с техническим долгом. Когда мы делали эту работу, версия Angular была 13, и поскольку [Google поддерживает только до 2 предыдущих версий] (https://angular.io/guide/releases), версии Angular со 2 по 10 больше не поддерживались.


Политика и расписание поддержки Angular


Начальные рекомендации


Сохраняйте спокойствие и обновление NG


Мы используем опыт, который у нас был при переносе проекта компонента с Angular 8 на 13. Вот возможные подходы к миграции:


  1. Запускаем ng update с каждой версией, т.к. через него нельзя перейти с версии 8 сразу на 13, поэтому нужно выполнить эту команду для перехода с 8 на 9, с 9 на 10 и так далее. Преимущество заключается в том, что он преобразует код автоматически, но процесс прохождения такого количества версий оказывается более дорогостоящим, и поэтому он не рекомендуется в нашем случае, когда был разрыв в 5 версий. Это может быть наиболее подходящим вариантом для будущих миграций.

  1. Создайте новый проект в Angular 13 и скопируйте шрифты из старого проекта в Angular 8. Затем решайте проблемы по мере их возникновения. Этот подход был принят для переноса нашего проекта компонента, и мы рекомендуем его в этой ситуации.

Дорожная карта миграции


1) Установите последнюю версию Angular


``` ударить


npm установить -g @angular/cli


2) Создать новый проект


``` ударить


новый ново-проект


3) Скопируйте шрифты из старого проекта


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


Также обновите угловые версии package.json подпроектов (если есть).


4) Изменить настройки tsconfig.lib.json


Обновите файлы tsconfig.lib.json в подпроектах (если они есть), чтобы привести их в соответствие с текущими файлами tsconfig.json.


```javascript


«цель»: «es2017», «модуль»: «es2020», «lib»: [ «es2020», «дом»]


Распространенные ошибки конфигурации и решения


  • Произошло необработанное исключение: целевая точка входа "@novo-projeto" имеет недостающие зависимости: primeng/toast, primeng/button

Добавьте primeng в package.json. Это будет самая распространенная ошибка, потому что она будет возникать для всех различных зависимостей, которые еще не были включены, таких как bootstrap, ng-select и другие.


Старайтесь всегда определять версию зависимости, соответствующую текущей версии Angular в проекте.


Другими ситуациями, которые можно решить таким образом, являются ошибки типа:


Файл сценария ____ не существует.


или


Произошло необработанное исключение: ENOENT: нет такого файла или каталога, lstat ______


  • `"сборка ng" для библиотеки завершается с ошибкой "не поддерживает цель 'сборки'"

Скопируйте файл angular.json из старого проекта.


  • `npm WARN @angular-devkit/build-ng-packagr@0.1002.0 требует однорангового узла ng-packagr@^10.0.0, но ни один из них не установлен. Вы должны установить одноранговые зависимости самостоятельно.

build-ng-packagr был прекращен.


Удалите build-ng-packagr из package.json и измените tasks в angular.json, чтобы там, где есть @angular-devkit/build-ng-packagr:build, заменили @angular-devkit/build-angular:ng-packagr


  • `Импорт каталога '...
    ode_modules\@angular\compiler-cli
    gcc' не поддерживается при разрешении модулей ES, импортированных из ...
    ode_modules
    g-packagr\lib\utils< br>g-компилятор-cli.js. Вы хотели импортировать @angular/compiler-cli/ngcc/index.js?

Решается путем изменения версии ng-packagr в файле package.json на версию, соответствующую версии проекта Angular.


  • Не удается преобразовать объект типа i5.Scrolling Module в символ* ou *ОШИБКА: в целевой точке входа "primeng/dropdown" отсутствуют зависимости: @angular/cdk/scrolling

Это решается добавлением @angular/cdk в package.json.


  • ModuleError: Ошибка модуля (из ./node_modules/postcss-loader/dist/cjs.js)... Не удается разрешить "OpenSans-Regular.eot" в "...\dist\seus-components\css"

Установите postcss иpostcss-cli:


``` ударить


npm установить postcss postcss-cli


  • Ошибка: модуль не найден: ошибка: не удается разрешить 'chart.js/auto'

Установите chart и ng2-charts, который является оболочкой первого, работающего:


``` ударить


npm install --save ng2-charts и npm install --save chart.js


Распространенные ошибки, связанные с изменением кода, и решения


    • Тип ошибки модуля *: '"primeng"' не имеет экспортированного члена 'ConfirmDialogModule'

Ранние версии импорта primeng были такими:


```javascript


импортировать {Checkbox, MessageService, ConfirmDialogModule} из 'primeng/primeng';


Ссылки теперь более конкретные, поэтому их нужно исправить:


```javascript


импортировать {Checkbox} из 'primeng/checkbox'; импортировать { MessageService } из 'primeng/api'; импортировать {ConfirmDialogModule} из 'primeng/confirmdialog';


  • ошибка TS1323: динамический импорт поддерживается, только если для флага --module установлено значение 'es2020'

[Для поддержки динамического импорта] (https://stackoverflow.com/questions/56375703/angular-8-lazy-loading-modules-error-ts1323-dynamic-import-is-only-supporte) добавьте эту строку в tsconfig.json:


```javascript


"модуль": "следующий",


  • При работе с наблюдаемыми может возникнуть ошибка «Ошибка TS2554: Ожидается 1 аргумент, но получено 0»

[Происходит после перехода на rxjs 7] (https://stackoverflow.com/questions/68590899/rxjs-7-update-subject-expected-1-arguments-but-got-0). Это можно решить, передав значение fake:


```javascript


эта.тема.следующая("");


  • Ошибка: модуль не найден: преобразование в каталоги невозможно с полем экспорта (запрос был ./)

[Обычно это происходит после перехода на Angular 12] (https://stackoverflow.com/questions/69446231/module-not-found-error-resolving-to-directories-is-not-possible-with-the-expor). Это решается удалением «/» в конце imports или заменой двойных кавычек на одинарные. Пример:


До:


```javascript


импортировать { MsgCenterModule } из '@seu-componente/etc-client/';


После:


```javascript


импортировать { MsgCenterModule } из '@seu-componente/etc-client';


До:


```javascript


импортировать {ABCEnum, XYZEnum} из "../../tablea.constants";


После:


```javascript


импортировать {ABCEnum, XYZEnum} из '../../tablea.constants';


  • Ошибка типа: Модуль не найден: Ошибка: Не удается решить ‘dayjs’ / Ошибка: Модуль не найден: Ошибка: Не удается решить ‘inputmask’

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


``` ударить


npm установить dayjs --save


npm установить маску ввода --save


  • Ошибка типа: Объект, возможно, 'нулевой'. TS2531 для окна.документ

[Компилятор машинописного текста указывает] (https://stackoverflow.com/questions/55588968/type-error-object-is-possily-null-ts2531-for-window-document), что window.document.getElementById('content ') может возвращать NULL.


Поскольку это перенесенный код, который уже работал ранее, просто добавьте ! к этому коду:


```javascript


document.getElementById('content')!. внутреннийHTML = '';


  • ошибка NG8002: невозможно привязать к 'minWidth', так как это неизвестное свойство 'p-dialog'.

[Начиная с Primeng 9 некоторые свойства должны быть установлены в стиле] (https://github.com/primefaces/primeng/issues/8551). Поэтому в html, где он есть


[width]="600" [minWidth]="200" измените на [style]="{width: '600px', minWidth: '200px'}". Посмотрите на скобки [или ошибку setar в стиле CSS] (https://stackoverflow.com/questions/55867116/failed-to-set-an-indexed-property-on-cssstyledeclaration-index-property-sette).


  • `ошибка TS7006: параметр 'perfis' неявно имеет тип 'любой'

[Это потому, что] (https://stackoverflow.com/questions/43064221/typescript-ts7006-parameter-xxx-implicitly-has-an-any-type) переменные теперь должны иметь определенный тип, поэтому это необходимо в все точки в коде, чтобы установить их как любые или для более конкретного типа.


Иногда рекомендуется установить для "noImplicitAny" значение false в tsconfig.json, но это не рекомендуется.


  • ошибка TS2564: свойство 'titulo' не имеет инициализатора и не определено в конструкторе

Начиная с версии 2.7 компилятор машинописного текста [требует инициализации свойства/переменной] (https://stackoverflow.com/questions/49699067/property-has-no-initializer-and-is-not-definitely-assigned-in- конструкция).


Для решения этой проблемы существует [несколько подходов] (https://mariusschulz.com/blog/strict-property-initialization-in-typescript), но мы решили добавить «!» в определении переменной:


```javascript


общедоступный контейнер!: ViewContainerRef;


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


Примечание. В tsconfig.json compilerOptions можно определить как "strictPropertyInitialization": false, чтобы игнорировать эти ошибки и ускорить этот этап миграции. , но рекомендуется вернуться к true позже.


  • ошибка TS2322: введите 'string | null» нельзя присвоить типу «string | не определено'.

Очень часто при установке [свойства интерфейса как необязательного] (https://stackoverflow.com/questions/54496398/typescript-type-string-undefined-is-not-assignable-to-type-string), решается с помощью "!" как и предыдущая ошибка.


  • ошибка TS2322: тип 'Boolean' не может быть назначен типу 'boolean'... 'boolean' является примитивом, но 'Boolean' является объектом-оболочкой. Предпочитаю использовать логическое значение, когда это возможно

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


  • `ошибка NG3001: Неподдерживаемый частный класс MsgCenterComponent. Этот класс виден потребителям через SistemaClientModule -> MsgCenterComponent, но не экспортируется из точки входа в библиотеку верхнего уровня.

[Обычно это происходит с версии 9 Angular] (https://stackoverflow.com/questions/60121962/this-class-is-visible-to-consumers-via-somemodule-somecomponent-but-is-not-e). Добавьте в public_api.ts строку, соответствующую рассматриваемому классу, в этом примере:


экспорт * из './lib/msg-center/msg-center.component';


  • ошибка TS2314: универсальный тип 'ModuleWithProviders<T>' требует 1 аргумента(ов) типа

Измените код [следующим образом] (https://stackoverflow.com/questions/62755093/angular-error-generic-type-modulewithproviderst-requires-1-type-arguments) в этом примере:


```javascript


статический forRoot(): ModuleWithProviders


  • ошибка TS7030: не все пути кода возвращают значение.

Убедитесь, что значение возвращается в рассматриваемый код. Обычно это происходит в более обширных предложениях if.


  • ошибка TS2339: свойство 'throw' не существует для типа 'typeof Observable'

[Измените вызов на:] (https://stackoverflow.com/questions/68655492/throwerrorerror-is-now-deprecated-but-there-is-no-new-errorhttperrorresponse)


```javascript


вернуть throwError(() => ответ);


  • ошибка TS1192: модуль '".../node_modules/@types/uuid/index"' не имеет экспорта по умолчанию.

Установить зависимость:


``` ударить


npm i --save-dev @types/uuid


Измените вызов в коде на:


```javascript


импортировать * как uuid из 'uuid';


  • ошибка TS7053: Элемент неявно имеет тип "любой", поскольку выражение типа "строка" не может использоваться для индексирования типа "{}". Не найдена сигнатура индекса с параметром типа "строка" для типа "{}"

Вам нужно определить тип индекса, который имеет объект, изменив код на:


```javascript


страницыСтатус: {[индекс: строка]: любой} = {}


  • ошибка TS2322: тип 'строка' не может быть назначен типу 'число'

Это может происходить в атрибутах html-тега. Например, где были:


```javascript



Поставьте скобки:


```javascript



После обновления


  • [Код] (https://stackoverflow.com/questions/61541876/why-entrycomponents-is-not-necessary-anymore-in-angular-9-ivy-compiler)entryComponentsудаление: начиная с Angular 13 использование entryComponents больше не требуется

  • Удалите атрибуты [response] из p-dialog. В новой версии такие компоненты полностью адаптивны, поэтому использование этого атрибута прекращено.

Также опубликовано [здесь] (https://dev.to/windmateus/upgrading-from-angular-8-to-13-2lj1).



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE