docs(devkit): initial project graph plugin guide (#5281)

This commit is contained in:
Jason Jean 2021-04-08 12:38:49 -04:00 committed by GitHub
parent 95cdeaed06
commit a01ea8ce25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 145 additions and 2 deletions

View File

@ -937,9 +937,14 @@
"file": "shared/monorepo-tags" "file": "shared/monorepo-tags"
}, },
{ {
"name": "Dependency Graph", "name": "Project Graph",
"id": "dependency-graph", "id": "dependency-graph",
"file": "shared/workspace/structure/dependency-graph" "file": "shared/workspace/structure/dependency-graph"
},
{
"name": "Extending the Project Graph",
"id": "project-graph-plugins",
"file": "shared/workspace/project-graph-plugins"
} }
] ]
}, },
@ -1998,6 +2003,11 @@
"name": "Dependency Graph", "name": "Dependency Graph",
"id": "dependency-graph", "id": "dependency-graph",
"file": "shared/workspace/structure/dependency-graph" "file": "shared/workspace/structure/dependency-graph"
},
{
"name": "Extending the Project Graph",
"id": "project-graph-plugins",
"file": "shared/workspace/project-graph-plugins"
} }
] ]
}, },
@ -3002,6 +3012,11 @@
"name": "Dependency Graph", "name": "Dependency Graph",
"id": "dependency-graph", "id": "dependency-graph",
"file": "shared/workspace/structure/dependency-graph" "file": "shared/workspace/structure/dependency-graph"
},
{
"name": "Extending the Project Graph",
"id": "project-graph-plugins",
"file": "shared/workspace/project-graph-plugins"
} }
] ]
}, },

View File

@ -0,0 +1,71 @@
# Extending the Project Graph of Nx
> This API is experimental and might change.
Nx views the workspace as a graph of projects that depend on one another. It's able to infer most projects and dependencies automatically. Currently, this works best within the Javascript ecosystem but it can be extended to other languages and technologies as well.
## Defining Plugins to be used in a workspace
In `nx.json`, add an array of plugins:
```json
{
...,
"plugins": [
"awesome-plugin"
]
}
```
These plugins are used when running targets, linting, and sometimes when generating code.
## Implementing a Project Graph Processor
Project Graph Plugins are chained together to produce the final project graph. Each plugin may have a Project Graph Processor which iterates upon the project graph. Plugins should export a function named `processProjectGraph` that handles updating the project graph with new nodes and edges. This function receives two things:
- A `ProjectGraph`
- Nodes in the project graph are the different projects currently in the graph.
- Edges in the project graph are dependencies between different projects in the graph.
- Some context is also passed into the function to use when processing the project graph. The context contains:
- The `workspace` which contains both configuration as well as the different projects.
- A `fileMap` which has a map of files by projects
The `processProjectGraph` function should return an updated `ProjectGraph`. This is most easily done using the `ProjectGraphBuilder` to iteratively add edges and nodes to the graph:
```typescript
import {
ProjectGraph,
ProjectGraphBuilder,
ProjectGraphProcessorContext,
DependencyType,
} from '@nrwl/devkit';
export function processProjectGraph(
graph: ProjectGraph,
context: ProjectGraphProcessorContext
): ProjectGraph {
const builder = new ProjectGraphBuilder(graph);
// Add a new node
builder.addNode({
name: 'new-project',
type: 'lib',
data: {
files: [],
},
});
// Add a new edge
builder.addDependency(
DependencyType.static,
'existing-project',
'new-project'
);
return builder.getProjectGraph();
}
```
## Visualizing the Project Graph
You can then visualize the project graph as described [here](dependency-graph).

View File

@ -4,7 +4,7 @@ To be able to support the monorepo-style development, the tools must know how di
<iframe width="560" height="315" src="https://www.youtube.com/embed/cMZ-ReC-jWU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <iframe width="560" height="315" src="https://www.youtube.com/embed/cMZ-ReC-jWU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## How the Dependency Graph is Built ## How the Project Graph is Built
Nx creates a graph of all the dependencies between projects in your workspace using two sources of information: Nx creates a graph of all the dependencies between projects in your workspace using two sources of information:

View File

@ -1,15 +1,24 @@
import { TargetConfiguration, Workspace } from '@nrwl/tao/src/shared/workspace'; import { TargetConfiguration, Workspace } from '@nrwl/tao/src/shared/workspace';
/**
* Some metadata about a file
*/
export interface FileData { export interface FileData {
file: string; file: string;
hash: string; hash: string;
ext: string; ext: string;
} }
/**
* A list of files separated by the project they belong to
*/
export interface ProjectFileMap { export interface ProjectFileMap {
[projectName: string]: FileData[]; [projectName: string]: FileData[];
} }
/**
* A Graph of projects in the workspace and dependencies between them
*/
export interface ProjectGraph { export interface ProjectGraph {
nodes: Record<string, ProjectGraphNode>; nodes: Record<string, ProjectGraphNode>;
dependencies: Record<string, ProjectGraphDependency[]>; dependencies: Record<string, ProjectGraphDependency[]>;
@ -18,38 +27,86 @@ export interface ProjectGraph {
allWorkspaceFiles?: FileData[]; allWorkspaceFiles?: FileData[];
} }
/**
* Type of dependency between projects
*/
export enum DependencyType { export enum DependencyType {
/**
* Static dependencies are tied to the loading of the module
*/
static = 'static', static = 'static',
/**
* Dynamic dependencies are brought in by the module at run time
*/
dynamic = 'dynamic', dynamic = 'dynamic',
/**
* Implicit dependencies are inferred
*/
implicit = 'implicit', implicit = 'implicit',
} }
/**
* A node describing a project in a workspace
*/
export interface ProjectGraphNode<T = any> { export interface ProjectGraphNode<T = any> {
type: string; type: string;
name: string; name: string;
/**
* Additional metadata about a project
*/
data: T & { data: T & {
/**
* The project's root directory
*/
root?: string; root?: string;
/**
* Targets associated to the project
*/
targets?: { [targetName: string]: TargetConfiguration }; targets?: { [targetName: string]: TargetConfiguration };
/**
* Files associated to the project
*/
files: FileData[]; files: FileData[];
}; };
} }
/**
* A dependency between two projects
*/
export interface ProjectGraphDependency { export interface ProjectGraphDependency {
type: DependencyType | string; type: DependencyType | string;
/**
* The project being imported by the other
*/
target: string; target: string;
/**
* The project importing the other
*/
source: string; source: string;
} }
/**
* Additional information to be used to process a project graph
*/
export interface ProjectGraphProcessorContext { export interface ProjectGraphProcessorContext {
/**
* Workspace information such as projects and configuration
*/
workspace: Workspace; workspace: Workspace;
fileMap: ProjectFileMap; fileMap: ProjectFileMap;
} }
/**
* A function that produces an updated ProjectGraph
*/
export type ProjectGraphProcessor = ( export type ProjectGraphProcessor = (
currentGraph: ProjectGraph, currentGraph: ProjectGraph,
context: ProjectGraphProcessorContext context: ProjectGraphProcessorContext
) => ProjectGraph; ) => ProjectGraph;
/**
* A plugin for Nx
*/
export interface NxPlugin { export interface NxPlugin {
processProjectGraph: ProjectGraphProcessor; processProjectGraph: ProjectGraphProcessor;
} }