Как се изгражда и публикува ъглов модул

Когато създадох ъгъл-async-local-storage, беше лесно да създам ъглов модул и да го използвам директно в приложението ми. Но тъй като може да помогне на други разработчици, исках да е модул за многократна употреба, опакован и консумиран като всеки друг ъглов модул.

Борях се с тази строителна част. Не открих почти никаква документация за това, затова се опитах да копирам как работи официалният Http модул. Сега вече е готово, споделям моя опит за създаването и публикуването на ъглов модул.

Тази публикация е за опитни разработчици, които вече знаят основните концепции на Angular и как да създадат основно приложение. Френска версия на тази публикация е достъпна тук.

Актуализация: ъглова 6

Тази публикация вече не е от значение. С Angular 6 създаването на ъглова библиотека е толкова просто, колкото ng g име на библиотеката. Вижте официалната документация за CLI.

От същия автор

  • Разширение на ъглови схеми за VS код: GUI за Angular CLI команди
  • @ ngx-pwa / local-storage: Първа ъглова библиотека за локално съхранение
  • Други ъглови библиотеки: @ ngx-pwa / offline & @ ngx-pwa / ngsw-схема
  • Други популярни ъглови публикации в Medium
  • Последвай ме в Туйтър
  • Ъглови обучения на място (базирани в Париж, така че уебсайтът е на френски, но моята биография на английски е тук и аз съм отворен да пътувам)

Създаване на вашия ъглов модул: клопки

Тази част е съвсем същата като създаването на модул в приложението ви: импортирайте необходимите модули, декларирайте компоненти, директиви или тръби или предоставете някои услуги. Има само няколко точки, които трябва да знаете.

Първо, никога не импортирайте BrowserModule. Вашият модул е ​​функционален модул, само крайният потребител трябва да импортира BrowserModule, в коренния модул на приложението. Ако имате нужда от общите директиви (* ngIf, * ngFor…), импортирайте CommonModule.

Ако вашият модул е ​​за създаване на нови компоненти, директиви или тръби, не забравяйте да ги експортирате. Декларираните са достъпни само във вашия модул.

Най-важното е да не смесвате компоненти / директиви / тръби и услуги в един и същ модул. Защо?

  • Услугата, предоставена в модул, ще бъде достъпна навсякъде в приложението, така че вашият модул трябва да бъде импортиран само веднъж, в коренния модул на потребителското приложение (като Http модула).
  • Експортиран компонент / директива / тръба ще бъде наличен само в модула, който импортира вашите, така че вашият модул трябва да бъде импортиран във всеки потребителски модул (корен и / или функционални модули), които се нуждаят от тях (като CommonModule).

Ако това не ви е ясно, трябва да публикувате моята друга публикация „Разбиране на ъгловите модули (NgModule) и техните обхвати“, тъй като това е важна (и объркваща) точка в Angular.

И накрая, спазвайте правилото Angular: никога не използвайте директно API-та на браузъра (като DOM) директно. Ако направите това, вашият модул няма да е съвместим с универсално сървърно изобразяване и други ъглови разширени опции. Ако наистина трябва да използвате специфични за браузъра API (localStorage…), трябва да опитате / да уловите грешки.

Експортиране на публичния API

Когато използвате официален модул Angular, просто имате една входна точка, за да импортирате всичко, което ви е необходимо (например „@ angular / http“).

Така че ще трябва да създадете файл index.ts, експортирайки всички публични API на вашия модул. Той трябва поне да съдържа вашия NgModule и вашите компоненти или услуги (потребителят ще трябва да ги импортира, за да ги инжектира там, където са необходими).

Компоненти / директиви / тръби няма да бъдат импортирани директно от потребителя, но трябва да ги експортирате, за да са съвместими с AoT (благодарение на Исак Ман за тази информация).

Инструменти за изграждане

Именно там започнах да се боря. Така успях да копирам как работят официалните ъглови модули, като HttpModule. Те използват:

  • typecript, чрез ъгловия компилатор (ngc), за транслиране,
  • rollupjs за опаковане,
  • uglify-js за минимизиране.
npm install @ angular / компилатор @ angular / compiler-cli typecript сбор uglify-js --save-dev

Конфигурация на TypeScript

