Build and run your project in Monorepo with PNPM
Project code organization: Polyrepo vs. Monorepo
There are two main ways to organize project code:
- Polyrepo: Spread project code in different repositories. This is the current standard practice. Multiple teams have their own warehouses, build products and pipelines, and have autonomy.
- Monorepo: Centralizes all project code in one repository. Projects are divided into applications and packages to facilitate code reuse and share standard functionality, which helps unify third-party package versions, recursively build source code for dependencies, and use the same tools for CI/CD pipelines.
Monorepo is used by many large tech companies, such as Yandex. Monorepo helps share ideas and best practices among teams and business units. For more information about Monorepo and related tools, please visit https://www.php.cn/link/b01ccf4f29b57b0b1bdb9407050db28d. This article will focus on a simple solution to build Monorepo using PNPM.
PNPM uses workspaces to integrate multiple projects in a single repository.
Environment setup
First, create an empty folder as a new Monorepo project. Initialize PNPM in the warehouse:
pnpm init
Then, create a pnpm-workspace.yaml
file describing the package folder:
// pnpm-workspace.yaml packages: - 'packages/**' - 'apps/**'
/packages
folder holds shared libraries, and the /apps
folder holds applications (for example, a standalone React Native mobile application and a web application that uses the same component or connection library to communicate with the API server).
This article will use a Telegram publishing robot as an example. Its source code is located on GitHub: https://www.php.cn/link/8164ca2fe04767628ac1c6813e8a0867. Download and extract to /apps/publish-bot
folder, then run the installation command:
pnpm install
Create Telegram Toolkit
Create a folder named /packages
in the telegram-utils
folder and initialize PNPM and TypeScript:
pnpm init && pnpm add -D typescript && pnpm tsc --init
This package will provide a function for combining text and captions from all messages (text, video and photo). Telegraf package needs to be installed:
pnpm add telegraf
All source code should be located in the /src
directory. To facilitate functional grouping, it is recommended to create different folders. The function of combining text is located in the /texts
folder, the code is as follows:
// packages/telegram-utils/src/texts/combineTexts.ts import { Message } from 'telegraf/types'; import { FmtString, join } from 'telegraf/format'; type GroupedMessages = { photos: Array<Message.PhotoMessage>; videos: Array<Message.VideoMessage>; text: Array<Message.TextMessage>; }; export const combineTexts = ({ photos, videos, text }: GroupedMessages) => { const photoTexts = photos .map(photo => photo.caption ? new FmtString(photo.caption, photo.caption_entities) : undefined) .filter((t): t is Required<FmtString> => t !== undefined); const videoTexts = videos .map(video => video.caption ? new FmtString(video.caption, video.caption_entities) : undefined) .filter((t): t is Required<FmtString> => t !== undefined); const allTexts = []; if (text.length) allTexts.push(join(text.map(t => new FmtString(t.text, t.entities))), '\n'); if (photoTexts.length) allTexts.push(join(photoTexts, '\n')); if (videoTexts.length) allTexts.push(join(videoTexts, '\n')); return join(allTexts, '\n'); };
Code description:
- The function inputs messages grouped by type: photo, video or text;
- Media messages should be converted to FMT strings containing title and title entities. For subsequent filtering,
undefined
should be returned; - Concatenate text arrays step by step, eventually combining all texts into one large message.
Create an index file for the /texts
folder:
pnpm init
Use the package.json
field in the exports
file to set up the export of the package function:
// pnpm-workspace.yaml packages: - 'packages/**' - 'apps/**'
To identify Monorepo packages in your application, add the prefix @monorepo
to all packages. Rename the package.json
package in the telegram-utils
file:
pnpm install
Add build script:
pnpm init && pnpm add -D typescript && pnpm tsc --init
Complete package.json
file:
pnpm add telegraf
Configure the TypeScript compiler: enable incremental compilation to save build time and process only changed parts; enable compound compilation to use project references. Define the /src
folder as rootDir
and the package's outDir
as /dist
. Updated tsconfig.json
:
// packages/telegram-utils/src/texts/combineTexts.ts import { Message } from 'telegraf/types'; import { FmtString, join } from 'telegraf/format'; type GroupedMessages = { photos: Array<Message.PhotoMessage>; videos: Array<Message.VideoMessage>; text: Array<Message.TextMessage>; }; export const combineTexts = ({ photos, videos, text }: GroupedMessages) => { const photoTexts = photos .map(photo => photo.caption ? new FmtString(photo.caption, photo.caption_entities) : undefined) .filter((t): t is Required<FmtString> => t !== undefined); const videoTexts = videos .map(video => video.caption ? new FmtString(video.caption, video.caption_entities) : undefined) .filter((t): t is Required<FmtString> => t !== undefined); const allTexts = []; if (text.length) allTexts.push(join(text.map(t => new FmtString(t.text, t.entities))), '\n'); if (photoTexts.length) allTexts.push(join(photoTexts, '\n')); if (videoTexts.length) allTexts.push(join(videoTexts, '\n')); return join(allTexts, '\n'); };
Integration
Go back to /apps/publish-bot
and add the @monorepo/telegram-utils
package to dependencies. Note that you do not need to specify the package version, use workspace:*
to indicate:
// packages/telegram-utils/src/texts/index.ts export * from './combineTexts';
Install dependencies:
// packages/telegram-utils/package.json "exports": { "./texts": { "import": "./src/texts/index.ts", "require": "./dist/texts/index.js" } }
Update the preview
command for publishing bots:
// packages/telegram-utils/package.json "name": "@monorepo/telegram-utils"
Update/apps/publish-bot/tsconfig.json
:
// packages/telegram-utils/package.json "scripts": { "build": "tsc -p tsconfig.json" }
Before building the application code, you need to build all dependencies:
// packages/telegram-utils/package.json { "name": "@monorepo/telegram-utils", "version": "1.0.0", "main": "index.js", "scripts": { "build": "tsc -p tsconfig.json" }, "keywords": [], "license": "ISC", "exports": { "./texts": { "import": "./src/texts/index.ts", "require": "./dist/texts/index.js" } }, "devDependencies": { "typescript": "^5.7.3" }, "dependencies": { "telegraf": "^4.16.3" } }
Summary
The release bot now uses internal shared libraries/packages and is located in Monorepo. This makes it possible to quickly build new features and reuse code across multiple applications.
Image via Gabriel Heinzer on Unsplash
The above is the detailed content of Build and run your project in Monorepo with PNPM. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.
