vNext C# Dependency Reference using NPM instead of NuGet

Natively, Visual Studio 2015 integrates with NuGet for project dependency resolution, see here for a bit more info. This workflow is heavily tied to NuGet, which in my opinion is both good and bad. While it's nice that Microsoft is making strides away from monolithic applications and embracing more modular development practices, the choice of NuGet as the sole source of dependency resolution is a bit frustrating.

The primary reason for this view is my experience with NPM. NPM is commonly used with Node.js and JavaScript development, though it isn't integral that it be used for these purposes. Functionally, there is a package.json file that describes a package and links to dependencies. This package also includes the reference to the source location.

When you install a package via NPM, it will go out to the registry, find the source code path, and will retrieve the source code from the actual source code path. It will deposit the package (and all of its dependencies inside the node_modules folder.

What's great is NPM's direct link to source control. Functionally npmjs.org really just provides a jumping off point to find the actual source code for the package. Furthermore, the source code is downloaded and available on your system for your perusal (if you so desire).

A biproduct of the direct integration to source control is the ability to directly link to a Git repository instead of using the registry. You can specify a package reference with a URL to a Git repository and it will automatically pull down the code from that Git repository. This is especially useful if you fork a package and want to reference your fork instead of the published package.

From my understanding, granted I haven't spent much time with this workflow, you can create private NuGet feeds and reference those. However, this seems (again see my previous caveat) a bigger endevour than simply linking to a Git source ref.

Additionally, one of my favorite NPM features is npm link. This allows me to take the source of a package and create a global reference on my machine to that source. In other projects I can link to this reference temporarily. The end result is you can modify the source for dependency package and use that in another project. It's a necessary feature for modularizing applications where different modules are in active development.

Ok, so how can you pull in C# project references via NPM? Well with VS2015 RC here's the "workflow" I came up with that "sort of" works:

1) Create a package.json in your project and link to the NPM package.

{
  "dependencies": {
    "ResponseTimer": "bmancini55/aspnet-responsetimer"
  }
}

2) Install the NPM package, in this case ResponseTimer. Restore was not working for me even though this is a valid NPM path. I just installed the NPM modules from the command line.

cd src\vNextNpm  
npm install  

3) In your solution, you will need to modify global.json to include a new projects entry that points to the newly added node_modules path.

{
    "projects": [ "src", "test", "src/vNextNpm/node_modules/ResponseTimer/src" ],
    "sdk": {
        "version": "1.0.0-beta4"
    }
}

4) Now from your original project, you can add a Reference in project.json that points to the dependency. In the case below, the dependency added is ResponseTimer.

{
  "version": "1.0.0-*",
  "description": "",
  "authors": [ "" ],
  "tags": [ "" ],
  "projectUrl": "",
  "licenseUrl": "",

  "dependencies": {
    "ResponseTimer": ""
  },

  "commands": {
    "vNextNpm" : "vNextNpm"
  },

  "frameworks" : {
    "dnx451": { },
    "dnxcore50" : {
      "dependencies": {
        "System.Console": "4.0.0-beta-22816",
        "System.Collections": "4.0.10-beta-22816",
        "System.Linq": "4.0.0-beta-22816",
        "System.Threading": "4.0.10-beta-22816",
        "Microsoft.CSharp": "4.0.0-beta-22816"
      }
    }
  }
}

Here's a working example. https://github.com/bmancini55/vnext-npm
Note* you will need to manually pull in the NPM dependency from the command line.

Ultimately this is not a great solution... but it does sort of work. Share your thoughts!

comments powered by Disqus