Ето tsconfig.json на моя модул:

Има някои важни разлики с вашия класически tsconfig.json:

  • изрични „пътища“ към други модули, които използвате, са необходими, тъй като крайният пакет няма да ги включва директно (повече за това по-късно).
  • "angularCompilerOptions": {"strictMetadataEmit": true} е необходим, за да е AoT съвместим.
  • "декларация": true е важно за генериране на файлове с дефиниции на типа, така че потребителят ще има Intellisense за вашия модул.
  • "noImplicitAny": true и "strictNullChecks": true се препоръчват, за да се избегнат грешки и да бъдат съвместими с всички потребителски конфигурации. "noImplicitAny": true трябва да се спазва от Angular 4.0, а "strictNullChecks": true, започващ от Angular 4.1.
  • "module": "es2015" е важно за производителността, а "sourceMap": true за отстраняване на грешки, но тук няма нищо конкретно.
  • "stripInternal": истински избягвайте безполезни декларации за вътрешни API и "skipLibCheck": true избягвайте да бъдете блокирани от (безобидни) грешки в библиотеките, които използвате.

Конфигурация за събиране

Ъгловите модули се доставят във UMD формат, така че вашият rollup.config.js трябва да бъде зададен впоследствие. Ето един пример:

Скриптът за въвеждане е transpiled index.ts, така че трябва да съответства на вашата конфигурация TypeScript. bundles / modulename.umd.js е конвенционалният път и име, използван от ъглови модули.

За събирането е необходим moduleName за UMD формат. Това ще бъде JavaScript обект, така че не използвайте специални символи (без тирета).

Тогава, там е важната точка. Вашият модул използва ъглови неща (поне декоратора на NgModule), но пакетът ви не трябва да включва Angular.

Защо? Ъгловата вече ще бъде включена от потребителското приложение. Ако вашият модул също го включва, той ще бъде там два пъти и ще има фатални (и неразбираеми) грешки.

Затова трябва да зададете Angular като глобален. И трябва да знаете името на UMD модула за всеки модул. Следва тази конвенция: ng.modulename (ng.core, ng.common, ng.http ...).

Същото важи и за RxJS, ако вашият модул го използва. И имената на модулите са доста бъркотия тук. За класове (наблюдателни ...), това е Rx. За операторите (карта, филтър ...) това е Rx.Observable.prototype. За директните методи на класове (на, отEvent…), това е Rx.Observable.

Сграда, най-накрая

Сега можете да изградите своя пакет модули. Можете да запишете командни редове в npm скриптове:

Тогава:

npm run build

Обърнете внимание, че преписването не се извършва директно от TypeScript, трябва да използвате Angular компилатор (ngc): той е TypeScript с някаква допълнителна ъглова магия.

Публикуване в npm

Не публикувайте всичко в npm, а само директорията dist.

Ще трябва да създадете нов и специфичен dist / package.json. Например :

Някои конкретни точки:

  • "версия" трябва да следва семантична версия. Всяка промяна в пробив означава главно увеличение на броя (дори ако е малка промяна). И когато промените модула си, за да сте в крак с Angular, това е незначително увеличение на броя.
  • "main" и "module" пътища са необходими за вноса на потребители. Пътят за "типизиране" е за Intellisense.
  • "лиценз": "MIT": лицензът с отворен код е важен или вашият модул е ​​безполезен. Angular използва лиценза за MIT и трябва да се придържате към него.
  • Ъгловите модули, които сте използвали, ще бъдат изброени в peerDependitions. Все пак следвайте semver, със знака ^ или модулът ви ще бъде остарял всеки път, когато ъпгрейди ъгъл. За други библиотеки (RxJS, zone.js ...) можете да видите текущите изисквания на Angular тук.

Не забравяйте да напишете README с документацията на вашия API. В противен случай вашият модул е ​​безполезен. Можете да използвате библиотека като copyfiles, за да копирате вашата README от вашата директория на коренния проект (показва се в Github) в вашата директория dist (показва се в хранилище npm).

И с конфигуриран npm акаунт, сега можете да публикувате своя модул:

cd dist
npm публикуване

И по всяко време, когато трябва да актуализирате своя модул, просто възстановете, променете номера на версията, актуализирайте регистъра на промените и публикувайте отново.