NX added a new trick to speed up your e2e pipeline.
Tags: nx, testing, ci, pipeline
Published: 2023-03-31 14:55:54

One of the key features of NX is its caching mechanism. It only rebuilds the parts of the codebase that have changed, saving time and resources.

Prior to 15.9.0, NX generated an e2e application by default but did not take advantage of its full capabilities.

```json
{
  "name": "e2e",
  ..
  "targets": {
    "e2e": {
      "executor": "@nrwl/cypress:cypress",
      "options": {
        "cypressConfig": "e2e/cypress.config.ts",
        "devServerTarget": "demo-app:serve:development",
        "testingType": "e2e"
      },
      "configurations": {
        "production": {
          "devServerTarget": "demo-app:serve:production"
        }
      }
    },
    ..
  },
  ..
}
```

The code block above shows that the e2e tests are dependent on the application's `serve` command.

While this approach is functional, it does not fully utilize the capabilities of NX. The use of the `serve` command in the e2e tests requires rebuilding the entire application from scratch each time, even if there were no changes to the codebase. This makes e2e testing slow and inefficient, particularly in large codebases.

When you create a fresh NX workspace containing an application and an e2e application. Both projects have new configurations in the `project.json` file. The NX team has implemented a new `serve-static` command that leverages the `@nrwl/web:file-server` executor to build and serve the application using an HTTP server.

```json
"serve-static": {
  "executor": "@nrwl/web:file-server",
  "options": {
    "buildTarget": "demo-app:build"
  }
}
```

Why did they do this? Is it not the same as using the `serve` command? The main difference is that the process is now divided into two steps: first, building the application, and then serving the resulting build. This approach allows NX to cache the build. If there are no changes, it can quickly serve the cached build without having to rebuild it from scratch.

To speed up your pipelines using this approach, you can add a `ci` tag to the configuration in the `project.json` and set the `devServerTarget` to `<app-name>:serve-static`.

```json
{
  "name": "e2e",
  ..
  "targets": {
    "e2e": {
      "executor": "@nrwl/cypress:cypress",
      "options": {
        "cypressConfig": "e2e/cypress.config.ts",
        "devServerTarget": "demo-app:serve:development",
        "testingType": "e2e"
      },
      "configurations": {
        "production": {
          "devServerTarget": "demo-app:serve:production"
        },
        "ci": {
          "devServerTarget": "demo-app:serve-static"
        }
      }
    },
    ..
  },
  ..
}
```

To execute the e2e tests in the pipeline, simply add the command `nx e2e <app-name> - configuration=ci`. This will trigger the tests using the `ci` configuration, which utilizes the `serve-static` command to serve the cached build and speed up the testing process. With NX Cloud it will be even better!

# Notes
## Issue
If you are creating an NX workspace using version 15.1.9. In that case, you may encounter issues with the default `serve-static` command as it uses an incorrect executor. You can refer to the issue that I created on GitHub. To resolve the issue, you'll need to replace the executor with `@nrwl/web:file-server` and install the `@nrwl/web` package.