question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Recommendations for a performing typescript web app

See original GitHub issue

I take the liberty of opening this issue here too because perhaps you have already faced this problem and you could show me the right way.

And I could also create a PR for future people.

I’m building for the first time a new app in Typescript designing it with Proto files.

I’m having doubts about which is the best strategy to manage the many service clients in this web app.

“Best” in terms of a good compromise between user’s device RAM and Javascript execution speed (main thread ops).

This is what I’m doing right now, this is the main file:

  • main.ts:
import { GrpcWebFetchTransport } from '@protobuf-ts/grpcweb-transport';

import { PlayerServiceClient } from './grpc/generated/player.client';
import { TeamServiceClient } from './proto/team.client';
import { RefereeServiceClient } from './proto/referee.client';
import { FriendServiceClient } from './proto/friend.client';
import { PrizeServiceClient } from './proto/prize.client';
import { WinnerServiceClient } from './proto/winner.client';
import { CalendarServiceClient } from './proto/calendar.client';

const transport = new GrpcWebFetchTransport({ baseUrl: 'http://localhost:3000/api' });

let playerService: PlayerServiceClient;
export const getPlayerService = (): PlayerServiceClient =>
	playerService || ((playerService = new PlayerServiceClient(transport)), playerService);

let teamService: TeamServiceClient;
export const getTeamService = (): TeamServiceClient =>
	teamService || ((teamService = new TeamServiceClient(transport)), teamService);

let refereeService: RefereeServiceClient;
export const getRefereeService = (): RefereeServiceClient =>
	refereeService || ((refereeService = new RefereeServiceClient(transport)), refereeService);

let friendService: FriendServiceClient;
export const getFriendService = (): FriendServiceClient =>
	friendService || ((friendService = new FriendServiceClient(transport)), friendService);

let prizeService: PrizeServiceClient;
export const getPrizeService = (): PrizeServiceClient =>
	prizeService || ((prizeService = new PrizeServiceClient(transport)), prizeService);

let winnerService: WinnerServiceClient;
export const getWinnerService = (): WinnerServiceClient =>
	winnerService || ((winnerService = new WinnerServiceClient(transport)), winnerService);

let calendarService: CalendarServiceClient;
export const getCalendarService = (): CalendarServiceClient =>
	calendarService || ((calendarService = new CalendarServiceClient(transport)), calendarService);

// and so on... a lot more...

As you can see there are many service clients.

I’m using this code because I thought it was better given my web app structure based on routes almost overlapping with client services:

I mean, if the player goes from /home to /players page I can use it like this:

import { getPlayerService } from 'main';

const players = async () => await getPlayerService().queryPlayers()

In this way, if the PlayerService does not exist, it is created at the moment and returned, otherwise it returns the one created before.

Since the user switches pages frequently this way I can avoid the sudden creation and destruction of those clients, right?

But in this way I am using global variables which I don’t like to use.

What do you suggest me to do?

Is there a better way?

Can I refactor this code into only one class?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
bluskriptcommented, Apr 8, 2021

Here’s a simple one that should work:

import type { AuthServiceClient } from "../protocol/auth/v1/auth";
import { HrpcTransport } from "./hrpcTransport";

export class Connection {
  host: string;
  private auth?: AuthServiceClient;
  private session?: string;
  private transport: HrpcTransport;

  constructor(host: string) {
    this.host = host;
    this.transport = new HrpcTransport({
      baseUrl: host,
    });
  }

  setSession(session: string) {
    this.session = session;
    this.transport.setSession(session);
  }

  getSession() {
    return this.session;
  }

  async getAuthClient() {
	if (!this.auth) {
      this.auth = new (await import("../protocol/auth/v1/auth")).AuthServiceClient(this.transport);
    }
	return this.auth;
  }
}

If the async getter gets too tiring for you, I would recommend having a loadAuthClient function instead that gets called before accessing auth

1reaction
bluskriptcommented, Apr 8, 2021

How we use this tool in our project, we have a Connection class which contains instances of each service needed by the application. We don’t use many services though, so we aren’t really taking advantage of lazy loading them. Although if we wanted to lazy load them then I would just have getters for the services that import only once.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Top 5 TypeScript Performance Tips - HackerNoon
Top 5 TypeScript Performance Tips · 1. Type Annotations · 2. Interfaces Over Intersections · 3. Base Types Over Unions · 4. Naming...
Read more >
Modern web apps with TypeScript - Vaadin Fusion - YouTube
A faster way of building modern web apps on Spring Boot. Learn how Vaadin's new TypeScript APIs simplify web app development on Java ......
Read more >
Performance · microsoft/TypeScript Wiki - GitHub
TypeScript is a superset of JavaScript that compiles to clean JavaScript output. - Performance · microsoft/TypeScript Wiki.
Read more >
TypeScript tutorial with Visual Studio Code
TypeScript tutorial in Visual Studio Code. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It offers classes, modules, ...
Read more >
Using Node.js, Typescript, and Express to Build a Web Server
Provides smarter autocomplete suggestions when working in your IDE. This guide shows you how to use TypeScript with two tools that are commonly ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found