Efficient configuration for pnpm monorepo with TypeScript, vite, and rollup

Struggling to set up a monorepo using pnpm workspaces with typescript, vite for frontends, and rollup for backend microservices. Here's the current project structure:

package.json                            <== all dependencies reside here
tsconfig.json
pnpm-workspaces.yaml
- commonlib/
  package.json, tsconfig.json, rollup.config.js
  src/
    ...interfaces, types etc---
- serverlib/
  package.json, tsconfig.json, rollup.config.js
  src/
    ...modules for common server/microservice functionality---
- weblib/
  package.json, tsconfig.json, vite.config.js
  src/
    ...react components & functions---
- servers/
    srv-gateway/
      package.json, tsconfig.json, rollup.config.js
      src/
        ...server code...
    ms-xxx/                             <== Multiple REST microservices
      package.json, tsconfig.json, rollup.config.js
      src/
        ...microservice code...
- webapps/
    app/
      package.json, tsconfig.json, vite.config.js
      src/
        ...main application code---
    admin/
      package.json, tsconfig.json, vite.config.js
      src/
        ...application code---
    app-2/                              <== Other webapps / micro frontends
      ...

Looking for some guidance on how to best organize my setup:

  • Managing all dependencies in root package.json
  • Accessing modules like @myapp/commonlib, @myapp/weblib, etc.
  • Avoiding publishing to npmjs as these libraries are not meant for public use
  • Handling multiple versions of dependencies and various module formats (cjs, es, esm)

Facing challenges understanding package.json, tsconfig.json, rollup.config.json, and vite.config.json files - it feels overwhelming. Do I need to compile/transpile the libraries or include them differently?

  • Should I version and bundle the libs, or simply reference them?
  • If referencing, how should I do it? Using paths and references in servers/webapps?
  • In weblib, excluding external packages during compilation caused issues - now the webapp is not displaying correctly.

Previously had a system working with individual libraries (@myapp/uilib, @myapp/graphlib) using paths and references but wanted to consolidate into a single library, leading to confusion. Looking for advice on correcting these missteps.

Tried following conflicting tutorials and suggestions from ChatGPT, ultimately creating more chaos. Ready to learn the right way forward. Appreciate any insight you can provide.

Answer №1

After numerous experiments, challenges, and performance assessments, I ultimately settled on the following strategies:

  • I learned that keeping dependencies at the root of the monorepo was not a good idea. When it came time to create Docker images, I had to relocate dependencies into their respective packages. Thankfully, the package manager (pnpm) already manages them at a high level and links to them from individual packages.
  • Working with microservices led me to refactor each one into smaller components. This made the packaging phase unnecessary, so I switched from rollup to esbuild on the server side. Esbuild produces optimized esm (ES2020 for now) bundles and properly handles references in tsconfig.json files (unlike tsup, which I tried but ultimately removed).
  • As a result of the previous change, I moved static files out of the bundle generation process (I had static data files/jsons being served using express-static). By moving the data to a static.mydomain.com installation, I eliminated lengthy copy processes during builds.
  • For my react frontend applications, I continue to use vite/rollup setups as they are functioning well - despite vite's slow start-up in dev mode.
  • All common, frontend, and server libraries now utilize esbuild bundles (limited to ES2020).
  • I reorganized all final frontend and servers into "apps," while libraries were moved to "libs" directories.
  • My multi-level tsconfig.json structure remains intact across all projects.

This experience provided valuable insights during my first venture into a monorepo setup. I plan to update this post with additional details about my project structure.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Merge two input fields into one to send data to the backend

I have created two input fields, one for selecting a date and the other for entering a time. Before submitting the form to the backend, I need to combine these two inputs into one variable. For example, <input type="text" name="myDate"> and <input ...

What is the reason behind TypeScript indicating that `'string' cannot be assigned to the type 'RequestMode'`?

I'm attempting to utilize the Fetch API in TypeScript, but I keep encountering an issue The error message reads: Type 'string' is not assignable to type 'RequestMode'. Below is the code snippet causing the problem export class ...

Listening for keypress events on a div element using React

I'm currently struggling with implementing a keypress listener on a component. My goal is to have my listener activated whenever the "ESC" key is pressed, but I can't seem to figure it out. The function component I am working with is quite stra ...

ridiculing callback within parameter

