RendleLabs

Front-end Package Management with UnpkgCli 2.0

TL;DR

Now that .NET Core 2.1 is finally final, the dotnet tool feature is properly supported, so I’ve made a new version of my unpkg command line tool that supports it. You can get it by running:

$ dotnet tool install -g RendleLabs.UnpkgCli

Once it’s installed, you can run it from any project as just unpkg; global tools don’t need the dotnet command anymore.

This tool is open source: you can find it on GitHub.

Caveat Utilitor!

This is a complicated problem space, so this tool might not work perfectly for some packages. Also, the build task is new and I’ve never written one before, so there may possibly be some issues there. If you have any problems, please open an Issue on GitHub to let me know. Thanks.

OK, what is this now?

It’s my simple tool for managing front end (i.e. JavaScript and CSS) packages in your ASP.NET Core project. There’s been some debate about this with reference to Microsoft’s LibraryManager tool for Visual Studio, so I’m going to explain this as best I can, and you can take it or leave it.

I make some web projects with very simple front end package requirements. I use Bootstrap, usually with one of the Bootswatch themes, and that requires jQuery, along with a couple of plug-ins. These projects generally have small, hand-written scripts, often one per page. The stylesheets and scripts are included using boring old <link> and <script> tags, with the <environment> helpers and CDN URLs and fallbacks. These are not complicated Single Page Apps or Progress Web Apps with hundreds of lines of TypeScript, using the latest Angular or React or whatever. There is no webpack or npm build process.

I want a nice, easy, repeatable way to install these packages directly into my wwwroot/lib folder. I don’t want to depend on Node.js and NPM and Gulp just to download a dozen files and copy them from wherever they’re hiding in node_modules. So I made this tool.

Important point: I also make some web projects that are SPAs or PWAs and I do use big frameworks and TypeScript and I do have a webpack build for those projects and so then I do use NPM to install the dependencies. It’s all about the right tool for the job.

How does it work?

I started out looking at NPM as the source for packages, looking for an API to interrogate it directly. While I was looking, I found UNPKG on GitHub. I knew about the unpkg.com CDN, but I hadn’t realised how it works: it grabs the packages directly from the NPM registry and hosts them on a global CDN. Even better, it has this thing where you can add a ?meta query-string to a URL and it will respond with a JSON description of the package. Basically, it was already doing the heavy-lifting, so I decided to hitch a ride.

Once you’ve installed UnpkgCli (see above), you open a command prompt in your web project directory and run

$ unpkg add jquery bootstrap

and the tool grabs the metadata from UNPKG, then downloads everything it finds into wwwroot/lib/{packageName}. It also records the details of what it’s downloaded in a file called unpkg.json, so you can just do unpkg restore to re-download all the files.

In some cases, downloading everything is not what you want, because some everythings are really, really big. If the package has a dist directory, only the contents of that will be downloaded, but if it doesn’t, everything will get downloaded. So you can control this to a certain extent by providing more information.

Example 1: the ASP.NET Core SignalR package includes cjs and esm directories that contain a bunch of files you don’t need for simple script tags. The ones you do need are in the browser directory, so you can use this command to grab those:

$ unpkg add @aspnet/signalr/browser

Example 2: Bootswatch distributes all the themes in the same package, and you probably only want one of them, so you can specify the one you want like this:

$ unpkg add bootwatch/yeti

Editing unpkg.json

Even with these extra controls, you might want to do some extra tweaking to limit the files being downloaded. For example, the font-awesome package includes all the less and scss files, which you probably don’t want. So feel free to open up the unpkg.json file and edit it to remove the cruft.

While you’re in there, you’ll notice that for each file, it records the CDN URL and the SHA384 hash used for integrity attributes, so you can copy these into your <link> and <script> tags.

Automatic restore

One of the big reasons for making this was CI builds, whether on regular CI servers or as Docker builds, where you might not have or want Node installed. Of course, you probably don’t want to have to dotnet tool install this package on those servers either, and you don’t have to. For that, there is an MSBuild task package, RendleLabs.Unpkg.Build, that you can add to your project which will trigger a restore as part of the build process. To make it really easy, you can add this package reference to your project by running:

$ unpkg --add-task

and it will install the package for you, at which point the restore will be run on every build. Don’t worry: it’s clever enough to work out when the file already exists, so it won’t be re-downloading megabytes of stuff every time you hit F5.

How does this compare to LibraryManager?

I haven’t tried LibraryManager, so I can’t be 100% sure how this compares, but there are some fundamental differences.

  • unpkg is explicitly designed as a command line tool, whereas Library Manager is a Visual Studio feature. I don’t know if Microsoft are planning on adding it to VS for Mac or VS Code, and I’m pretty sure they won’t be contributing it to Rider. It seems to work by providing completions* in its .json file; there’s no CLI mode at all. So if you, or anybody on your project, is using some other editor or IDE, then unpkg might make more sense for you.
    • * FWIW, one thing I might do if this project gains any traction is look at CLI completions for Bash and PowerShell. Maybe you could build that and send me a PR!)
  • Library Manager uses a couple of different package sources (cdnjs and local filesystem) out of the box, and can be extended with more. unpkg only works with unpkg.
  • unpkg is out now. Library Manager is still in the preview VS2017 channel. (Timestamp: 2018-05-31)

Coming soon

I’m working on Tag Helpers that will use the metadata from unpkg.json to provide nice shortcuts in <link> and <script> tags. I still haven’t worked out the details, particularly the integration with the build-in ASP.NET Core tag helpers, but I think it’ll look something like this:

<script unpkg-cdn="jquery" ... ></script>

That will generate the src attribute, as well as integrity and crossorigin attributes. Getting it to work with asp-fallback-href is the interesting bit, but I’ll figure it out.

markrendle

markrendle

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.