Lerna / Nx / Turborepo 或其他非 js 应用程序的 monorepo 系统 (php)

发布于 2025-01-12 04:27:07 字数 452 浏览 2 评论 0原文

我有带有 /frontend (JS/Vue) 和 /backend (PHP) 以及 docker-compose.yml 的存储库用于开发。但现在我需要添加另一个 JS 前端,它将共享一些组件、库等。我不想重复代码,所以我发现我可以使用很多工具来实现此目的,例如 lernanxturborepo 等用于使用共享包管理 monorepo。

问题是我发现的所有教程和示例存储库都基于 100% JS 存储库,例如前面的 React + 后面的 Nest 等。

所以问题 - 使用 for ex。 nx 在具有多种语言的存储库上有意义,只是为了在 JS 包上利用它?如果是,目录结构应该是什么样子?或者也许有更好的 monorepo 工具是为多种语言设计的,而不仅仅是 JS?

I have repository with /frontend (JS/Vue) and /backend (PHP) and docker-compose.yml for development. But now I need to add another JS frontend that will be sharing some components, libs etc. I do not want to repeat code, so I found that I can use many tools for this like lerna, nx, turborepo and more for managing monorepo with shared packages.

Problem is that all tutorials and example repos I found are based on 100% JS repos, like React on front + Nest on back etc.

So question - using for ex. nx makes sense on repos with multiple languages, just to leverage it on JS packages? If yes, how directory structure should look like? Or maybe there are better monorepo tools that are designed for multiple languages, not just JS?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十秒萌定你 2025-01-19 04:27:07

我在 Nx monorepo 中使用 Angular 和 PHP(Yii 框架),两者都工作正常。不知道 Lerna 和 Turborepo 是如何工作的,但 Nx 允许运行 CLI 命令,我将其用于 PHP 部分。我的 monorepo 看起来有点如下:

- apps // <- folder holding my projects
--- project-1
--- project-2
------ web // <- Main frontend app (Angular/JS)
------ electron // <- other JS apps like mobile, capacitor, extension, ...
------ api // <- PHP api overridden config files

- libs
--- web // <- shared JS stuff, most people call it 'shared' folder instead
------ ui // <- my shared design system
--- electron
--- project-2 // <- specific project overrides and locally shared stuff
------ services
------ data-access 
------ ui
--------- button // <- overriding a component from my design system to only apply in project-2
------ api // <- PHP api but only holding overridden files
--- php
------ api // <- shared PHP api code
------ auth // <- another shared PHP app
------ shell // <- another shared PHP app

- dist // <- is where NX will will put all generated code from all apps/libs 

主要思想是,我编写的每个代码都放在 libs 文件夹中(JS 的 libs/web 和 PHP 的 libs/php)以及生成的 Nx 库中,因此它有一个名称(如 php-api),可以从任何地方链接它,还有一个 project.json 文件保存 Nx 配置。

这是我的基本共享代码。一次编写,适用于任何需要它的项目或库。

然后,libs/project-2 将保存 project-2 特定代码。仅在该应用程序页面内共享的内容以及我从前面提到的文件夹(或以前的共享层)覆盖的内容,如上面的按钮示例。

apps 内的代码尽可能小,主要是布局和配置。这几乎就是大多数 Nx 文档/教程的建议(对于 JS)。我对 PHP 做了同样的事情:

  1. 我将所有 Yii api 代码放入 libs/php/api
  2. 特定于 project-2 应用程序的所有内容(例如模型、控制器) , ...) 文件夹和/或文件位于 libs/project-2/api 内部
  3. 主要配置文件(如 .env)位于 apps/project-2/api 内部
  4. 每个 lib 文件夹都需要一个 project.json 文件定义它:
{
  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
  "projectType": "library",
  "sourceRoot": "libs/php/api",
  "tags": ["scope:php", "type:api"]
}
  1. 在我的例子中,使用 Angular,根级别有一个 angular.js 文件,我在其中声明了每个 PHP 库名称,以便 Nx 检测到它,我只需添加两行:<代码>“php-api”:“libs/php/api”和“project-2-api”:“libs/project-2/api”,

  2. apps/project- 内2/api文件夹,我添加了一个project.json 文件包含以下内容:

{
  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
  "projectType": "application",
  "sourceRoot": "apps/project-2/api",
  "targets": {
    "build": {
      "executor": "nx:run-commands",
      "options": {
        "commands": [
          "mkdir -p dist/apps/project-2",
          "rsync -rtul libs/php/api dist/apps/project-2",
          "rsync -rtul libs/project-2/api dist/apps/project-2",
          "rsync -rtul apps/project-2/api dist/apps/project-2"
        ],
        "parallel": false
      }
    },
    "serve": {
      "executor": "nx:run-commands",
      "dependsOn": ["build"],
      "options": {
        "commands": ["php -S localhost:8081 -t dist/apps/project-2/api/web"]
      }
    }
  },
  "implicitDependencies": ["php-api"]
}

它定义了 build>serve 脚本,所以我可以使用 Nx cli 来运行它们,第一个只会将 PHP 文件复制到 dist 文件夹(尊重我的覆盖层次结构),而第二个使用 PHP 的内置服务器提供最终文件夹:

> nx 运行project-2-api:build

> nx run project-2-api:serve

请注意,我的第一个脚本使用 rsync -rtul 来复制文件,您可以使用 cp -R 代替,我只是发现 rsync 速度更快,因为它能够(使用这些选项)跳过未更改的文件。