I have a model setup in the following way: export class MyClass { grpcClient: MyGRPCClient; constructor(config: MyGRPCClientConfig) { this.grpcClient = new MyGRPCClient( config.serverUrl, grpc.credentials.createInsecure(), ); ...

Tips for creating a tailored Express.js request interface using Typescript efficiently

I have been working on designing a custom Express request interface for my API. To achieve this, I created a custom interface named AuthRequest, which extends Request from Express. However, when attempting to import my interface and define req to utilize t ...

Is there a way to revert my Ionic CLI back to the previous version that I had installed?

Having just updated to version 3.2.0, I am encountering numerous issues, such as the malfunctioning of the ionic serve command. ...

Issue with Angular 17 button click functionality not functioning as expected

Having trouble with a button that should trigger the function fun(). Here's the code snippet I'm using. In my TS file: fun(): void { this.test = 'You are my hero!'; alert('hello') } Here is the respective HTML: &l ...

Jest - managing parent class methods during unit tests

The code snippet provided demonstrates a class called First extending TelemetryFramework with specific props and states, containing a method named getData. This method retrieves confidential data and logs telemetry information. However, running unit tests ...

Encountering issues with MediaSession.setPositionState() and seekto functionalities not functioning properly

Having trouble with MediaSession.setPositionState() not displaying the audio time and seekbar not behaving as expected. const sound= document.querySelector('sound'); function updatePositionState() { if ('setPositionState' in navigato ...

Exposing the method to the outside world by making it public in

I have a situation where I have a base class with a protected method called foo, and a child class that needs to make this method publicly accessible. Since this method will be called frequently, I am looking for a more efficient solution to avoid unnecess ...

The issue of saving Rails input from an Angular2 front end has been causing some trouble

Currently, I am in the process of developing a front-end application using Angular 2 that retrieves data from a Rails 5 API. This specific application serves as a network inventory tool. One particular feature of this app is an Asset-form in Angular2 whic ...

Having trouble accessing previously submitted form values in Angular

When I try to update the form, I notice that my meetupform.controls.day array is not retaining the previously selected values app.component.html <div *ngIf="meetupForm.controls.recurring.value==='weekly'"> <mat-checkbox (change)="o ...

What is a more efficient way to differentiate a group of interfaces using an object map instead of using a switch statement?

As someone still getting the hang of advanced typescript concepts, I appreciate your patience. In my various projects, I utilize objects to organize react components based on a shared prop (e.g _type). My goal is to automatically determine the correct com ...

best practices for choosing items from a dropdown menu using Angular

I have a dropdown list displaying existing tags/chips created by users in the past. However, I'm having an issue where when I select a tag from the dropdown list, it doesn't show up in my input field (similar to the Chart tag currently). I am abl ...

Incorporating traditional Javascript classes for modeling in React development

Can traditional JavaScript classes be utilized in models within the MVC framework while using React, as opposed to relying on Redux or contexts & reducers which may impact reusability? If this approach is feasible, how can we efficiently 'subscribe&ap ...

The argument labeled as 'shop' does not fit the criteria for the parameter 'items' or 'cart'

I've been doing some research but haven't had any luck finding a solution. I'm fairly new to Angular and currently working on a webstore project. I followed a tutorial, but encountered an error along the way. import { select, Store } from & ...

Is there a way to utilize "npm install ts-node-dev -D" in Termux?

npm ERR! code EACCES npm ERR! syscall symlink npm ERR! path ../acorn/bin/acorn npm ERR! dest /storage/emulated/0/bot-baiano/node_modules/.bin/acorn npm ERR! errno -13 npm ERR! Error: EACCES: permission denied, unable to create symlink fro ...

Having trouble getting the Bootstrap 5 Modal to function properly within an Electron app

Facing an issue with my web app using Bootstrap 5, as the modal is not displaying properly. Below is the HTML code for the modal and the button that triggers it: <div class="modal" tabindex="-1" id=&quo ...

Leverage the power of ssh2-promise in NodeJS to run Linux commands on a remote server

When attempting to run the command yum install <package_name> on a remote Linux server using the ssh2-promise package, I encountered an issue where I couldn't retrieve the response from the command for further processing and validation. I' ...

Creating a JSON structure using an array in Typescript

Here is an example of my array structure: [ { "detail": "item1", "status": "active", "data": "item1_data" }, { "detail": "item2", "status": ...