Most modern Front-End frameworks are Component-Oriented, taking advantage of encapsulation and separation of responsibilities to improve developer productivity and application robustness. However, to fully exploit the power of components, you need to aggregate them in a consistent and modular set. In this talk we share our experience in building several component libraries, from API Design concepts to advanced component interaction patterns, from packaging and documentation to refactoring & interoperability. Examples are Angular-based, but most concepts apply to all Front-End dev approaches.
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Build your Angular Component Library
1. So you want to build your (Angular)
Component Library? We can help
Carlo Bonamico - Sonia Pini
Milan | November 29 - 30, 2018
2. Components are the core of Web Apps
Self-contained set of UI and logic
○ encapsulate a specific behaviour
○ provide an explicit API
better than
3. Advantages of Components
Stronger Encapsulation
● explicit @Input and @Output bindings
● changing the component internal implementation has less
impact on the rest of the application
● more decoupling, less regressions
Reusability
● same component used in different contexts
● with different parameters or inputs
4. Advantages of Components
Better Collaboration
● less conflicts when team grows
● easier to test for regressions
More Clarity and Readability
● I can effectively use a component knowing only its API (the
bindings section)
● the link to other components is very clear and explict in the
HTML
Also, the component tree is very good for performance
<mail-view>
<message-list>
<nav-actions><common-star>
<message-view>
<common-star>
5. Why build a
Component Library?
Most of the concepts in this talk apply to any framework
although example syntax is based on Angular
6. Why a Component Library?
Starting point:
Provide a Uniform Visual Style
7. Why a Component Library?
● Higher productivity
○ Higher abstraction
○ Re-use across projects
○ Faster app build time
● Focus Documentation / Test effort
● Promote Cleaner Design and Best Practices
○ Separation of Responsibility
● Apps benefit from improvements in the Library
8. What kind of Component Library?
● Basic Components / Atoms
○ form labels
○ input controls
○ buttons <mat-button>
○ abstract elements: fonts, color palettes, animations, ...
http://atomicdesign.bradfrost.com/table-of-contents/
9. What kind of Component Library?
● Composed Components / Molecules
○ combining Base Components together
○ e.g. <lib-search-filter>
10. What kind of Component Library?
● Complex Components / Organisms
○ combining Basic and/or Composed Components together
○ Domain-independent es. <ht-table>, <shopping-cart>
○ Domain-specific es. <doc-sign-documents>, <contact-address-book>
11. Composability + Consistency = Great LIB
Functional Consistency
● Make your product more predictable
● Better UX
Visual Consistency
● Includes the colors, fonts, sizes, positions
Modularity / Composability
● the set is greater than the parts
API Consistency & Development Experience
● including Documentation and Packaging
● make developer more productive
13. Adopt or Provide Style Guide
Well defined colors, fonts, spacing
Davide Casali - Gestalt Design Principles for Devs
https://www.slideshare.net/folletto/gestalt-design-principles-for-developers
14. Adopt a naming convention for styles
● your own vs Block-Element-Modifier http://getbem.com
Use a CSS Pre-Processor (SCSS - LESS) to
● simplify uniform style definitions with @variables
● semi/automatically create themes or accessibility features
Library-level CSS should concentrate on
● variables for color palette, base font sizes, margin, padding
● page-level layout (e.g. Grid)
Component-level CSS
● encapsulation for easier maintenance
Organize Library Stylesheets
15. Separate Containers from content
Container Components focus on
● position/layout within the page or parent
○ <ht-sidebar-layout>, flex-based
● decorating the content
○ <ht-card>, <ht-accordion>, <ht-panel>
19. Pattern: Data Flow “down”
Component bind a subset of their model to children
<mail-view>
<folder-list> <message-list>
<nav-actions><common-star>
<message-view>
<common-star>
folders
messages
currentMessage
20. Using @Input()
Using plain variables/arrays for @Input
● data owned by parent
● better for stateless / “dumb” components
<user-details [user]=”currentUser”>
Using Observable for @Input
● if you want to listen to changes continuously or
asynchronously
<realtime-chart [dataStream]=”stockValueStream” >
24. Using DataSource in @Input
More complex components might need data refresh / drill-down
○ think <ht-table> with pagination, sorting, ...
Define a DataSource Interface
○ with all methods your component want use during its life
Provide an Implementation for the easier/common use-cases
○ ArrayDataSource, PagedDataSource
Document the DataSource Interface to guide developers
○ provide example of custom implementation
25. An Example from Angular Material
abstract DataSource<T>
○ connect(...): Observable<T[]>
○ disconnect(...): void
TableDataSource<T> extends DataSource<T>
○ page(...): Observable<T[]>
○ sort(...): Observable<T[]>
○ filter(...): Observable<T[]>
https://material.angular.io/components/table/api#MatTableDataSource
26. Multi-mode @Inputs
The component auto-adapts to the provided input
For example, to populate a mat-table we can use
○ a simple T[] if our data are static
○ an Observable<T[]>
○ a DataSource<T>
29. Never communicate directly: Publish events! key for low coupling
● towards Parent Component
@Output() selected = new EventEmitter<string>();
select(item) { this.selected.emit(item); }
● towards shared Observable Streams in a Service
○ e.g. ErrorService, AlertService
private errorSubject = new Subject<any>();
notifyError(code, message) {
this.errorSubject.next({
code: code,
message: message
});
}
Events & Common Services
In both cases, events
should express
● what's happened
● à la DDD Events
● intent, not what to
do
30. Separation of Responsibilities +
Component Interaction
Complex behaviour achieved through collaboration
<mail-view>
<folder-list> <message-list> <message-view>
onSelected()
onCurrentMsg()messages
currentMessage
32. Implement the Decorator Pattern to add cross-cutting
behaviour to a set of components
● <ht-modal>
● <ht-input-container>
○ provides label, required,
validation errors to an input
<ht-input-container>
<ht-input [(ngModel)]=...
</ht-input-container>
○ uses @ContentChild
to access the control
Decorator Component Pattern
34. API Design Challenges and Principles
● Your Library has two “Users”
○ End Users and Developers
○ think from both perspectives
● Joshua Block: Principle of Least Astonishment
○ How to Design Good APIs
https://www.youtube.com/watch?v=aAb7hSCtvGw
35. Names Matter
● Functionality should be easy to explain
○ express Intent
○ X is hard to name => symptom that X design needs refinement
■ too many responsibilities
■ unclear intent
○ Good names drive development
● Adopt Naming Conventions
○ library prefix in components name (e.g. ht-panel vs app-view)
○ prefix in property names vs HTML5 attributes (disabled, width...)
36. Beyond Names: Conceptual Consistency
● Same/standard APIs based on Types
○ LabelAndIcon interface
○ ControlValueAccessor for all input fields
● Same Abstractions
○ DataSources for <ht-table>, <ht-tree>, <ht-document-download>
○ conceptually similar event if cannot share same Type
Limit the amount of Mental Models that developers must learn
● Kathy Sierra on learning for effective products
https://www.youtube.com/watch?v=FKTxC9pl-WM
37. API Should Be As Small As Possible
● But no Smaller
○ focus on the most important use-cases
● Constant trade-off between Under and Over-Engineering
○ if in doubt, leave it out: you can add it later
● often adding an Extension Point is easier
○ less risky than a Feature
○ e.g. <ng-content> or publishing an Event on a Stream
38. Gather & Refine Requirements
● Extract true requirements from ‘proposed solutions’
■ Table Columns should be configured to display a Button / Link
○ becomes
■ “Table Columns supports a template to customize cell rendering”
● Think more general
● Keep the Spec short
39. Plan for the Future
● Expect to make mistakes
● Prepare to evolve API
○ Expand-Contract pattern
○ Deprecation / console.warn()
○ Design for Refactoring: Typescript helps!
○ Ease upgrade with tools (tslint for rxjs 5-> 6, schematics)
○ automatic tests
41. Documentation Matters
Document every public component, interface, method, ...
● if it is not documented, “it does not exists” for developers
● Component, method, variable names should be as
self-explanatory as possible
● for all the rest, there is...
45. A good Angular Library
● Is platform independent
○ can be consumend as UMD, FESM, ...
● Is bundled and distributed
● Works with AOT (Ahead of Time Compiler)
● Plays well with TypeScript and IDEs
○ autocompletion, compile-time checking
See Angular Package Format
Minko Gechev
@mgechev
screenshot
structure of the build
package in node
modules
46. Angular 6.x integrates David Herges’ ng-packagr
● workspace = apps + libs
ng generate library basiclib
ng generate app basiclib-demo
ng build basiclib
cd dist/basiclib
npm pack
npm publish basiclib.y.z.tgz
even live reload across lib & app
https://mereommig.dk/en/blog/adding-livereload-to-the-angular-cli-libraries
Creating and publishing
48. Future directions
● Angular Ivy Renderer
○ reusing a library does not require metadata processing
■ https://blog.angularindepth.com/inside-ivy-exploring-the-new-angular-compiler-ebf85141cee1
● Angular Elements
○ package Components as HTML5
Custom Elements (a.k.a. Web Components)
○ https://angular.io/guide/elements
● See also StencilJs Component Compiler
○ https://stenciljs.com/
49. References on Components
Codemotion 2016 Talk
https://www.slideshare.net/carlo.bonamico/angular-rebooted-components-every
where
Components in Angular 2
https://angular.io/docs/ts/latest/cookbook/component-communication.html
More on Angular
https://angularconnect.com/talks
50. Thank you!
● Other presentations
− http://www.slideshare.net/carlo.bonamico/presentations
● Follow us on Twitter
− @carlobonamico @nis_srl @Sonietta
● updates on Angular, Clean Code, Continuous Delivery
● Contact us
− carlo.bonamico@gmail.com / carlo.bonamico@nispro.it
− Sonia.pini@nispro.it
● Our company
− http://www.nispro.it