Parcel 11 ๐ฆ Sass & Less โ Preprocessor integration
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
| Extension | Package | Install |
|---|---|---|
.scss, .sass | sass (Dart Sass) | npm install --save-dev sass |
.less | less | npm install --save-dev less |
.styl | stylus | npm install --save-dev stylus |
The import rule
| Method | Reliability |
|---|---|
JavaScript import './styles.scss' | Reliable |
HTML <link href="styles.scss"> | Unreliable |
CSS @import 'styles.scss' | Unreliable |
The path rules
| Rule | Correct | Wrong |
|---|---|---|
| Relative path | @import './variables'; | @import '/variables'; |
| Partial file | _variables.scss | variables.scss |
| Image path | url('./icon.svg') | url(/icon.svg) |
The deployment flag
| Scenario | Flag |
|---|---|
| Domain root | None (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
| Pitfall | Why It Happens | Fix |
|---|---|---|
Cannot find module 'sass' | Auto-install disabled in v2.12+ | npm install --save-dev sass |
| SCSS file not compiled | Referenced from HTML, not JS | Import from JavaScript |
@import fails | Absolute path used | Use a relative path |
| Partial file emitted separately | Filename missing underscore | Rename to _variables.scss |
| CSS 404 after subdirectory deploy | Asset paths start with / | --public-url ./ |
node-sass conflict | Deprecated package installed | Replace 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
| Item | Value |
|---|---|
| Sass package | sass (Dart Sass) |
| Less package | less |
| Sass extension | .scss, .sass |
| Less extension | .less |
| Import trigger | JavaScript import |
| Auto-install | Disabled in v2.12+ |
| Path rule | Relative 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
sassorlesspackage must be installed as a dev dependency. In Parcel v2.12 and later, the build fails withCannot 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
@importcan be unreliable. Theimport './styles.scss'statement from JavaScript is the mechanism that Parcel’s dependency graph follows most consistently . - The
@importpaths 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-sasspackage is deprecated. Parcel v2 and later use Dart Sass, which is thesasspackage. A project that still hasnode-sassshould 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.
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!