Ръководството „от нулата“ за създаване на уеб компоненти с Angular (в 10 стъпки)

Напоследък имаше много от говори за възможността за създаване на уеб компоненти от обикновен Angular компонент, но досега има много по-малко практически примери за това как да се изгради такъв – в смисъл на действително създаване на пакета които можете просто да добавите към html и да имате работещ потребителски елемент. Би трябвало да е много лесно в бъдеще, но засега трябва да се задоволим с малко ръчно бърникане.

Препоръчвам ви да прочетете/гледате свързани презентации, за да научите за специфичните възможности на технологията (спойлер: те са безкрайни 😉), но междувременно нека изградим компонент за себе си, с фокус върху минимални инструменти, от които трябва да се нуждаем:

Забележка:
Това е подход от нулата. Ще последвам тази статия с настройка, базирана на Angular CLI проект, в отделна публикация по-късно тази седмица.
Актуализация:Статията, базирана на CLI е готова!

1. Инициализирайте проекта:

mkdir angular-element-demo
cd angular-element-demo
npm init -y demo

2. Инсталирайте основните зависимости:

Добавете минималното количество редовни членове на семейството на Angular:
(имаме нужда от най-новата, все още не официално пусната версия 6 за тази…
актуализация:Angular 6 е пуснат , актуализирах статията, за да отразя това)

npm i @angular/{core,compiler,common,platform-browser,platform-browser-dynamic}

… и приятели:

npm i core-js rxjs zone.js

Сега за елементите ще ни трябва Angular библиотеката и polyfill:

npm i @angular/elements @webcomponents/custom-elements

3. Инсталирайте dev dependencies

Да видим: ще ни трябва Angular компилатор, webpack, ngtools, за да ги комбинираме... о, и TypeScript:

npm i -D @angular/compiler-cli @ngtools/webpack webpack webpack-cli typescript@~2.7

Добре, достатъчно инсталиране за сега. Сега нека напишем конфигурации.

4. Конфигурирайте webpack

Отново, колкото е възможно по-малка конфигурация – всичко, което не е необходимо, пропускаме и използваме каквото и да е по подразбиране, предоставено от webpack 4:
(никога не сте чували за webpack? Вижте неговата документация за подробности относно набора от опции)

Минималното webpack.config.js, от което се нуждаем, е:

module.exports = {
  module: {
    rules: [{test: /\.ts$/, loader: '@ngtools/webpack'}]
  },
  resolve: {
    extensions: ['.ts', '.js']
  },
  plugins: [
    new NgCompilerPlugin({
      tsConfigPath: './tsconfig.json',
      mainPath: './src/index.ts'
    })
  ],
  mode: 'production',
  stats: 'errors-only'  // there are… few deprecation warnings that 
};                      // I expect to go away soon (Angular 6.0?)
                        // for now, let's not see them ;)

5. Конфигурирайте TypeScript

Нашият минимален жизнеспособен tsconfig.json изглежда така:

{
  "compileOnSave": false,
  "compilerOptions": {
    "sourceMap": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "target": "es2015",
    "lib": ["es2017", "dom"]
  }
}

Това е краят на необходимата ни настройка! Не беше ли лошо, надявам се?

Сега да преминем към кода. Нашият пакет ще бъде изграден само от 3 изходни файла:
дефиницията на компонента, дефиницията на модула и кода за стартиране.

6. Дефиниране на компонент

Можете да поставите наистина почти всеки компонент тук, важното е да използвате ViewEncapsulation.Native, така че стиловете да са групирани в един js файл с шаблона и логиката на компонента. Освен това няма абсолютно нищо специално за него.

За нашата цел ще използваме нещо просто, което също така ще илюстрира Input и Output логиката на Angular, работеща в рамките на собствения уеб компонент.

src/button.component.tsизглежда така:

7. Дефиниране на модул — интересната част

Така че това е частта, която е най-важната и специфична за Angular Elements от цялата тази настройка. Ще използваме функцията createCustomElement на Angular, за да създадем клас, който може да се използва с естествената customElements.define функционалност на браузърите.

Angular документацията описва това най-добре:

createCustomElement Създава клас, който капсулира функционалността на предоставения компонент и използва конфигурационната информация, за да предостави повече контекст на класа. Взема входовете и изходите на фабриката за компоненти, за да ги преобразува в правилния персонализиран елемент API и да добавя кукички към промените на входа.

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

Файлътsrc/button.module.ts:

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

Също така трябва да кажем на Angular да използва този модул за стартиране, оттук и метода ngDoBootstrap.

8. Bootstrap код

Що се отнася до bootstrap, тук не се случва нищо изключително сложно. Просто вашият типичен код за стартиране, само с добавяне на подложка на потребителски елемент.

Файлътsrc/index.ts:

9. Изградете

Всички части вече са на мястото си, просто трябва да изстреляме webpack. Нека добавим скрипт за изграждане към package.json файл:

"scripts": {
  "build": "webpack"
}

и стартирайте npm run build.

Добре, сега какво? Трябва да създадем файл main.js в папката dist/, но прави ли изобщо нещо? Нека се опитаме да го стартираме.

10. Стартиране на кода и някои оптимизации

Тъй като имаме дефинирани изход и вход, ще поставим нашия персонализиран елемент на страницата, ще прослушаме неговото събитие и ще променим стойността на атрибутав нашия примерен код:

Файлът[projectFolder]/index.htmlще изглежда така:

За да обслужваме тази страница, ще използваме прост http-server npm модул, така че нека го инсталираме: npm i -D http-server и да добавим към npm скриптове в package.json:

"scripts": {
  "build": "webpack",
  "serve": "http-server --gzip"
}

Сега стартирайте npm run serve, посетете http://127.0.0.1:8080 с отворени инструменти за разработка и щракнете върху бутона, за да видите обработката на дорита.

Нека отделим малко време, за да се насладим на нашия (надявам се!) момент на триумф🤓

Добре, може би сте забелязали, че пакетът dist тежи около 325kB. Това е тежко! В не толкова далечно бъдеще ще можем да намалим това до много, много, по-малък размер благодарение на двигателя за изобразяване на Angular Ivy, който е планиран за пускане на Angular 7, но засега можем на поне минимизиране и gzip това, което имаме.

За целта нека инсталираме 2 последни dev зависимости:

npm i -D uglifyjs-webpack-plugin compression-webpack-plugin

и ги използвайте в нашите webpack.config.js:

След като стартираме npm run build отново, сега трябва да имаме бит(е, няколко байта всъщност) по-малък js файл, но което е по-важно също и допълнителен gzipped файл, това ще бъде този, който ще предоставим на нашите потребители — и този е много по-лек 85kB. Не е перфектно, но е значително подобрение.

между другото можете да прегледате завършения код в Github.

Епилог

уф! Това беше страхотно пътуване! Имайте предвид, че го направихменаръчно иот нулата.
Трябва и ще бъде много по-лесно в бъдеще. Можем да очакваме всичко да бъде конфигурирано в рамките на Angular CLI и създаването на компилация на елемент ще бъде въпрос на една команда cli.

Но ако сте започнали да чувате за Angular Elements и нямате търпение да ги изпробвате — това е едно от възможните решения. Както споменах, ще споделя второто в следваща статия.

Научихте ли нещо ново? Ако е така, моля:

→ пляскане 👏 бутон по-долу️, за да могат повече хора да видят това
последвайте мев Twitter (@sulco), така че няма да пропуснете бъдещи публикации!



Вижте базирания на CLI подход тук: