Code Monkey home page Code Monkey logo

angular-movies's People

Contributors

biophoton avatar christopherpholder avatar dingnan avatar eneajaho avatar francesco-buscicchio avatar hoebbelsb avatar jeanmeche avatar karnaukhov-kh avatar mannil avatar medeirosjoaquim avatar mishaseredenkopushbased avatar vmasek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-movies's Issues

ngSrc generates wrong srcset

In list detail page we can see that all posters have broken images, that's because srcset is wrong:

srcset="
https://image.tmdb.org/t/p/w355/g4a5YLWwi6OCp8TcvxsUNrXMbN5.jpg 1x, 
https://image.tmdb.org/t/p/w710/g4a5YLWwi6OCp8TcvxsUNrXMbN5.jpg 2x"

Actually available sizes from TMDB are

Poster Sizes:

  • w92
  • w154
  • w185
  • w342
  • w500
  • w780
  • original

Backdrop Sizes:

  • w300
  • w780
  • w1280
  • original

Profile Sizes:

  • w45
  • w185
  • h632
  • original

Still Sizes:

  • w92
  • w185
  • w300
  • original
image

Temporary fix done in #256

SSR/Prerender/Hybrid setup

We want to experiment with the following features:

  • SSR
    • handle assets
  • prerendering (blocked by SVG and injector hack)
    • handle assets
  • ISSG - incremental server-side generation
  • Cloud Run

Bug: API calls are processed by the client even though responses are cached in TransferState

I came across this issue related to Angular Universal in combination with a zoneless app while working on performance improvements in my own app. I wanted to look for a solution here, but found the same problem to occur in angular-movies.

Problem:

Even though API calls are done by the server and saved into TransferState, those API calls are made by the client again.

Reproduction:

Just have a look into the network tab when loading the live deployment of the application at https://angular-movies-a12d3.web.app/list/category/popular

Bildschirmfoto 2022-07-11 um 11 00 14

My findings so far:

I did some debugging and found the issue to be in TransferHttpCacheInterceptor. When appRef.isStable emits the first time, the cache is set to inactive. In an app that is zoneless, the timing of this emit seems to differ from an app that utilizes zone.js.

Bildschirmfoto 2022-07-11 um 11 04 22

The app will be stable before any HTTP request is processed, thus the cache will never be used. If you implement this exact HttpInterceptor yourself and use that instead of HttpTransferCacheModule and also for example just comment out the isStable subscription in the constructor, caching will work fine.

I did not find out what causes the zoneless app to be considered stable earlier. Gotta dig into how isStable works. Maybe you know better :-)

Visual polishing

The following screens could be updated on the desktop:

movie-list
next-popular-desktop
angular-popular-desktop

  • size of yellow icon on the right
  • Headline, sub-headline missing
  • account icon size different

movie-detail
next-detail-desktop
angular-detail-desktop

  • Headline, sub-headline font-size different
  • star-rating different number of highlighted start
  • back-button color
  • slider buttons missing and scrollbar visible
    person
    next-person-desktop
    angular-person-desktop
  • Headline, sub-headline font-size different
  • back-button color
  • sort select missing

account menu
next-account-hover-desktop
angular-account-hover-desktop

  • hover styling different
  • menu styling different

next-account-hover-item-desktop
angular-account-hover-item-desktop

  • hover item styling different

my-list add/remove
next-my-lists-list-add-desktop
angular-my-lists-list-add-desktop

  • back button color
  • icon instead of button
  • color of number icon
    my-list add/remove search
    next-my-lists-list-add-search-desktop
    angular-my-lists-list-add-search-desktop
  • image should be square
  • text is not needed
  • buttons are not needed

preview channel deploy fails

If there are many PRs the preview channel deploy fails

Deploying to Firebase preview channel 
  /opt/hostedtoolcache/node/18.16.1/x64/bin/npx firebase-tools hosting:channel:deploy  --expires 7d --project angular-movies-a12d3 --json
  ***
    "status": "error",
    "error": "channelID is currently required"
  ***
  ***
    "status": "error",
    "error": "channelID is currently required"
  ***
  
  The process '/opt/hostedtoolcache/node/18.16.1/x64/bin/npx' failed with exit code 1
  Retrying deploy with the --debug flag for better error output
  /opt/hostedtoolcache/node/18.16.1/x64/bin/npx firebase-tools hosting:channel:deploy  --expires 7d --project angular-movies-a12d3 --debug
  [2023-07-13T10:38:30.069Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
  [2023-07-13T10:38:30.189Z] [iam] checking project angular-movies-a12d3 for permissions ["firebase.projects.get","firebasehosting.sites.update"]
  [2023-07-13T10:38:30.190Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions [none]
  [2023-07-13T10:38:30.191Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions x-goog-quota-user=projects/angular-movies-a12d3
  [2023-07-13T10:38:30.191Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions ***"permissions":["firebase.projects.get","firebasehosting.sites.update"]***
  [2023-07-13T10:38:30.304Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions 200
  [2023-07-13T10:38:30.304Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions ***"permissions":["firebase.projects.get","firebasehosting.sites.update"]***
  [2023-07-13T10:38:30.306Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 [none]
  [2023-07-13T10:38:30.505Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 200
  [2023-07-13T10:38:30.505Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 ***"projectId":"angular-movies-a12d3","projectNumber":"453188470[76](https://github.com/tastejs/angular-movies/actions/runs/5542079633/jobs/10116298444#step:6:79)1","displayName":"angular-movies","name":"projects/angular-movies-a12d3","resources":***"hostingSite":"angular-movies-a12d3","storageBucket":"angular-movies-a12d3.appspot.com","locationId":"us-central"***,"state":"ACTIVE","etag":"1_d8f3b634-5217-42f6-94f3-1de87149e3d2"***
  [2023-07-13T10:38:30.506Z] Expires TTL: 604800000
  
  Error: channelID is currently required
  [2023-07-13T10:38:30.069Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
  [2023-07-13T10:38:30.189Z] [iam] checking project angular-movies-a12d3 for permissions ["firebase.projects.get","firebasehosting.sites.update"]
  [2023-07-13T10:38:30.190Z] >>> [apiv2][query] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions [none]
  [2023-07-13T10:38:30.191Z] >>> [apiv2][(partial)header] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions x-goog-quota-user=projects/angular-movies-a12d3
  [2023-07-13T10:38:30.191Z] >>> [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions ***"permissions":["firebase.projects.get","firebasehosting.sites.update"]***
  [2023-07-13T10:38:30.304Z] <<< [apiv2][status] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions 200
  [2023-07-13T10:38:30.304Z] <<< [apiv2][body] POST https://cloudresourcemanager.googleapis.com/v1/projects/angular-movies-a12d3:testIamPermissions ***"permissions":["firebase.projects.get","firebasehosting.sites.update"]***
  [2023-07-13T10:38:30.306Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 [none]
  [2023-07-13T10:38:30.505Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 200
  [2023-07-13T10:38:30.505Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/angular-movies-a12d3 ***"projectId":"angular-movies-a12d3","projectNumber":"453188470761","displayName":"angular-movies","name":"projects/angular-movies-a12d3","resources":***"hostingSite":"angular-movies-a12d3","storageBucket":"angular-movies-a12d3.appspot.com","locationId":"us-central"***,"state":"ACTIVE","etag":"1_d8f3b634-5217-42f6-94f3-1de87149e3d2"***
  [2023-07-13T10:38:30.506Z] Expires TTL: 604[80](https://github.com/tastejs/angular-movies/actions/runs/5542079633/jobs/10116298444#step:6:83)0000
  
  Error: channelID is currently required
  
  The process '/opt/hostedtoolcache/node/18.16.1/x64/bin/npx' failed with exit code 1
  Error: The process '/opt/hostedtoolcache/node/18.16.1/x64/bin/npx' failed with exit code 1
  ***
    conclusion: 'failure',
    output: ***
      title: 'Deploy preview failed',
      summary: "Error: The process '/opt/hostedtoolcache/node/18.16.1/x64/bin/npx' failed with exit code 1"
    ***
  ***
  ##[debug]Node Action run completed with exit code 1
  ##[debug]Finishing: Deploy firebase live hosting

RFC: Optimize pre-rendered pages for LCP

Motivation

Dynamic pages are hard to optimize for the LCP as we can't determine the LCP before executing the page.
It is important to optimize the LCP because it is part of the core web vitals and has a direct impact on user experience.
If we could know the LCP we could use preload and fetch priority to increase the network priority and load the LCP image much faster.

This can be applied to pre-rendered pages.

e.g. inject

  • <img src="img.png" fetchpriority="high" />
  • <link rel="preload" as="image" href="img.png" fetchpriority="high" />

State of the art

ATM preloading of images is done manually.
An example is manually adding the LCP image in the index.html. This can only improve situations where the LCP is static.

Idea

For pre-rendered pages we can run analyzing tools against the page e.g. lighthouse and determine the LCP and if it is an image.
Here is a detailed definition LCP.

In our case the following content is relevant:

  • <img> elements
  • <image> elements inside an <svg> element
  • <video> elements (the poster image is used)
  • An element with a background image loaded via the url()

After identifying the LCP element and its content source we can insert a link tag using the preload rel attribute to improve the download prioritization of the content by the browser, thus overwriting the HTML file of the pre-rendered page.

Implementation proposal

As the code should also be executed in the CI pipeline we should create a CLI executable in the CI.
The CLI should maintain the following commands:

  • Optimize (It measures the LCP, and then injects the LCP as a preload link tag and re-analyzes the LCP).
  • Analyze (Determent if LCP is the image or video, determine if the rendered size and the intrinsic size are the same or smaller and if it's delivered in a next-gen format).

Image on movie detail page does not get updated when switching to another movie

Test Case:

chrome-capture-2023-4-26

Cause:

ngSrc does not allow updating the input dynamically. An error is displayed in the console:

caught Error: NG02953: The NgOptimizedImage directive (activated on an <img> element with the `ngSrc="/nsxnMbkl9Lpc12AmYwKi9SmsJ7e.jpg"`) has detected that `ngSrc` was updated after initialization. The NgOptimizedImage directive will not react to this input change. Changing the `ngSrc` would have no effect on the underlying image element, because the resource loading has already occurred. To fix this, either switch `ngSrc` to a static value or wrap the image element in an *ngIf that is gated on the necessary value.
    at postInitInputChangeError (common.mjs:6416:12)
    at common.mjs:6435:19
    at Array.forEach (<anonymous>)
    at assertNoPostInitInputChange (common.mjs:6425:12)
    at NgOptimizedImage.ngOnChanges (common.mjs:6143:13)
    at NgOptimizedImage.rememberChangeHistoryAndInvokeOnChangesHook (core.mjs:2812:14)
    at callHookInternal (core.mjs:3804:14)
    at callHook (core.mjs:3835:9)
    at callHooks (core.mjs:3786:17)
    at executeCheckHooks (core.mjs:3717:5)

Solution:

There is an open issue angular/angular#47813

The alternatives are:

I can make the PR if needed!

Small bug in dark mode toggle component.

Dark mode toggle works in reverse manner

  • Light theme, the toggle shows it's in dark mode
    Screen Shot 2022-10-21 at 15 24 33

  • Dark theme, the toggle shows it's in light mode
    Screen Shot 2022-10-21 at 15 24 46

I've also checked with other demos and they work correctly.

Possible quick fix

/*
https://github.com/tastejs/angular-movies/blob/c72d7197677c3698a9cd0fcb22920b05460c1fbc/projects/movies/src/app/ui/component/dark-mode-toggle/dark-mode-toggle.component.ts
*/
      <span class="toggle">
        <input
          *rxLet="isLightTheme$; let isLightTheme; strategy: 'immediate'"
          class="toggle-track"
          type="checkbox"
          id="dark-mode"
          [checked]="!isLightTheme"
          (change)="setChecked(!isLightTheme)"
        />
        <label style="color: transparent" for="dark-mode">
          Toggle Switch
        </label>
      </span>

Errors during npm install on Windows

First the README should mention nx needs to be installed.
I did an 'npm i' and noticed a lot of deprecated packages then this list of errors. I am not sure what's causing the errors.

image

Polishing

  • reusable grid code? => account list page & list img comp are duplicated
  • account menu
    • .ts - remove RxState in favour of RxEffect
  • app-shell
    • .html - svg refactor
    • .html - finetune let chunks
    • .ts - remove ununsed snav prop
  • image-dimensions
  • comment out unused constants
  • paginate
    • remove sort prop and move it into sort folder
  • recources
    • auth4 token not exposed?
    • const file into internals folder
    • get cached reconsider stateful
    • list resource refactor to align with others
    • person type for append_video
  • account-list
    • .html => w/h from entity
    • list-create-page duplicates _button.scss by importing it again
    • use native dialog element for overlay in list-remove.component.html
    • every single component is an article. Do we actually want that? For the most part we can get rid of the wrapper elements at all by just doing :host { display: block; }

List of small improvements

General

  • configure tags
  • add tsconfig.base.json
  • split out test selectors as lib (to share across app and test helpers)
  • fix cyclic movies<->movies-user-flow

Angular Movies

  • modern app bootstrap
  • service worker refactoring
  • clean dist
  • Implement a better onStable patch (ATM it is a static timeout)

Ng Universal Express

  • remove axios
  • fix dist/projects/movies/browser/dist/tmp/projects/movies/server/routes.txt/index.html output for prerender
  • prerender already builds no need for movie build
  • add tests to catch past prerender bugs
    #259
  • Zoneless SSR

Firebase Cloud Function

  • clean dist
  • fix path for firebase function emulation
  • update firebase, firebase-tools and firebase-gh-actions
  • build over nx executor
  • upload only files that are needed for deployment (firebase.json#functions#ignore & firebase.json#functions#ignore)
  • prod and dev configs for build
  • remove implizite dependency for universal app
  • resolve action hack by fixing gh action
    push-based/user-flow-gh-action#119
  • add lint for no file access
  • remove implizite deps
  • separate static hosting and function hosting
  • add affected deploy for firebase services
  • put a custom package.json into dist to have it disconnected form the main package.json. https://stackoverflow.com/questions/74944491/husky-prepare-script-failing-firebase-function-deployment

Cloudflare Worker

  • use preview deployment in GH action
  • use nx executor to build
  • resolve action hack by fixing gh action
  • clean dist before build
  • deploy pages
  • deploy worker

User-Flow Helper for Angular Movies

Rework Tooling, Deploy & SSR

Problem

The SSR part is flaky ATM. A couple of resulted problems where:

  • PR's that broke SSR where released (router configuration, zone-less config, standalone component)
  • SSR and file hosting is tricky to automate for Preview branches (because of the Firebase hosting constrains)
  • Platform problems due to access rights, versions, wrong payment configuration on Firebase project
  • Inconsistency of Prerender runtime vs SSR runtime resulting in broken prerender pages

This impacts the score significantly also in the CrUX report.

Solution

Due to this reasons I suggest a list of possible improve up for evaluation:

Tooling

  • Nx setup
    • separated projects
    • refactored tooling
    • using only --affected lint,test,build in the CI
    • using only --affected deploy in the CI
    • user-flows over the nx-plugin
    • firebase
      • better serve and build
      • separated universal and firebase cloud function

Code structure

  • File and folder structure is off from the rest of the src files (functions folder, server.ts outside of projects, main.ts and main.server.ts are very different in content, etc.) a better file organization is needed
  • Move specific SSR decisions into tokens if it makes sense for them to be part of DI and not component/service.
  • All SSR decisions that are related to files (e.g. zone.js) should be done with target configurations and the ng build process (ng build-ssr movies --configuration ssr)
  • firebase functionsand hosting should life in the functions folder

Documentation

  • Better docs on how to develop, build etc
    • Development should be served with npm run start:ssr:dev locally to validate changes to Browser and Server versions
  • Documentation of the included pieces of the SSR + SSG

Testing

  • Setup integration tests for the build process. Statically check the output HTML from the build process.
  • Detailed Server Timing => POSTPONED
  • Setup e2e tests that run against the app
    • Ensure the tests passes without JS executed
  • Preview branch of the firebase cloud function
  • Preview branch of the cloudflare edge worker
  • live hosting of the firebase cloud function
  • live hosting of the cloudflare edge worker => POSTPONED
  • Setup e2e tests that checks the "src switch bug" from ngSrc

Improvements

  • Render less pages of the infinite scroll content if possible
  • Post optimize for the LCP. PoC here #133
  • Fix HTTP transfer state. #119
    options so far:
    • custom Zone (fix zone stable) #139
    • or zone full SSR setup zone-full SSR
      to reduce TBT
  • implement time based HTTP caching to avoid over fetching and benefit from HTTP transfer state #138
  • enable ISG #132
  • fix chunking of initial rendering related to RxA render strategies. #157
    • [x] this is visible flicker on SSR to client hydration

Next suggested steps

  • start with hot fixes to get score first (we want to see CrUX early)
  • evaluate effort and prioritize items

ISR doesn't work for angular movies because of zoneless

While trying to implement ISR ngx-isr I found out that it didn't work.

The reason is because the routing depends on zone.js implementation.

For ISR in order to get the route data, something like this is implemented:

this.router.events
  .pipe(
    filter((e) => e instanceof ChildActivationEnd),
    map((event) => {
      let snapshot = (event as ChildActivationEnd).snapshot;
      while (snapshot.firstChild !== null) {
        snapshot = snapshot.firstChild;
      }
      return snapshot.data;
    }),
    take(1)
  )
  .subscribe((data: any) => {
    if (data?.['revalidate'] !== undefined) {
      this.setRevalidate(data['revalidate']);
    }
  });

It listens to router events, and waits for it to emit, also, because in zoneless the isStable observable emits directly, ISR doesn't have time to listen to stuff on SSR and add the revalidate data to html.

Without finding a way to wait for the router stuff to finish but also for the api requests (that zone.js helps with), we can't have correct http transfer cache but also ISR features in zoneless apps.

Unable to bootstrap application

Hello,

I cloned this repo and ran followed the steps in Readme. I have created my own tmdbApiKey and tmdbApiReadAccessKey. In Readme it says npm run build:dev to run it locally but I don't see any script in package.json. I ran npm run start assuming it's the start command but I get below -

$ npm run start

> [email protected] start
> nx serve movies:development


 >  NX   Cannot find configuration for task movies:development

   Pass --verbose to see the stacktrace.

Please provide me some hints here. Thanks.

add link to app as about url

I always struggle to find the link for the deployed version of this app. Can we please add it as website url in the about section? As we did for rx-angular pointing to the docs.

image

use input transforms

Use input transforms wherever applicable.

example before:

  @Input({required: true})
  set lazy(component: RxInputType<Type<any>>) {
    this.connect('component', coerceObservable(component));
  }

example after:

  @Input({required: true, transform: <T>(value: RxInputType<T>) => coerceObservable(value)})
  set lazy(component: Observable<Type<any>>) {
    this.connect('component', component);
  }

or:

  @Input({required: true, transform: coerceObservable<Type<any>>})
  set lazy(component: Observable<Type<any>>) {
    this.connect('component', component);
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.