engineering placeholder
Tech

Preventing Node-Sass (Or Any Specific Dependency) From Installing

By OpenWeb

If you’re using sass in your frontend projects (which we definitely recommend!), you’ve probably run into node-sass in one way or another. Node-sass is a C++ add on for NodeJS that binds libsass, the C language compiler for the sass language.

Both node-sass and libsass have been deprecated in favor of Dart Sass (sass) since October 2020. While they were built to be fast, they have the disadvantage of long build times, and breaking unexpectedly when using a new NodeJS version—or missing any required tooling for building the dependencies.

In the end of 2021 (and after many such issues over the years), the OpenWeb team ran into a problem preventing us from building most frontend projects due to a platform change that removed one of the dependencies used by the node-sass build process. In most cases, we were migrated to sass, but multiple dependencies were still referencing node-sass —meaning that it was being installed and compiled, but not used.

We Were Faced With Two Choices

  1. Update all nested dependencies to use sass and update all projects to use the new versions of said dependencies, or
  2. Find a way to prevent node-sass from being installed downstream even if referenced by a dependency.

Normally, if you want to prevent something from being used, you can use null-loader (on Webpack 4), or disable the dependency using an alias (on Webpack 5), but this will not prevent the dependency from being installed and built—only from being included in your built asset.

Since we use yarn 1 (npm and yarn 2 instructions included below) as our package manager, a good place to start looking was yarns resolutions section, which allows resolving multiple versions of a dependency to one version.

The issue here was that resolutions allows us to specify a specific version, but not disable the dependency entirely as in Webpack 5. The yarn documentation also specifies that you can use a local file in the dependency section (file:…) but does not specify the same for resolutions.

This meant that going by the documentation, you could redirect a downstream dependency to a local file, but not anything used by upstream dependencies.

Nonetheless, we tried specifying a local stub dependency for node-sass to try to prevent it from installing the actual dependency, and it worked with resolutions as well! Now we could easily redirect node-sass to a stub, prevent it from being installed without updating any dependencies, and solve the issue rather quickly.

Our Step-By-Step Solution

  1. Install sass using yarn add -D sass if not installed.
  2. Create a folder named dependency-stub in the project root, housing a single file named index.js containing the line module.exports = {}; (which is the stub we will redirect to using resolutions).
  • yarn 2 – add a package.json file to the directory containing { “name: “node-sass”, “version”: “0.0.0” }
  • npm – see note under step 3.
  1. In package.json add “node-sass”: “file:dependency-stub” to the resolutions (or overrides if using NPM) section.
  • npm – use the overrides section rather than resolutions, and since npm file urls are relative to the current dependency, you can either use an absolute path to dependency-stub (possibly placing it in your home directory), a URL for a stub module, or a GitHub URL for a stub module.
  1. In tsconfig.json add “dependency-stub” to the include array (to prevent ESLint from throwing errors regarding the file not being in the project).
  • npm – assuming dependency-stub isn’t in your project directory, this is not needed.

(Step 3 of the process can be reused for any arbitrary C++ NodeJS add on, assuming it isn’t used).

And that was it! node-sass stopped installing in all projects and the issue was resolved (save for a few projects with out of date sass-loaders which needed manual updating). Hopefully, this will help anyone else needing to quickly remove node-sass.

Subscribe to our blog