-
-
Notifications
You must be signed in to change notification settings - Fork 182
refactor: remove AsyncPipe
to reduce bundle size
#578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: remove AsyncPipe
to reduce bundle size
#578
Conversation
This commit removes the `AsyncPipe` from the bundle and replaces its usage with signals (currently the primary communication mechanism with the view in Angular). **Use case:** We're using `ngx-markdown`, but not using `AsyncPipe` directly. However, it’s still being included in the initial bundle due to its usage within `ngx-markdown`.
Would be cool to see this landed. Signals became fully stable in v20: "Promoting reactivity features to stable" https://blog.angular.dev/announcing-angular-v20-b5c9c06cf301#0665 |
@midzer if you need a quick fix, you can use Diffdiff --git a/node_modules/ngx-markdown/fesm2022/ngx-markdown.mjs b/node_modules/ngx-markdown/fesm2022/ngx-markdown.mjs
index c3194b6..f1392bf 100644
--- a/node_modules/ngx-markdown/fesm2022/ngx-markdown.mjs
+++ b/node_modules/ngx-markdown/fesm2022/ngx-markdown.mjs
@@ -1,8 +1,9 @@
-import { AsyncPipe, isPlatformBrowser, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
-import { Component, ChangeDetectionStrategy, InjectionToken, Pipe, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, Input, Output, SecurityContext, NgModule } from '@angular/core';
+import { computed, Component, ChangeDetectionStrategy, InjectionToken, Pipe, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, Input, Output, SecurityContext, NgModule } from '@angular/core';
+import { toSignal } from '@angular/core/rxjs-interop';
import { Subject, merge, of, timer } from 'rxjs';
-import { switchMap, mapTo, distinctUntilChanged, shareReplay, startWith, map, takeUntil, first } from 'rxjs/operators';
+import { switchMap, mapTo, distinctUntilChanged, shareReplay, map, takeUntil, first } from 'rxjs/operators';
+import { isPlatformBrowser } from '@angular/common';
import { Renderer, marked } from 'marked';
export { Renderer as MarkedRenderer } from 'marked';
import * as i1 from '@angular/common/http';
@@ -13,10 +14,11 @@ const BUTTON_TEXT_COPIED = 'Copied';
class ClipboardButtonComponent {
constructor() {
this._buttonClick$ = new Subject();
- this.copied$ = this._buttonClick$.pipe(switchMap(() => merge(of(true), timer(3000).pipe(mapTo(false)))), distinctUntilChanged(), shareReplay(1));
- this.copiedText$ = this.copied$.pipe(startWith(false), map(copied => copied
- ? BUTTON_TEXT_COPIED
- : BUTTON_TEXT_COPY));
+ this.copied = toSignal(this._buttonClick$.pipe(switchMap(() => merge(of(true), timer(3000).pipe(mapTo(false)))), distinctUntilChanged(), shareReplay(1)));
+ this.copiedText = computed(() => {
+ const copied = this.copied();
+ return copied ? BUTTON_TEXT_COPIED : BUTTON_TEXT_COPY;
+ });
}
onCopyToClipboardClick() {
this._buttonClick$.next();
@@ -25,10 +27,10 @@ class ClipboardButtonComponent {
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.0", type: ClipboardButtonComponent, isStandalone: true, selector: "markdown-clipboard", ngImport: i0, template: `
<button
class="markdown-clipboard-button"
- [class.copied]="copied$ | async"
+ [class.copied]="copied()"
(click)="onCopyToClipboardClick()"
- >{{ copiedText$ | async }}</button>
- `, isInline: true, dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
+ >{{ copiedText() }}</button>
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: ClipboardButtonComponent, decorators: [{
type: Component,
@@ -37,12 +39,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
template: `
<button
class="markdown-clipboard-button"
- [class.copied]="copied$ | async"
+ [class.copied]="copied()"
(click)="onCopyToClipboardClick()"
- >{{ copiedText$ | async }}</button>
+ >{{ copiedText() }}</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [AsyncPipe],
}]
}] });
@@ -222,7 +223,7 @@ class MarkdownService {
.pipe(map(markdown => this.handleExtension(src, markdown)));
}
highlight(element) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return;
}
if (typeof Prism === 'undefined' || typeof Prism.highlightAllUnder === 'undefined') {
@@ -236,7 +237,7 @@ class MarkdownService {
Prism.highlightAllUnder(element);
}
decodeHtml(html) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return html;
}
const textarea = document.createElement('textarea');
@@ -302,7 +303,7 @@ class MarkdownService {
: marked.parse(html, markedOptions);
}
parseEmoji(html) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return html;
}
if (typeof joypixels === 'undefined' || typeof joypixels.shortnameToUnicode === 'undefined') {
@@ -311,7 +312,7 @@ class MarkdownService {
return joypixels.shortnameToUnicode(html);
}
renderKatex(element, options) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return;
}
if (typeof katex === 'undefined' || typeof renderMathInElement === 'undefined') {
@@ -320,7 +321,7 @@ class MarkdownService {
renderMathInElement(element, options);
}
renderClipboard(element, viewContainerRef, options) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return;
}
if (typeof ClipboardJS === 'undefined') {
@@ -381,7 +382,7 @@ class MarkdownService {
}
}
renderMermaid(element, options = this.DEFAULT_MERMAID_OPTIONS) {
- if (!isPlatformBrowser(this.platform)) {
+ if (ngServerMode) {
return;
}
if (typeof mermaid === 'undefined' || typeof mermaid.initialize === 'undefined') {
@@ -773,19 +774,19 @@ class MarkdownModule {
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule, imports: [CommonModule, ClipboardButtonComponent,
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule, imports: [ClipboardButtonComponent,
LanguagePipe,
MarkdownComponent,
MarkdownPipe], exports: [ClipboardButtonComponent,
LanguagePipe,
MarkdownComponent,
MarkdownPipe] }); }
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule, imports: [CommonModule] }); }
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MarkdownModule, decorators: [{
type: NgModule,
args: [{
- imports: [CommonModule, ...sharedDeclarations],
+ imports: sharedDeclarations,
exports: sharedDeclarations,
}]
}] });
|
@arturovt Thanks, but I don't have this file on my system:
|
Hi @arturovt, Thanks for the PR. It will be merged into a temporary branch before being merged into the master branch so I can...
|
* refactor: remove `AsyncPipe` to reduce bundle size (#578) --------- Co-authored-by: Artur <arthurandrosovich@gmail.com>
This commit removes the
AsyncPipe
from the bundle and replaces its usage with signals (currently the primary communication mechanism with the view in Angular).Use case: We're using
ngx-markdown
, but not usingAsyncPipe
directly. However, it’s still being included in the initial bundle due to its usage withinngx-markdown
.