@pregular/core

🚀Fast, 💎Lightweight Angular alternative with the same modern API thats compile directly to WebComponents

Showing:

Popularity

Downloads/wk

2

GitHub Stars

45

Maintenance

Last Commit

1yr ago

Contributors

0

Package

Dependencies

0

License

MIT

Type Definitions

Tree-Shakeable

No?

Categories

Readme

Build Status

⚠️Early Draft⚠️

Pregular

React has its Preact. It's time for Angular to get his Pregular! Full AOT support and as real WebComponents. Even the template syntax of Angular!

Source of quote: Bitcollage

Motivation

My main motivation for Pregular is Preact and the fact that I am fascinated about compilers (Babel, PostCSS), the love to Angular, Typescript, Reactive-Programming(RxJS) and of course to challenge myself. It is amazing that Jason Miller has developed against the interfaces of React and created an extremely slim version of React. Exactly the same I intend to do with Pregular.

Pregular should be fast and extremely slim in terms of file size!

Goal

Almost every line of code which could be executed at runtime should be created or optimized at compile time.

This way of creating code has many advantages. Huge runtime-libs, high memory usage, large bundled files, not optimize-code are practically almost nonexistent when the code generated at compile time. This is also called AOT. With this approach the JIT compiler has less work to do, and that is damn good for performance.

What do I mean when I talk about full AOT support?

This has nothing to do with Angular. It's more about AOT approach. Angular does it in his way and Pregular in his way.

Do not reinvent the wheel and simply use the official interfaces of Angular.

With Pregular you will have the same Angular Interfaces. I will use the Angular original ones. Internally I will map the interfaces to Pregular. The main difference is that the code will directly transpiled to WebComponents without any dependency to Angular. It will just be plain Javascript.

This procedure, also compiling directly to WebComponents has another advantage. You can use the written Pregular components in every conceivable Framework or Project. It does not matter if it is used React, Vue or Svelte.

Of course you could say why you are not supporting angular/elements and why putting in all this effort for Pregular?

Well let me explain. The Typescript Eco-System in terms of plugin development and how to traverse or manipulate easily an AST is hard and not well documented. Furthermore, Angular is huge, this fact will take me a very long time to understand what is happening under the hood of Angular. Maybe in the end, when Pregular is implemented I will be much more smarter on how Angular works because I will have to deal with it while implementing Pregular. Hopefully.

Awesome toolings exist already. I do not have to write my own compiler, Angular-Template-Syntax-Parser or CSS-Parser.

I decided to go with Babel, Typescript (only typing system), PostCSS-Compiler, Angular-html-Parser, lit-html and lit-html-server for SSR. I am very familiar with them. Especially with writing Babel and PostCSS plugins. I have already looked into Angular-HTML-Parser library, it is not magic, it is handcraft that I already know from Babel and PostCSS.

There are some challenges that need to be overcome.

Using exactly the same Angular Template Syntax

The biggest and most exciting challenge will be to implement the Angular Template Syntax in Pregular. Parsing should not be a problem, because there is already the Angular-Template-Parser. In my point of view 2 things are important. First, not to reinvent the wheel and to use an existing, flexible, fast rendering engine, e.g. lit-html s tag function html and Secondly, most important, writing an adapter that translates Angular-Template-Syntax into the desired rendering engine at compile time.

lit-html is like your very own template construction kit

lit-html is extremely customizable and extensible. Directives customize how values are handled, allowing for asynchronous values, efficient keyed-repeats, error boundaries, and more. lit-html is like your very own template construction kit.

Source of quote: lit-html.polymer-project.org

How could it be possible to implement directives with WebComponents?

There are two types of components in WebComponents. The classic one is to inherit directly from HTMLElement and define it with customElements.define:

Creation:

customElements.define('app-header', class extends HTMLElement {...});

Usage:

<app-header></app-header>

and secondly to inherit directly from an e.g HTMLButtonElement, HTMLDivElement or HTMLImgElement and interact directly in the instance of HTMLImageElement.

Creation:

customElements.define('ng-if-img', class extends HTMLImageElement {...}, {extends: 'img'});

Usage:

<img is="ng-if-img" ng-if-value="someValue" />

As you can see, the second variant is ideal for Angular Directive with WebComponents.

The shown concept (above) is on a very high abstract level. Of sure, in the implementation of Pregular there will more happens under the hood. I just wanted to show that even Angular directives can be implemented with real WebComponents.

Independent packages

At the end of the day it would be desirable if the Angular-Template-Syntax or other feature from Pregular could be used in other Projects, Frameworks or Libs. Therefore the development of Pregular is focused on loose coupling.

