Introduction Link to heading

When working with CDK in an enterprise environment, you will almost certainly want to create a library of your own constructs. That library is probably going to be private and is going to need to live somewhere. The traditional place for nodejs libraries to live is npmjs.com. However, there are some alternatives available.

Criteria Link to heading

  • Availability: How likely is the service to actually be working at any given time
  • Cost: How much $$$
  • ACL: Access and Control
  • DevOps Ease of Use: My opinion about how easy it is to use
  • Developer Ease of Use: My opinion about how easy it is for my developers to use

The Contenders Link to heading

npmjs Link to heading

The incumbent.

  • Availability: status It’s history for availability has been surprisingly decent. No guarantees or SLA as far as I can see.
  • Cost: $7/month ($84 / year)
  • ACL: Primitive. Doesn’t integrate with… anyone.
  • DevOps Ease of Use: No IaC as far as I can tell. Yet another vendor. No real integration with… anything. You’ll be forced to create a machine user for your CI/CD system and that user will be a superuser.
  • Developers Ease of Use: Your developers already know how to use it. Setup is bone-head easy.

AWS CodeArtifact Link to heading

The Amazon offering.

  • availability: status. SLA is fine for an artifactory, IMHO.
  • cost: pricing there’s a pretty generous free tier. Linear cost scaling after that and it stays cheap.
  • ACL: Just more IAM. If you’re already heavily AWS, this is great.
  • DevOps Ease of Use: I don’t see any CDK L2 constructs, but at least there’s L1. If you’re using CodeBuild/CodePipeline (my condolences) then identity is all AWS in-house. So you’re pretty set. Otherwise you can probably leverage the identity you’re already using in your CI/CD system for deploys to also publish etc.
  • Developer Ease of Use: Logging in requires you to generate an ephemeral token which goes in your .npmrc file. Great for security, not so great developer experience. The auth docs are decent but I note that they don’t describe using --scope to manage which packages should be sourced from which repo. CodeArtifact does allow you to configure it as a read-thru cache. I suppose this is great if you really need to achieve high availability. Or if you’re really trying to blast through that free tier.

GitHub Packages Link to heading

GitHub bought NPMJS and then released Packages

  • availability: status I couldn’t find a formal SLA.

  • cost: pricing the free tier is exactly half as generous as AWS. Stepping it up is $48/user/year, since it is included in the price of GitHub Teams. Not available as a separate offering.

  • ACL: It’s just another facet of GitHub. You’re probably already managing a GitHub org, so the extra cost of management is minimal.

  • DevOps Ease of Use: Not even the terraform provider appears to support IaC for Packages. If you’re using GitHub Actions, identity management is super-slick. GitHub has already thought through the build & publish pipeline for you. If you’re on another CI/CD system, well, you probably already have a GitHub machine user anyway. If you’re using projen, publishing the module is as easy as putting the following in your .projenrc.js.

    {
      name: '@node-scope-matches-gh-org/project-name',
      npmRegistry: 'npm.pkg.github.com',
    }
    

    See Elad’s PR for why you don’t even have to hack your NPM_TOKEN anymore. There’s an example at projen-github-demo and a presentation about how to do it.

  • Developer Ease of Use: The user documentation is excellent and covers the concept of scoping by default. Your developers will have to do a small amount of extra configuration, but, it’s a one-time config and it’s not enough to hate you. If they’re already using the totally awesome gh cli tool, they’ve already set up a PAT which is about half the work to configuring Packages with npm / yarn / etc.

    TL;DR: put the following in your ~/.npmrc (note that the nmpjs stuff is just for legacy support)

    //registry.npmjs.org/:_authToken=MY_NPM_TOKEN
    registry=https://registry.npmjs.org/
    
    //npm.pkg.github.com/:_authToken=ghp_MY_GITHUB_TOKEN_WITH_AT_LEAST_read:packages_PRIVS
    @node-scope-matches-gh-org:registry=https://npm.pkg.github.com/
    

Conclusion Link to heading

I think it’s really a battle between Packages (because github integration is seamless) and old-school npmjs (because everything is already written to work with it). I hate to add an extra vendor though, so I’m leaning towards Packages.