SharePoint / SharePoint/sp-dev-docs

[SPFx 1.22β†’1.23] Sass import resolution changed β€” `~` breaks in `meta.load-css()`, bare specifiers and `importIncludePaths` no longer work (undocumented)

Open
#10,854 2 comments 1 reaction 1 assignee View on GitHub

@Ashlesha-MSFT is already working on this.

Since May 21, 2026.

area:docs area:spfx area:tooling Needs: Triage :mag: status:fixed-next-drop
Dominant language
PowerShell
Stars
1.4k
Forks
1.1k
Avg merge
4d 12h
Merged PRs (30d)
12

Description

Target SharePoint environment

SharePoint Online

SharePoint development model

πŸ’₯ SharePoint Framework

Developer environment

macOS, windows, linux

Additional environment details

I reproduced this on two SPFx projects β€” one scaffolded and pinned to the SPFx 1.22 toolchain, one to SPFx 1.23 β€” and verified the versions from each project's node_modules:

SPFx 1.22 project SPFx 1.23 project
SPFx (@microsoft/spfx-web-build-rig) 1.22.2 1.23.0
@rushstack/heft-sass-plugin 0.15.24 1.3.8
@rushstack/heft 1.1.2 1.2.17
sass-embedded 1.77.8 1.85.1
Node.js 22.22.0 22.22.0

@microsoft/spfx-web-build-rig@1.22.2 pins @rushstack/heft-sass-plugin@0.15.24; @1.23.0 pins @1.3.8 β€” so this is the version pair every SPFx project gets on each release. The reference dependency I imported in the repro is @n8d/htwoo-core@2.7.1.

Describe the bug / error

Between the @rushstack/heft-sass-plugin version SPFx 1.22 ships (0.15.24) and the one SPFx 1.23 ships (1.3.8), the plugin's Sass import-resolution model was rewritten β€” from Sass loadPaths + a tilde (~) importer to the pkg: scheme plus a tilde-to-pkg: text rewrite. pkg: is the modern Sass mechanism, so the direction is fine, but the change isn't documented anywhere I could find: not in the plugin CHANGELOG, not in the SPFx 1.23 release notes, not in Configure Sass processing during builds, and not in Migrate from the Gulp Toolchain to Heft Toolchain β€” even though that migration guide's whole job is to spell out what changes on upgrade.

Three things that worked in SPFx 1.22 fail in SPFx 1.23:

Import form SPFx 1.22 (0.15.24) SPFx 1.23 (1.3.8)
D bare specifier β€” @use '@scope/pkg/...' works Can't find stylesheet to import
E ~ inside @include meta.load-css('~@scope/pkg/...') works Unexpected tilde in URL
G config/sass.json with importIncludePaths valid option build fails config validation

E is the one that really catches you out. ~ still works in @use, @import and @forward, so it's natural to assume ~ is just supported β€” until you use it in meta.load-css() and the build throws.

Why E happens

In 1.3.8, ~ is no longer a Sass importer. It's rewritten to pkg: by a regular expression that runs over the source before compilation (SassProcessor.js, line 56):

const importTildeRegex = /^(\s*@(?:import|use|forward)\s*)('~(?:[^']+)'|"~(?:[^"]+)")/gm;

That regex only matches @import, @use and @forward. @include meta.load-css('~…') doesn't start with any of those, so the ~ is never rewritten β€” and when it reaches the importer it is rejected outright (SassProcessor.js, line 356):

throw new Error(`Unexpected tilde in URL: ${url} in context: ${context.containingUrl?.href}`);

In 0.15.24, ~ was a genuine Sass importer, and Sass consults importers for meta.load-css() too β€” so it worked everywhere. Bare specifiers (D) worked in 0.15.24 because the plugin passed loadPaths: [<project>/node_modules, <project>/src]; 1.3.8 passes no loadPaths at all. importIncludePaths (G) was a documented config/sass.json option in 0.15.24's schema; 1.3.8 removed it, and the schema is additionalProperties: false, so setting it now fails validation.

Steps to reproduce

  1. Create (or upgrade to) an SPFx 1.23 project and install any package that ships SCSS partials β€” e.g. npm install @n8d/htwoo-core.
  2. Add a .global.scss file under src/webparts/<wp>/components/ containing:
    @use 'sass:meta';
    .x { @include meta.load-css('~@n8d/htwoo-core/lib/components/all'); }
    
  3. Run heft build. The build fails:
    [build:sass] Error: src/webparts/.../X.global.scss:2:11 - Error: Unexpected tilde in URL:
                 ~@n8d/htwoo-core/lib/components/all in context: heft:/.../X.global.scss
    -------------------- Failed --------------------
    
  4. Add another file with a bare specifier β€” @use '@n8d/htwoo-core/lib/components/all'; β€” and heft build fails with Can't find stylesheet to import.
  5. Add "importIncludePaths": ["node_modules", "src"] to config/sass.json and heft build fails before compiling anything:
    [build:sass] Error: Resolved configuration object does not match schema: ... JSON validation failed
    [build:sass]        must NOT have additional properties: importIncludePaths
    
  6. Build the same files on an SPFx 1.22 project β€” all three succeed.