There are many frameworks out there. Many are self-contained. You can't just use features from other Frameworks, Libs or Projects. This should be different with Pregular. It should be like lit-html which expressed it very well.

lit-html is like your very own template construction kit

You will able to use any features of Pregular in other independent Projects!

Compiling not only to WebComponents

Theoretically, it would be also possible to use Pregular to compile directly into React, Vue or to another component Framework / Lib / Project.

Proposal platform for Angular Component

Let me first explain how BabelJS and the TC39 committee work together and what my intention behind Proposal platform for Angular Components is.

I assume that you have all heard of BabelJS and that it is used in almost every javascript project. With Babel you can use next generation Javascript today. I mean you can already test features in browsers that would normally not work. The best example is async await. This has been working long before native support.

What does TC39 committee do?

TC39 is the committee that evolves JavaScript. Their members are companies (among others, all major browser vendors). TC39 members meet regularly, and their meetings are attended by delegates who are sent and invited by experts.

Each proposal for an ECMAScript feature goes through the following maturity stages, starting with stage 0. The progression from one stage to the next one must be approved by TC39.

Source of Quote: 2ality.com

What is the relationship between BabelJS and TC39?

New Javascript features are only implemented by BabelJS if they reach Stage-1 in the TC39 committee. In short, TC39 invents new features, passes them to the next stage or discards them and Babel makes sure that can be used in not supported Browsers. This allows TC39 to detect design flaws early and even get feedback from the Community whether the new feature is accepted or not.

Note: Exactly the same is applied to Typescript. Only features will be implemented by Typescript which reached Stage-3 on TC39. There is one exception I can remember and that is the @decorators(stage-2) proposal.

What does this have to do with Pregular?

First of all, I would like to make it clear that my intention is not to propose e.g. a new decorator or a directive. These can already be implemented by Angular resources. Rather, it is about trying out completely new concepts. In an old project of mine app-decorators you can define real javascript events (see below @on load, @on click example Code) in CSS. A part of this feature is executed at compile time and the rest, a small runtime executes at runtime.

I think with BabelJS and PostCSS you can implement ideas faster than with Typescript and Angular. The tooling, the developer experience around BabelJS and PostCSS is simply more easier and the community has much more experience with these two tools. You would have more devs who might work on this project.

These are just two examples (see below code examples) what i already implemented with app-decorators and would like to port to Pregular.

Maybe we can 'build a bridge' between Pregular and Angular just like BabelJS and TC39 do.

// Example CSS-File

/** These atrule (@) events will be loaded asynchronous (non blocking) **/

/** will be loaded on load event **/
@on load {
  @fetch path/to/on/load.css;
}

/** will be loaded when clicked .up class **/
@on click .up {
  @fetch path/to/on/click/up.css;
}

/** will be loaded when url changed **/
@route hello/my/friend.html {
  @fetch path/to/on/some/route/action.css;
}

/** critical path (inline css will appear immediately) **/
my-box div {
  width: 100px;
  height: 100px;
}

Or moving an Element by declaring events in css properties.

my-box div {
  top: mousemove('top');
  left: mousemove('left');
}

And what about AI-Based which you can see at the top of the github repo?

I don't want to talk about that yet but when the time comes, you will be the first to know but in short, it follows a different approach like guess-js. The fetching of the files (HTML, CSS and Javascript) per Component by the Browser is much more fragmented or/and clustered. Interaction such as Events (Click, Hove) are also considered.

The only thing in common with guess-js is that the evaluation is done by an AI.

Conclusion

This is not a design document. These are just my thoughts on how I imagine Pregular to be. Design documents follow as soon as they are worked out. Of course you are welcome to participate in this project. I would be happy about it.

Pregular Features

Meanings

Icon
✔️will implemented
will developed when first alpha is released
new feature
not sure if this will be implemented
⚠️experimental
will not be implemented
PlannedImplemented
Component Class decorator
@Component()✔️No
@Directive()✔️No
@Pipe()✔️No
@Injectable()No
Component configuration
selector✔️No
template✔️No
templateUrl✔️No
styles✔️No
styleUrls✔️No
encapsulation✔️No
interpolation✔️No
hostNo
exportAsNo
elementType
@Component({
selector: 'lazy-img-polyfill'
elementType: 'img'
})

@Component({ selector: 'lazy-img-polyfill' elementType: 'img' }) <img is="lazy-img-polyfill" loading="lazy" src="image/url.jpg"> * Safari needs polyfill

