| | |

Parcel 11 ๐Ÿ“ฆ Sass & Less โ€” Preprocessor integration

โฑ๏ธ Estimated read: 8 min | |

Parcel includes first-class support for CSS preprocessors, but the support is not fully automatic. The official documentation states that a <link rel="stylesheet"> element can reference a CSS file “or any other file that compiles to CSS such as SASS, Less, or Stylus” . The preprocessor itself is not bundled with Parcel; it is installed as a dependency when Parcel detects the corresponding file type. The critical detail that the documentation does not emphasize is that Parcel v2.12 and later disabled the automatic installation behavior, so the dependency must be present in the project before the build succeeds .

This chapter covers the preprocessor integration: the dependency requirement for Sass and Less, the file extension that triggers the loader, the @import resolution rules that differ from plain CSS, and the --public-url flag that fixes the asset path when the build is deployed to a subdirectory.

Key point: Parcel compiles Sass and Less when it encounters a .scss/.sass or .less file that is imported from JavaScript or referenced from HTML. The preprocessor package (sass or less) must be installed as a dev dependency. In Parcel v2.12+, the build fails with Cannot find module 'sass' if the package is missing, because the auto-install behavior was disabled.


Why the preprocessor is a separate dependency

The zero-configuration claim problem. Parcel is marketed as a zero-configuration bundler, and for CSS, JavaScript, and HTML it delivers on that claim . The preprocessors are not part of the core. They are compiler packages that Parcel invokes through a transformer. The transformer is built in, but the compiler is not. The dependency is the boundary between the bundler and the language implementation.

The auto-install history problem. In earlier Parcel 2 versions, the bundler attempted to install the missing preprocessor automatically. The behavior was convenient but unpredictable, and it was disabled in v2.12 for security and control reasons . The current behavior is explicit: the dependency must be installed, and the error message names the missing package. The fix is npm install --save-dev sass or npm install --save-dev less .

The node-sass problem. The node-sass package is deprecated. Parcel v2 and later use Dart Sass, which is the sass package on npm. A project that still has node-sass in its dependencies should replace it with sass .


a. The Sass integration

Sass is installed as a dev dependency and referenced by the .scss or .sass extension. Parcel detects the extension and invokes the Sass compiler.

npm install --save-dev sass
// styles.scss
$primary: #3498db;

.button {
  background: $primary;
  padding: 8px 16px;
}
// app.js
import './styles.scss'

The import from JavaScript is the most reliable trigger. The documentation notes that referencing a preprocessor file directly from HTML with a <link> tag or a CSS @import can be unreliable; the JavaScript import is the mechanism that Parcel’s dependency graph follows most consistently .

The @import rules inside the Sass file are resolved relative to the importing file, not the project root. A path that starts with / is treated as an absolute path and fails. The correct form is a relative path: @import './reset'; or @import '../mixins/breakpoints'; .

A Sass partial (a file that is only meant to be imported, not compiled on its own) should start with an underscore, such as _variables.scss. Without the underscore, Parcel may treat the file as a separate entry point and emit it as its own CSS file .


b. The Less integration

Less follows the same pattern with a different package and extension.

npm install --save-dev less
// styles.less
@primary: #3498db;

.button {
  background: @primary;
  padding: 8px 16px;
}
// app.js
import './styles.less'

The .less extension is the trigger. The less package is the compiler. The @import resolution and the relative-path rule are the same as for Sass.


c. The --public-url flag

