Using Fabric.js (Fabric) without Cairo for web use – notes on NPM

  • report
    Click for Disclaimer
    This Post is over a year old (first published about 5 years ago). As such, please keep in mind that some of the information may no longer be accurate, best practice, or a reflection of how I would approach the same thing today.
  • infoFull Post Details
    info_outlineClick for Full Post Details
    Date Posted:
    May. 12, 2019
    Last Updated:
    May. 12, 2019
  • classTags
    classClick for Tags

Fabric.js is an amazing open-source library for Canvas manipulation with Javascript – I ended up using it heavily for this project, and have been meaning to post this writeup for a while on some ways to bundle Fabric into your dependencies, without requiring that the system your repo is built on has Cairo installed. These solutions only work if you don’t need any of the node-canvas features, which is true for many web uses of Fabric.

By default, if you add Fabric.js as a dependency to your package.json and/or run npm install, it will kick off a build process that will fail  if Cairo is not installed globally on your build system. This is because node-canvas (published under NPM as just “canvas“) is a dependency of Fabric.js, and in the canvas package.json, the install command will run a build command that requires Cairo. 

Easy option: Just ignore the build errors and grab JS from /dist

Although it probably goes against best practices, the nice builders of Fabric have checked in pre-built versions of the Fabric.js library into their repository, built without node-canvas support. This means that, as long as you just need the browser version of Fabric, you can simply pull the pre-built file out of /node_modules for use in your app. For example, as a build step, simply copy like this:

cp node_modules/fabric/dist/fabric.js public/lib/js/fabric.js

Because Canvas is an optional dependency, NPM install will succeed, even though it will spit out all those build errors without Cairo installed.

As a side note, you could even pull Fabric.js from its Github location rather than NPM, since NPM install lets you specific Git repos as sources for dependencies.

Another option – check in your own pre-built version:

This is true for almost any scenario, not just for Fabric; you can always build the file the end user will need yourself, in your dev environment, and then check in the fully built file into your source code, and optionally excluding the raw dependencies as part of your package. In general this is a bad idea for multiple reasons; it goes against some principles of version control, makes it harder for other devs to change the build system, and could have legal implications depending on the license of the third party library. However, for a scenario like this one, I think checking in a single pre-built JS file into your source control could outweigh requiring every dev who wants to build your app to install an entire separate build tool like Cairo.

Off on a tangent; exploring using CDNJS as a dependency

When I initially ran into this issue, one silly thought I had that I wanted to explore to see if it would even be possible, was to pull the prebuilt fabric.min.js file from a URL, ideally from CDNJS. This is not something that should ever be used in a production setting, but it was a fun idea to explore and see if it could easily be scripted with Node (it was). I was able to very quickly script together a file to download the Javascript file directly from CDNJS and place in the spot within my project. I then called that script as my “preinstall” script. I took a little time today to clean that script up and make it into a generic file downloader that can be called via the CLI and optionally can check the downloaded file’s hash, to make sure it matches what is expected (e.i. that the code within the file has not been changed). I have uploaded it as a Github gist here.

Leave a Reply

Your email address will not be published.