* Safari needs polyfill
⭐⏰⚠️No
inputsNo
outputsNo
providersNo
animationsNo
queriesNo
viewProviders-
changeDetection-
entryComponents-
preserveWhitespaces-
module.id-
jit-
Class field decorators for components
@Input()✔️No
@Output()✔️No
@HostBinding('class.valid')No
@HostListener('click', ['$event'])No
@ContentChild(myPredicate)No
@ContentChildren(myPredicate)No
@ViewChild(myPredicate)No
@ViewChildren(myPredicate)No
@Query(myPredicate)
Alias for:
@ContentChild, @ContentChildren, @ViewChild and @ViewChildren
⭐⏰⚠️No
@On('click .foo')
(1) Defining an event with a selector in a class method
(2) Alias for @HostBinding => @On('click')
⭐⏰⚠️No
@Route('/name/{{value}}', myPredicate, {name: 'myOutlet'})
@Component({
selector: 'some-component',
template:
@Component({ selector: 'some-component', template: <router-outlet name="myOutlet"></router-outlet> }) class Foo { @Route('/name1/{{value}}', {name: 'myOutlet'}, BarComponent) route1 = 'myRoute1'; }
})
class Foo {
@Route('/name1/{{value}}', {name: 'myOutlet'}, BarComponent)
route1 = 'myRoute1';
}
⭐⏰⚠️No
Built-in Services
ElementRef, constructor(private elr: ElementRef)✔️No
TemplateRefNo
ViewContainerRefNo
Component lifecycle hooks
constructor()✔️No
ngOnChanges(changeRecord)✔️No
ngOnInit()✔️No
ngAfterViewInit()✔️No
ngOnDestroy()✔️No
ngAfterContentInit()No
ngAfterViewChecked()-
ngDoCheck()-
ngAfterContentChecked()-
Built-in Services
ElementRef✔️No
TemplateRefNo
ViewContainerRefNo
Template syntax
Hello {{ponyName}}✔️No
<div title="Hello {{ponyName}}">✔️No
(click)="foo($event)"✔️No
[value]="firstName"No
[attr.role]="myAriaRole"No
[class.extra-sparkle]="isDelightful"No
[style.width.px]="mySize"No
Sum{{1 + 1 + getVal()}}No
[(title)]="name"No
<video #movieplayer
<button (click)="movieplayer.play()">
</video>
No
*myUnless="myExpression"No
Employer: {{employer?.companyName}}No
<ng-template>No
<ng-content>No
<router-outlet>, <router-outlet name="myOutlet">No
<svg:rect x="0" y="0" width="100" height="100"/>No
<svg>
<rect x="0" y="0" width="100" height="100"/>
</svg>
No
<ng-container>No
<ng-container *ngTemplateOutlet>No
(keydown.enter.esc)="bar($event)"No
(ngSubmit)="bar(...)"No
Built-in directives
*ngIf="showSection"✔️No
*ngIf="condition; else elseBlock"✔️No
*ngIf="condition; then thenBlock else elseBlock"No
*ngFor="let item of list; index as i"No
*ngFor="let item of list; first as isFirst"No
*ngFor="let item of list; even as isEven"No
*ngFor="let item of list; odd as isOdd"No
*ngFor="let item of items; index as i; trackBy: trackByFnNo
[ngSwitch], [ngSwitchCase], ...No
[ngClass]No
[ngStyle]No
Built-in pipes
{{ observableOrPromise | async }}✔️No
{{ value_expression | json }}No
{{ value_expression | uppercase }}No
{{ value_expression | lowercase }}No
{{ input_expression | keyvalue }}No
{{ value_expression | number }}No
{{ value_expression | percent}}No
{{ value_expression | uppercase }}No
{{ value_expression | currency }}No
{{ value_expression | i18nPlural }}No
{{ value_expression | slice }}No
{{ value_expression | date }}No
{{ value_expression | i18nSelect }}No
{{ value_expression | titlecase }}No
Dependency injection decorators
@Self()No
@Optional()No
@SkipSelf()No
@Host()No
@Attribute()No
@Inject(<any_token>)No
@Inject(DOCUMENT)No
@Inject(WINDOW)⭐⏰No
@Inject(LOCATION)⭐⏰No
@Inject(NAVIGATOR)⭐⏰No
@Inject(HISTORY)⭐⏰No
@Inject(LOCALSTORAGE)⭐⏰No
StateNo
Routing and navigationNo
Directive configurationNo
NgModules-

Browser Support

Chrome*Firefox*EdgeSafari*IE11+Chrome Android*Mobile Safari*
✔️✔️✔️✔️✔️✔️

* Indicates the current version of the browser
In special cases lazy load polyfills for older browsers (+IE11 excluded) but not in first step of pregular

dev watch test

  • npm run compile:watch
  • npm run test

dev single run test

  • npm run compile
  • npm run test

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100