A Parcel build writes the CSS and JavaScript asset paths with a leading slash by default, such as /main.abc123.css. This is correct for a deployment at the domain root (https://example.com/). It is wrong for a deployment at a subdirectory (https://example.com/my-app/), because the browser requests the asset from the domain root and receives a 404 .

The fix is the --public-url flag:

parcel build index.html --public-url ./

The flag rewrites the asset paths to relative URLs, such as ./main.abc123.css, which resolve correctly regardless of the deployment subdirectory . The flag affects all assets, not only the CSS.


Complete Example Session

# ============================================
# PART 1: INSTALL THE PREPROCESSOR
# ============================================
npm install --save-dev sass
# or
npm install --save-dev less
// ============================================
// PART 2: THE SASS FILE
// ============================================
// styles.scss
$primary: #3498db;

.button {
  background: $primary;
  padding: 8px 16px;
}
// ============================================
// PART 3: THE JAVASCRIPT IMPORT
// ============================================
// app.js
import './styles.scss'
# ============================================
# PART 4: THE BUILD
# ============================================
parcel build index.html

# The SCSS is compiled to CSS.
# The output CSS is extracted and referenced from the HTML.
// ============================================
// PART 5: THE RELATIVE @IMPORT
// ============================================
// _variables.scss
$primary: #3498db;

// styles.scss
@import './variables';

.button {
  background: $primary;
}
// ============================================
// PART 6: THE WRONG PATH
// ============================================
// @import '/variables';
// Absolute path, fails.
# ============================================
# PART 7: THE SUBDIRECTORY DEPLOY
# ============================================
parcel build index.html --public-url ./

# The asset paths become relative.
# The build works at https://example.com/my-app/.
# ============================================
# PART 8: THE MISSING DEPENDENCY ERROR
# ============================================
# Cannot find module 'sass'
# Fix: npm install --save-dev sass
// ============================================
// PART 9: THE LESS EQUIVALENT
// ============================================
import './styles.less'
// Requires: npm install --save-dev less
# ============================================
# PART 10: THE DECISION
# ============================================
# Sass โ†’ install sass, import .scss
# Less โ†’ install less, import .less
# Subdirectory deploy โ†’ --public-url ./

The ten parts covered the preprocessor installation, the Sass file, the JavaScript import, the build, the relative @import, the wrong absolute path, the subdirectory deploy, the missing dependency error, the Less equivalent, and the decision.


Quick Reference

Preprocessor dependencies

ExtensionPackageInstall
.scss, .sasssass (Dart Sass)npm install --save-dev sass
.lesslessnpm install --save-dev less
.stylstylusnpm install --save-dev stylus

The import rule

MethodReliability
JavaScript import './styles.scss'Reliable
HTML <link href="styles.scss">Unreliable
CSS @import 'styles.scss'Unreliable

The path rules

RuleCorrectWrong
Relative path@import './variables';@import '/variables';
Partial file_variables.scssvariables.scss
Image pathurl('./icon.svg')url(/icon.svg)

The deployment flag

ScenarioFlag
Domain rootNone (default)
Subdirectory--public-url ./

Best Practices

โœ… Do This:

# Install the preprocessor explicitly
npm install --save-dev sass                                  # โœ…
// Import the preprocessor file from JavaScript
import './styles.scss'                                       # โœ…
// Use relative paths for @import
@import './variables';                                       # โœ…
# Use --public-url for subdirectory deployments
parcel build index.html --public-url ./                      # โœ…

โŒ Don’t Do This:

# Rely on automatic installation
# Parcel v2.12+ fails with "Cannot find module"                # โŒ
// Use an absolute path
@import '/variables';                                        # โŒ
# Use node-sass
npm install --save-dev node-sass                             # โŒ (deprecated)
# Deploy to a subdirectory without --public-url
parcel build index.html                                      # โŒ (404 on assets)

Common Pitfalls

PitfallWhy It HappensFix
Cannot find module 'sass'Auto-install disabled in v2.12+npm install --save-dev sass
SCSS file not compiledReferenced from HTML, not JSImport from JavaScript
@import failsAbsolute path usedUse a relative path
Partial file emitted separatelyFilename missing underscoreRename to _variables.scss
CSS 404 after subdirectory deployAsset paths start with /--public-url ./
node-sass conflictDeprecated package installedReplace with sass

Real-World Examples

1. Install Sass

npm install --save-dev sass

2. Install Less

npm install --save-dev less

3. Sass import from JS

import './styles.scss'

4. Less import from JS

import './styles.less'

5. Relative @import

@import './variables';

6. Partial file

// _variables.scss

7. The subdirectory deploy

parcel build index.html --public-url ./

8. The error

Cannot find module 'sass'

9. The fix

npm install --save-dev sass

10. The decision

Sass โ†’ sass + .scss; Less โ†’ less + .less

Visual

The preprocessor pipeline

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  styles.scss                                                 โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Parcel detects .scss                                        โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Invokes the sass compiler                                   โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  CSS output                                                  โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Extracted and referenced from HTML                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The dependency boundary

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Parcel core          โ†’  transformer (built in)              โ”‚
โ”‚  sass / less package  โ†’  compiler (must be installed)        โ”‚
โ”‚                                                              โ”‚
โ”‚  Without the compiler:                                       โ”‚
โ”‚    Cannot find module 'sass'                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The path resolution

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  src/css/main.scss                                           โ”‚
โ”‚    @import './variables';  โ† src/css/variables.scss         โ”‚
โ”‚    @import '../mixins';    โ† src/mixins.scss                โ”‚
โ”‚                                                              โ”‚
โ”‚  The path is relative to the importing file,                 โ”‚
โ”‚  not the project root.                                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The subdirectory deploy

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Default:                                                    โ”‚
โ”‚    <link href="/main.abc123.css">                            โ”‚
โ”‚    โ†’ 404 at https://example.com/my-app/                      โ”‚
โ”‚                                                              โ”‚
โ”‚  --public-url ./:                                            โ”‚
โ”‚    <link href="./main.abc123.css">                           โ”‚
โ”‚    โ†’ works at any subdirectory                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Sass packagesass (Dart Sass)
Less packageless
Sass extension.scss, .sass
Less extension.less
Import triggerJavaScript import
Auto-installDisabled in v2.12+
Path ruleRelative to the importing file
Partial file_ prefix
Subdirectory deploy--public-url ./

Key takeaways:

  • Parcel supports Sass and Less through built-in transformers, but the compiler is a separate dependency. The sass or less package must be installed as a dev dependency. In Parcel v2.12 and later, the build fails with Cannot find module 'sass' if the package is missing, because the auto-install behavior was disabled .
  • The JavaScript import is the reliable trigger. Referencing a preprocessor file directly from HTML or a CSS @import can be unreliable. The import './styles.scss' statement from JavaScript is the mechanism that Parcel’s dependency graph follows most consistently .
  • The @import paths are relative to the importing file. An absolute path that starts with / fails. A partial file that is only meant to be imported should start with an underscore to prevent Parcel from treating it as a separate entry point .
  • The node-sass package is deprecated. Parcel v2 and later use Dart Sass, which is the sass package. A project that still has node-sass should replace it .
  • The --public-url ./ flag fixes the subdirectory deployment. By default, Parcel writes asset paths with a leading slash, which resolves to the domain root. The flag rewrites them to relative paths, which work at any subdirectory .

Remember: Sass and Less integration in Parcel is a dependency and an extension. Install sass or less as a dev dependency, import the .scss or .less file from JavaScript, and use relative paths for the @import rules. The --public-url ./ flag is the fix for a subdirectory deployment. And the auto-install behavior is gone; the dependency must be present before the build starts.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!