mrkeyoor.com_
Sun 20 Sept 07:01 UTC
npmWeb Frontendupdated 20 Sept 2026

sass review

The npm `sass` package is Dart Sass compiled to JavaScript, with a `sass` command and a modern host API for turning SCSS or indented Sass into CSS. The language supplies modules, variables, mixins, functions, loops, maps, selectors, and compile-time color or unit calculations. Build tools call `compile()` or `compileString()` and can supply importers, custom functions, loggers, load paths, source-map settings, and deprecation policy. Version 1.103.1 has no user-visible change. Version 1.103.0 immediately before it changed CSS Color conversion so analogous missing channels remain `none` instead of becoming zero, which the release notes mark as a potentially breaking compatibility fix.

Verdict

Sass 1.103.1 installed in 3.8 seconds with 12 packages, 9 MB on disk, and 0 audit findings, while our complete browser import reached 684.7 KB gzipped. Keep it in the build pipeline for real Sass sources; new CSS and performance-sensitive compilers should first test native CSS and `sass-embedded`.

We installed it

Lab card: what happened when we installed sassScreenshot of sass documentation
Install✓ · 3.8s12 packages on disk · 9 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser684.7 KBgzipped (3246.2 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does sass install cleanly?

Yes. In a fresh container with an empty cache, npm install sass finished in 4 seconds, leaving 12 packages and 9 MB on disk. npm audit reported no known vulnerabilities.

How much does sass add to a browser bundle?

684.7 KB gzipped (3246.2 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does sass work with both ESM and CommonJS?

Yes. Both import 'sass' and require('sass') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does sass include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

sass or sass-embedded: which should you use?

sass-embedded: Choose it for Sass syntax and the modern host API backed by the native Dart compiler process. Sass 1.103.1 installed in 3.8 seconds with 12 packages, 9 MB on disk, and 0 audit findings, while our complete browser import reached 684.7 KB gzipped.

When should you not use sass?

A new stylesheet only needs browser-supported nesting, custom properties, layers, container queries, and current CSS color functions. Start with native CSS before adding another language.

API stability4/5The modern compile functions, result objects, importer protocol, custom Sass values, module system, and command-line interface are established across current 1.x releases. Compatibility work is still active: the legacy JavaScript API and language `@import` path are deprecated for 2.0, while version 1.103.0 shipped a potentially breaking CSS Color correction in a minor release. Sass's policy permits such changes when old behavior conflicts with valid CSS evolution.
Docs5/5The Sass site documents SCSS and indented syntax, every built-in module, `@use` and `@forward`, the CLI, modern JavaScript functions, importers, custom values, loggers, source maps, browser execution, deprecation IDs, and migration from `@import`. Compiler warnings link to focused explanations. The material is extensive because it covers a language and several host environments, yet exact option and value behavior is usually available without reading source.
Maintenance5/5GitHub reported an unarchived repository pushed on August 25, 2026, with 4,216 stars and 71 open issues and pull requests. Releases 1.103.0 and 1.103.1 shipped on August 20; the former changed missing-channel conversion for CSS Color compatibility and the latter had no visible behavior change. Work tracks Sass semantics, newly standardized CSS, Node support, packaging, the JavaScript build, and the native embedded protocol.
Ecosystem5/5npm counted 32,416,228 downloads in the latest completed week. Major bundlers detect the `sass` package for SCSS, design systems publish module-based theme surfaces, and editor tooling understands the language. `sass-embedded` shares the modern API for teams that outgrow the JavaScript compiler's speed, while the official migrator covers much of the move from `@import`. The ecosystem is large, though that also keeps old global-style examples circulating.

Use it if

  • The repository already owns `.scss` or indented `.sass` sources and needs the reference implementation of the current language.
  • A component library exposes Sass variables, mixins, functions, or module configuration as its supported theming contract.
  • Stylesheets generate selectors or calculated declarations from maps and loops that native CSS cannot express at authoring time.
  • A build integration needs a custom importer, typed Sass values, or compiler deprecation controls through the modern JavaScript API.
Skip it if

Setup reality

We installed sass 1.103.1 in a fresh Node 22 Bookworm sandbox in 3.8 seconds. The install left 12 packages and 9 MB on disk, and npm audit reported 0 known vulnerabilities. Sass declares 3 direct dependencies and 0 peers, with 5,916 KB unpacked and an MIT license. It is a CommonJS package behind an exports map, includes TypeScript declarations, and worked through both require() and ESM import in our checks.

Install it as a development dependency and call the modern compile, compileString, compileAsync, or compileStringAsync functions. The older render and renderSync interface is deprecated for removal in 2.0. The project README says compileAsync() is substantially slower than compile() in this JavaScript implementation. Use an asynchronous call when an importer or custom function genuinely waits for outside work, rather than by habit.

Sass modules load with @use and re-export with @forward. A @use belongs before ordinary style rules, runs a module once, and keeps members under a namespace. A with (...) clause can set only !default variables and must appear on the module's first load. The official migrator can rewrite old @import syntax, but it cannot choose the intended public boundary for globals that leaked between partials. Compare generated CSS after migration.

Our complete browser import measured 3,246.2 KB minified and 684.7 KB gzipped. Browser code can call compileString() with custom importers, has no filesystem compile(), and needs name preservation in esbuild. In Node, test sass-embedded when repeated compilation is slow. The JS result returns CSS and source-map data; your integration writes the files and map reference. Use deprecation IDs to silence known migration noise temporarily, then make the same ID fatal once fixed.

Patterns

Compile one file or a directory compile-from-cli

npx sass src/app.scss dist/app.css
npx sass src/:dist/ --style=compressed
npx sass --watch src/:dist/ --source-map

Directory mode skips Sass partials whose filename starts with `_`; watch mode recompiles entry points when loaded dependencies change.

Compile a file with the modern API compile-file-in-node

import * as sass from 'sass';

const result = sass.compile('src/app.scss', {
  loadPaths: ['src/styles'],
  style: 'compressed',
  sourceMap: true,
});
console.log(result.css, result.loadedUrls);

The returned source map is a data object. Sass 1.103.1 does not write the map or its CSS reference for your integration.

Compile generated SCSS compile-scss-string

const result = sass.compileString(
  '$gap: 12px; .grid { gap: $gap; }',
  { url: new URL('file:///workspace/generated.scss') },
);
console.log(result.css);

A canonical source URL makes relative loads and compiler diagnostics resolve from a known location.

Load Sass members under a namespace use-namespaced-module

// _tokens.scss
$brand: #0869b8;

// app.scss
@use 'tokens';
@use 'sass:color';

.button {
  background: tokens.$brand;
  border-color: color.scale(tokens.$brand, $lightness: -20%);
}

`@use` loads a module once and keeps members namespaced; place it before ordinary selectors in the stylesheet.

Set a theme's declared defaults configure-module-defaults

// _theme.scss
$radius: 4px !default;
$accent: navy !default;

// app.scss
@use 'theme' with (
  $radius: 8px,
  $accent: maroon,
);

Only variables marked `!default` can be configured, and the configuring `@use` must be the first load of that module.

Publish selected module members forward-module-api

// components/_index.scss
@forward 'button';
@forward 'card' hide $internal-gap;
@forward 'grid' as grid-*;

// app.scss
@use 'components';

`@forward` exposes members to downstream users; `hide`, `show`, and prefixes define the package's public Sass names.

Resolve a package through its exports load-node-package

const result = sass.compile('src/app.scss', {
  importers: [new sass.NodePackageImporter()],
});

// app.scss
// @use 'pkg:some-design-system';

NodePackageImporter reads package export metadata instead of depending on relative paths inside `node_modules`.

Serve an in-memory Sass module provide-virtual-importer

const importer = {
  canonicalize(url) {
    return url === 'theme:tokens' ? new URL('theme:tokens') : null;
  },
  load(url) {
    return url.href === 'theme:tokens'
      ? { contents: '$accent: #0869b8;', syntax: 'scss' }
      : null;
  },
};

sass.compileString("@use 'theme:tokens';", { importers: [importer] });

Return a stable canonical URL so Sass identifies repeated requests as 1 module; `load()` must state the source syntax.

Return a typed Sass value define-custom-function

const result = sass.compileString('.build::after { content: build-id(); }', {
  functions: {
    'build-id()': () => new sass.SassString(process.env.BUILD_ID ?? 'local'),
  },
});

Custom functions exchange Sass value objects, not plain JavaScript strings; keep environment-dependent output out of reproducible builds unless intended.

Route warnings through a logger capture-compiler-warnings

const warnings = [];
const result = sass.compile('src/app.scss', {
  logger: {
    warn(message, options) { warnings.push({ message, deprecation: options.deprecation }); },
    debug() {},
  },
});

A custom logger replaces normal warning output; preserve deprecation information so the build does not hide migration work.

Silence then forbid a deprecation enforce-deprecation-policy

npx sass --silence-deprecation=import,global-builtin src/:dist/
npx sass --fatal-deprecation=import src/:dist/

Silencing buys migration time. Once old imports are removed, making that ID fatal prevents new uses from entering the codebase.

Rewrite modules and slash division run-official-migrator

npx sass-migrator module --migrate-deps src/app.scss
npx sass-migrator division --migrate-deps 'src/**/*.scss'

Run the migrator on a reviewable branch and compare the compiled CSS; automatic edits cannot infer every intended global or module boundary.

Alternatives

PackageRegistryPick it when
sass-embeddednpmChoose it for Sass syntax and the modern host API backed by the native Dart compiler process.
postcssnpmChoose it when selected CSS transformations should come from an explicit plugin pipeline rather than Sass syntax.
lessnpmChoose it when an existing Less theme or codebase already fixes the preprocessor language.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.