Full cross-version reproduction

I compiled six identical fixture files (Matrix{A..F}.global.scss) with each project's own heft build. Import target: @n8d/htwoo-core/lib/components/all.

Fixture Statement SPFx 1.22 SPFx 1.23
MatrixA @import '~…/all' PASS PASS
MatrixB @use '~…/all' PASS PASS
MatrixC @use 'pkg:…/all' FAIL PASS (new in 1.23)
MatrixD @use '…/all' (bare specifier) PASS FAIL
MatrixE @include meta.load-css('~…/all') PASS FAIL
MatrixF @include meta.load-css('pkg:…/all') FAIL PASS (new in 1.23)

SPFx 1.23 β€” heft build (plugin 1.3.8):

[build:sass] Compiling 7 files...
[build:sass] Error: src/webparts/.../MatrixD.global.scss:1:0 - Can't find stylesheet to import.
[build:sass] @use '@n8d/htwoo-core/lib/components/all';
[build:sass] Error: src/webparts/.../MatrixE.global.scss:2:11 - Error: Unexpected tilde in URL:
             ~@n8d/htwoo-core/lib/components/all in context: heft:/.../MatrixE.global.scss
-------------------- Failed (4.352s) --------------------

Only MatrixD and MatrixE errored. A, B, C, F compiled fine.

SPFx 1.22 β€” heft build (plugin 0.15.24):

Error occurred parsing and generating typings for file ".../MatrixC.global.scss": ... Can't find stylesheet to import.
Error occurred parsing and generating typings for file ".../MatrixF.global.scss": ... Can't find stylesheet to import.
[build:sass] Generated sass typings

Only MatrixC and MatrixF errored (0.15.24 has no pkg: importer). MatrixA, B, D and E all compiled β€” confirming D and E are genuine regressions, not pre-existing failures.

Two more things the same builds surfaced

The rig still advertises the removed option. @microsoft/spfx-web-build-rig@1.23.0 ships this in node_modules/@microsoft/spfx-web-build-rig/profiles/default/config/sass.json (the file your project's config/sass.json extends β€” not your project file itself):

/**
 * A list of paths used when resolving Sass imports.  The paths should be relative to the project root.
 *
 * Default value: ["node_modules", "src"]
 */
// "importIncludePaths": ["node_modules", "src"],

Un-comment that and the build fails the schema validation above β€” the option it documents no longer exists.

A 1.23-scaffolded project will not build on 1.22. The webpart SCSS the 1.23 generator emits starts with @import 'pkg:@fluentui/react/dist/sass/References.scss'; (or pkg:@microsoft/sp-office-ui-fabric-core/... for the no-framework template). That pkg: line fails on SPFx 1.22, since 0.15.24 has no pkg: importer. (See also #10833 on the scaffold's deprecated @import.)

Expected behavior

The behavior change itself is reasonable β€” pkg: is the right modern mechanism. The problem is that it's undocumented, and ~ is left half-working (fine in @use/@import/@forward, broken in @include meta.load-css()), which is exactly the kind of thing that turns a 1.22β†’1.23 upgrade into mystery build failures.

I'd expect the docs to cover it:

  • The SPFx 1.23 release notes and the Configure Sass processing during builds page should state that the resolution model changed β€” loadPaths/importIncludePaths are gone, pkg: is the supported scheme, and ~ is only auto-rewritten in @use/@import/@forward.
  • The Migrate from the Gulp Toolchain to Heft Toolchain guide should include a Sass step: replace @include meta.load-css('~…') and bare @use '@scope/pkg/…' with the pkg: form, and remove importIncludePaths from config/sass.json.
  • The stale importIncludePaths comment should be removed from spfx-web-build-rig's sass.json.
Workaround for anyone hitting this today

Use pkg: for every npm-package import β€” it's the one form that works in @use, @import, @forward and meta.load-css():

  • @include meta.load-css('~@scope/pkg/...') β†’ @include meta.load-css('pkg:@scope/pkg/...')
  • bare @use '@scope/pkg/...' β†’ @use 'pkg:@scope/pkg/...'
  • delete importIncludePaths from config/sass.json
References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up β€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.