DEV Community

Devin Shoemaker
Devin Shoemaker

Posted on • Updated on

Building an Nx Plugin to Add Dependencies to a Project

Nx community plugins are a powerful new technology by Nrwl that allows you to customize the functionality of Nx. If you have not yet watched Nrwl's official Nx Plugin guide then I highly recommend starting there.

When building an Nx Plugin you may want to add dependencies when a schematic is executed. Perhaps you need to add dependencies during an ng add command, or maybe you only want to add dependencies when a particular flag is passed into a schematic (such as whether routing will be enabled or not). Adding dependencies with an Nx Plugin is very easy using the @nrwl/workspace library provided by Nrwl.

Implementation

First, add the addDepsToPackageJson library:

import { addDepsToPackageJson } from '@nrwl/workspace';
Enter fullscreen mode Exit fullscreen mode

Next, create a new function that returns the addDepsToPackageJson function. This function accepts two arguments; a dependencies and devDependencies object to merge with the users package.json:

function addDependencies(): Rule {
  return addDepsToPackageJson(
    {
      '@ionic/react': ionicReactVersion,
      ionicons: ioniconsVersion
    },
    {
      '@nxtend/ionic-react': nxtendVersion,
      '@testing-library/user-event': testingLibraryUserEventVersion,
      '@testing-library/jest-dom': testingLibraryJestDomVersion
    }
  );
}
Enter fullscreen mode Exit fullscreen mode

In the example above, I am setting the library versions based on variables in a separate versions.ts file. This allows me to easily view and maintain what dependency versions my plugin is importing.

Finally, just execute this function in you schematic default function chain:

export default function(): Rule {
  return chain([
    addDependencies()
  ]);
}
Enter fullscreen mode Exit fullscreen mode

Testing

Adding a unit test for this is trivial. Here is an example from my @nxtend/ionic-react plugin:

describe('init', () => {
  let appTree: Tree;

  const testRunner = new SchematicTestRunner(
    '@nxtend/ionic-react',
    join(__dirname, '../../../collection.json')
  );

  beforeEach(() => {
    appTree = createEmptyWorkspace(Tree.empty());
  });

  it('should add Ionic React dependencies', async () => {
    const result = await testRunner
      .runSchematicAsync('init', {}, appTree)
      .toPromise();
    const packageJson = readJsonInTree(result, 'package.json');
    expect(packageJson.dependencies['@ionic/react']).toBeDefined();
    expect(packageJson.dependencies['ionicons']).toBeDefined();
    expect(packageJson.dependencies['react']).toBeDefined();
    expect(packageJson.dependencies['react-dom']).toBeDefined();
    expect(packageJson.devDependencies['@nrwl/react']).toBeDefined();
    expect(packageJson.devDependencies['@nxtend/ionic-react']).toBeDefined();
    expect(
      packageJson.devDependencies['@testing-library/user-event']
    ).toBeDefined();
    expect(
      packageJson.devDependencies['@testing-library/jest-dom']
    ).toBeDefined();
  });
});
Enter fullscreen mode Exit fullscreen mode

In this test we create a new workspace, execute the init schematic that executes the addDepsToPackageJson method, and then asserts that these dependencies are present in the package.json.

Conclusion

Nx Plugins are an exciting new technology with a lot of potential. Adding dependencies to a project with Nx Plugins is fairly simple, but feel free to check out my @nxtend/ionic-react Nx Plugin for more examples.

Resources

Nx

Nx Plugin Guide

@nxtend/ionic-react GitHub

Discussion (1)

Collapse
patelvimal profile image
vimal patel

Instead of unit test how to test custom nx plugin locally in empty nx workspace. can you please help me with this?