遇见Nx.dev

672 阅读3分钟

遇见Nx.dev

什么是Nx

  • 简单来讲,Nx可以快速搭建一个新的独立项目甚至整个monorepo。它可以逐步采用,并随着项目的扩展而增长。
  • 官方介绍:nx.dev/getting-sta…
  • monorepo很多包管理工具都支持,熟知的:npm、pnpm、lerna
  • 那什么是monorepo呢?monorepo.tools(它会给你答案)

以我这个小白的角度来想,即要满足可以同时开发、维护、规范一系列子包,还要能同时构建、发布等一系流流程...,实际场景:对于前端业务子包、UI团队子包要相互引用...

😃我想用monorepo并且采用Nx的原因:有些公司招聘需要、同时我想要写一些业务场景的小项目,合在一项目里又不太适合,分开又要创建不同的GitHub仓库,所以决定all in one即可

⚠️ 本博客主要以记录为主,非常推荐大家如果感兴趣,一定要将文档过一遍

搭建React子包

# 根据提示创建一个空的monorepo
npx create-nx-workspace@latest --preset=npm
​
npm install -D @nrwl/react
nx g @nrwl/react:app my-new-app # 根据提示走完流程
.
├── README.md
├── babel.config.json
├── jest.config.ts
├── jest.preset.js
├── nx.json # nx配置文件
├── package.json
├── packages
│   ├── web-print # 我们的react项目
│   │   ├── jest.config.ts
│   │   ├── project.json # 项目nx配置文件,如lint、serve、build命令
│   │   ├── src
│   │   ├── tsconfig.app.json # 3个根TS相关的配置
│   │   ├── tsconfig.json
│   │   ├── tsconfig.spec.json
│   │   └── webpack.config.js # webpack配置
│   └── web-print-e2e # e2e测试项目
└── tsconfig.base.json
  • 配置webpack别名
// webpack.config.js
const { composePlugins, withNx } = require("@nrwl/webpack");
const { withReact } = require("@nrwl/react");
const { resolve } = require("path");
​
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), withReact(), (config) => {
  config["resolve"].alias = {
    "@": resolve(__dirname, "./src"),
    assets: resolve(__dirname, "./src/assets"),
  };
  return config;
});
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "allowJs": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "paths": { // 添加TS别名(仅为了编译通过,webpack会处理别名)
      "@/*": ["./src"],
      "assets/*": ["./src/assets"],
    }
  },
  // ...
}
  • 开发
nx run web-print:serve # 运行dev

Nx:运行任务

  • 运行单个任务
nx run web-print:lint
nx lint web-print # 上面cli的简写# 使用特定的配置项并覆盖默认
nx build web-print --configuration=production
  • 运行所有子项目的任务
nx run-many -t lint # 运行所有子项目的lint命令
  • 运行受git改动影响的子项目
nx affected -t lint

Nx:受影响的项目

  • affected:依赖于git元数据来确定您的workspace中提交影响到的项目
# commit代码后,修改部分代码,可以通过`nx affected:graph`查看受影响的项目
nx affected --target lint # 受影响的项目全部执行lint命令
nx affected -t lint # 受影响的项目全部执行lint命令

image-20230425170845729

Nx:缓存任务结果

  • nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
        "options": {
          // 针对以下命令启用缓存,如果文件未改动则无需再运行(前提:未改动属性需要生成一致输出,比如后台和数据库交互就不行,因为数据库可能随时变动)
          "cacheableOperations": ["build", "lint", "test", "e2e"]
        }
    }
  },
}
nx build web-print # 第一次会进行build编译
nx build web-print # 第二次因为相同文件则会直接读取缓存
# 缓存提示如下
>  NX   Successfully ran target build for project web-print (24ms)
 Nx read the output from the cache instead of running the command for 1 out of 1 tasks.

Nx可视化

  • Nx创建了存储库中所有项目之间的依赖关系图
nx graph # 启动一个前端项目并打开浏览器窗口
NX   Project graph started at http://127.0.0.1:4211/projects

Nx集成进编辑器

project.json任务执行器

{
  "serve": {
    // executor:运行哪个NX执行器(plugin名:命令名)
    // [包名, 执行器名] = [@nrwl/linter, eslint]
    "executor": "@nrwl/webpack:dev-server",
    "defaultConfiguration": "development",
    "options": { // 默认配置选项
      "buildTarget": "web-print:build",
      "hmr": true
    },
    "configurations": { // 配置,都以options key作为选项,使用时进行覆盖
      "development": {
        "buildTarget": "web-print:build:development"
      },
      "production": {
        "buildTarget": "web-print:build:production",
        "hmr": false
      }
    }
  },
    
  "echo": {
    "command": "echo 'hello world'" // 运行指定命令行
  }
}

Nx:环境变量

// 一般env文件名使用如下
.env // 生产环境
.env.local // 开发环境

⚠️ 所有环境变量都要以NX_作为前缀开头

// 例如react TSX中获取
console.log(process.env);
{ NX_CLI_SET: 'true', NX_LOAD_DOT_ENV_FILES: 'true', NX_STREAM_OUTPUT: 'true' , ...}