所以主要的想法是,我的大部分代码都是编写一次,在需要时覆盖,一个单一的设计系统,我只覆盖它的 CSS,以使用新应用程序获得不同的外观。我对 PHP 也做了同样的事情,即使不直接支持,我也只是使用 nx:run-commands 执行器来执行诸如移动文件、实时构建或部署之类的操作。

保存时自动更新

我使用 VSCode,其他 IDE 也可能有类似的方式,在我的情况下,我使用名为 run-on-save 根据提供的正则表达式保存文件时执行命令。我的项目的配置如下:

"emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "(/(project-2|php)/(api|yii-shared)/.+).php$",
        "cmd": "nx run project-2-api:build --skip-nx-cache"
      },
      {
        "match": "(/(project-2|php)/(auth|yii-shared)/.+).php$",
        "cmd": "nx run project-2-auth:build --skip-nx-cache"
      },
      {
        "match": "(/(project-2|php)/(shell|yii-shared)/.+).php$",
        "cmd": "nx run project-2-shell:build --skip-nx-cache"
      }
    ]
  }

每次我按 CTR+S 保存 PHP 文件时,dist 文件夹都会自动更新。

I use Angular and PHP (Yii Framework) inside an Nx monorepo and both works fine. No idea how Lerna and Turborepo works, but Nx allow running CLI commands, I use that for the PHP part. My monorepo looks a bit as follow:

- apps // <- folder holding my projects
--- project-1
--- project-2
------ web // <- Main frontend app (Angular/JS)
------ electron // <- other JS apps like mobile, capacitor, extension, ...
------ api // <- PHP api overridden config files

- libs
--- web // <- shared JS stuff, most people call it 'shared' folder instead
------ ui // <- my shared design system
--- electron
--- project-2 // <- specific project overrides and locally shared stuff
------ services
------ data-access 
------ ui
--------- button // <- overriding a component from my design system to only apply in project-2
------ api // <- PHP api but only holding overridden files
--- php
------ api // <- shared PHP api code
------ auth // <- another shared PHP app
------ shell // <- another shared PHP app

- dist // <- is where NX will will put all generated code from all apps/libs 

The main idea is that, every code I write goes inside that libs folder (libs/web for JS and libs/php for PHP) and within a generated Nx library so it has a name (like php-api) to link it from everywhere and a project.json file holding Nx configs.

That is my base shared code. Written once, for any project or lib needing it.

libs/project-2 will then hold project-2 specific code. Things that are only shared inside that app pages plus things I override from the previously mentioned folders (or previous shared layer) like the button example above.

Code inside apps is as tiny as possible, mainly layouts and configs. That is pretty much how most Nx documentation/tutorials out there would suggest (for JS). I do the same for PHP:

  1. I've put all of my Yii api code inside libs/php/api
  2. Everything specific to the project-2 app (like models, controllers, ...) folders and/or files goes inside libs/project-2/api
  3. main config files (like .env) goes inside apps/project-2/api
  4. Each lib folder needed a project.json file defining it:
{
  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
  "projectType": "library",
  "sourceRoot": "libs/php/api",
  "tags": ["scope:php", "type:api"]
}
  1. In my case, using Angular, there was an angular.js file at root level, where I declared each PHP lib name so Nx detects it, I simply added 2 lines: "php-api": "libs/php/api" and "project-2-api": "libs/project-2/api",

  2. Inside apps/project-2/api folder, I added a project.json file with the following content:

{
  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
  "projectType": "application",
  "sourceRoot": "apps/project-2/api",
  "targets": {
    "build": {
      "executor": "nx:run-commands",
      "options": {
        "commands": [
          "mkdir -p dist/apps/project-2",
          "rsync -rtul libs/php/api dist/apps/project-2",
          "rsync -rtul libs/project-2/api dist/apps/project-2",
          "rsync -rtul apps/project-2/api dist/apps/project-2"
        ],
        "parallel": false
      }
    },
    "serve": {
      "executor": "nx:run-commands",
      "dependsOn": ["build"],
      "options": {
        "commands": ["php -S localhost:8081 -t dist/apps/project-2/api/web"]
      }
    }
  },
  "implicitDependencies": ["php-api"]
}

That defines both build and serve scripts, so I can use Nx cli to run them, the first will just copy PHP files to dist folder (respecting my overriding hierarchy) while the second uses PHP's built-in server to serve the final folder:

> nx run project-2-api:build

> nx run project-2-api:serve

Note that my first script uses rsync -rtul to copy files, you can use cp -R instead, I just found rsync much faster as it has the ability (with those options) to skip unchanged files.

So main idea is that, Most of my code is written once, overrides when needed, a single design system I only override its CSS for a different look with a new app. And I do the same for PHP, even if not directly supported, I simply use nx:run-commands executer for things like moving files, building or deploying live.

Auto update on save

I use VSCode, other IDE may also have a similar way, in my case I use an external extension called run-on-save that executes commands when saving a file based on provided regex. Its configuration for my project looks a bit as follow:

"emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "(/(project-2|php)/(api|yii-shared)/.+).php
quot;,
        "cmd": "nx run project-2-api:build --skip-nx-cache"
      },
      {
        "match": "(/(project-2|php)/(auth|yii-shared)/.+).php
quot;,
        "cmd": "nx run project-2-auth:build --skip-nx-cache"
      },
      {
        "match": "(/(project-2|php)/(shell|yii-shared)/.+).php
quot;,
        "cmd": "nx run project-2-shell:build --skip-nx-cache"
      }
    ]
  }

Every time I hit CTR+S to save a PHP file, dist folder is automatically updated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文