blueprint
blueprint copied to clipboard
Unable to compile BluePrint 4 SCSS with webpack sass-loader
Environment
- Package version(s): @blueprintjs/core: 4.17.8, sass: 1.60.0, sass-loader: 13.2.2, webpack: 5.73.0, node 16.16.0
- Operating System: Ubuntu 22.04
- Browser name and version: Chrome: 111.0.5563.110
Steps to reproduce
- Install @blueprintjs/core using npm:
npm install @blueprintjs/[email protected] - Create an index.scss file that imports the blueprint scss file:
@import '@blueprintjs/core/src/blueprint';
- Add webpack configuration using sass-loader e.g.
module: {
rules: [
{
test: /\.(css|scss|sass)/,
use: [
{
loader: 'sass-loader',
},
],
}
},
Actual behavior
ERROR in ./style/index.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./style/index.scss)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: (path: (fill: hsl(213.75, 10.8108108108%, 50%))) isn't a valid CSS value.
╷
39 │ background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-icon-color)));
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unknown function treated as plain CSS
╵
node_modules/@blueprintjs/core/src/components/breadcrumbs/_breadcrumbs.scss 39:54 @import
node_modules/@blueprintjs/core/src/components/_index.scss 5:9 @import
node_modules/@blueprintjs/core/src/blueprint.scss 18:9 @import
style/index.scss 5:9 root stylesheet
SassError: SassError: (path: (fill: hsl(213.75, 10.8108108108%, 50%))) isn't a valid CSS value.
╷
39 │ background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-icon-color)));
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unknown function treated as plain CSS
╵
node_modules/@blueprintjs/core/src/components/breadcrumbs/_breadcrumbs.scss 39:54 @import
node_modules/@blueprintjs/core/src/components/_index.scss 5:9 @import
node_modules/@blueprintjs/core/src/blueprint.scss 18:9 @import
style/index.scss 5:9 root stylesheet
at Object.loader (/home/adam/Documents/source/frontend/node_modules/sass-loader/dist/index.js:56:14)
@ ./style/index.scss 8:6-183 22:17-24 26:7-21 58:25-39 59:36-47 59:50-64 63:6-73:7 64:54-65 64:68-82 70:42-53 70:56-70 72:21-28 83:0-153 83:0-153 84:22-29 84:33-47 84:50-64 61:4-74:5
@ ./src/index.ts 4:0-29
Expected behavior
I would expect all of the blueprint internal SCSS files (e.g. the breadcrumb component scss file) to compile out of the box.
I have looked at all the similar issues raised but I am unable to follow them or to get this SCSS compiling. Are there any other steps that need to be done after installing this version of Blueprint? Previously working on Blueprint v3 had no compilation issues.
I tried to follow the webpack suggestion as well https://github.com/palantir/blueprint/issues/5334#issuecomment-1444223876 however this doesn't work and I would preferably not want to store a local copy of blueprint's icons.
I tried to follow the webpack suggestion as well https://github.com/palantir/blueprint/issues/5334#issuecomment-1444223876 however this doesn't work
Sorry for the trouble here, could you share some of the issues you encountered with that approach? I'm open to making bugfixes which make it possible to continue compiling Blueprint's Sass code when it's consumed as an NPM package.
I don't have a great alternative solution right now that doesn't involve advanced Blueprint consumers storing a copy of the icons SVG folder. We inline icons in a few places across the code base and there's a bit of work to untangle that which I don't have the bandwidth to do right now. So the inlining has to stay, at least for now.
Note that the svg-icon() function is only used for a few specific icons, so you really only need to ensure these files exist (I don't have plans to add any more usage of svg-icon() to the code base):
- 16px/chevron-right.svg
- 16px/more.svg
- 16px/chevron-right.svg
- 16px/more.svg
- 16px/small-tick.svg
- 16px/small-minus.svg
Thanks @adidahiya I will try storing those icons locally and see if that works.
- I was originally using React 16 and upgraded to React 18 via NPM.
- I also then upgraded blueprint from v3 to v4 with NPM and upgraded to use the latest version of the core package: @blueprintjs/core 4.17.8
- I remembered that there was a migration from node-sass to the dart-based sass. I upgraded the webpack sass-loader package to the latest version, uninstalled node-sass and then installed sass.
Once this was done, I ran npm start to run the dev server version of webpack where I then get the error above. If I run npm run build to create a production build, I also get the same error.
@ahaganDEV so it sounds like you did not try using the new sassSvgInlinerFactory as suggested in https://github.com/palantir/blueprint/issues/5334#issuecomment-1444223876 and documented here in the docs, can you please try that? It requires adding a dependency on the @blueprintjs/node-build-scripts NPM package and using some of the utilities available there.
@adidahiya I didn't see that in the docs! I'll give that a go. I am currently using node 16 am I right that to use the node-build-scripts library I need to use node 18?
am I right that to use the node-build-scripts library I need to use node 18?
@ahaganDEV Yes, this is enforced by the "engines" constraint defined for the @blueprintjs/node-build-scripts package.
@adidahiya I am trying to import the node-build scripts into my webpack.config.js file like in the example. However, I get the error:
[webpack-cli] Failed to load '/my-project/webpack.config.js' config [webpack-cli] Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /my-project/node_modules/@blueprintjs/node-build-scripts/package.json
My project is using node 18.13.0, the compilerOptions in tsconfig.json are set totarget: es6, module: commonjs and we use babel.
I tried importing using require('@blueprintjs/node-build-scripts/import') as the package.json for @blueprintjs/node-build-scripts' has that in its exports section but that doesn't work either.
Do you know how I can get this importing correctly in the project. Thanks.
Here are some snippets of the webpack config:
webpack.config.js
// node build scripts import
const { sassSvgInlinerFactory, sassNodeModulesLoadPaths} = require('@blueprintjs/node-build-scripts');
const sass = require('sass');
// sass function
const sassFunctions = {
/**
* Sass function to inline a UI icon svg and change its path color.
*
* Usage:
* svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
*/
'svg-icon($path, $selectors: null)': sassSvgInlinerFactory('style/blueprint/local-icons', {
optimize: true,
encodingFormat: 'uri',
}),
};
// sass-loader config
{
loader: 'sass-loader',
options: {
sassOptions: {
loadPaths: sassNodeModulesLoadPaths,
functions: sassFunctions,
},
},
},
@adidahiya I got the above to start running by turning my webpack config into es6 format.
However, I get an error when running webpack with the sassSvgInliner is this something that has been seen before or could something be configured wrong?
@blueprintjs/node-build-scripts/src/sass/sassSvgInliner.mjs:42
const resolvedPath = resolve(base, path.text);
^
TypeError: Cannot read properties of undefined (reading 'text')
at Object.<anonymous> (file:///home/source/node_modules/@blueprintjs/node-build-scripts/src/sass/sassSvgInliner.mjs:42:49)
When I add console logs to sassSvgInliner function, I get this output for the args paramter:
sass.types.String { dartValue: "16px/chevron-right.svg" }
The sass in _breadcrumbs.scss is:
background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-icon-color)));
and later on in the file
background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-dark-icon-color)));
Hello @ahaganDEV I am having the exact same problem that you described, have you found a solution to this yet?@adidahiya Do you have any idea how to resolve this?
Hi @adidahiya, I am also facing same issue. Can you please help us.
Just wanted to add my +1 to the issue @ahaganDEV brought up above. I feel like I've got everything set up right, and yet, this custom function doesn't compile.
My feeling is like, I don't know what the heck is going on, but I'm pretty sure the fault is with sass-loader. I made an issue there asking for help.
https://github.com/webpack-contrib/sass-loader/issues/1137
There is an answer https://github.com/webpack-contrib/sass-loader/issues/1137#issuecomment-1537240206.
Shortly - sass-loader (and other sass loader/transformers for other bundlers, like vite/rollup plugins/esbuild plugins/etc) are on the old API, i.e. use render/renderSync, instead compileString/compileStringAsync due to lack abilities to implement resolving (due to lack ability to get current file where we found @import/@use), that is why it is not working, sass team recentry merge RFC to support it, so I hope we will fix it soon, maybe blueprint should provide different versions of functions for the old and the new API
feel free to feedback
@alexander-akait thanks for the clarification, I didn't realize that sass-loader only supports the legacy Sass render APIs.
maybe blueprint should provide different versions of functions for the old and the new API
There is an SVG inliner function available for the legacy Sass API. Blueprint was using a third-party library for this before we migrated to the newer API. It's called @vgrid/sass-inline-svg, but it's not compatible with Node 18+. You can see how it was used here: https://github.com/palantir/blueprint/blob/f88e8184940d1de1ae4251a1d0c082bd08c7e328/packages/core/scripts/sass-custom-functions.js. Maybe this same setup could still be used with Blueprint v4 and sass-loader? You would need to downgrade to Node 16.x, though.
Thanks all!
For anyone else who needs a workaround literally asap, I made a quick gist here: https://gist.github.com/eastside/adcdf0d189c7470be241a851c5add350
Instead of the normal factory, you'd use legacySassSvgInlinerFactory. It works almost the same as the original factory, (except optimize doesn't work), at least through the current version of Blueprint.js.
You'd just make a new file, maybe call it sassSvgInliner.mjs, and then of course import it:
import { legacySassSvgInlinerFactory } from './path-to/sassSvgInliner.mjs';
...<snip>...
{
loader: "sass-loader",
options: {
implementation: "sass",
sassOptions: {
"functions": {
// /**
// * Sass function to inline a UI icon svg and change its path color.
// *
// * Usage:
// * svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
// */
"svg-icon($path, $selectors: null)": legacySassSvgInlinerFactory("blueprint-icons/icons"),
}
}
}
}
Hi
We tried your approach, but started getting new error.

Please help.
@eastside Thank you for the gist, I managed to make it work with Vite 4. There were 2 errors in your code which required adjustments:
- SVG wasn't properly encoded to base64. Creating new buffer was required instead of encoding string directly
- Closing
"was missing at the end ofurl("...)in base64 case
function encode(content, opts) {
let buff = new Buffer(content)
if (opts.encodingFormat === "uri") {
return new sass.SassString(
`url("${svgToDataUri(buff.toString("UTF-8"))}")`,
{quotes: false}
)
}
if (opts.encodingFormat === "base64") {
return new sass.SassString(
`url("data:image/svg+xml;base64,${buff.toString("base64")}")`,
{quotes: false}
)
}
throw new Error(
`[node-build-scripts] encodingFormat ${opts.encodingFormat} is not supported`
)
}
Additionally, it was required to install postcss-scss and create postcss.config.js config file to support scss imports:
module.exports = {
syntax: 'postcss-scss',
};
That's all I had to adjust
FYI @prachibansal01
Hi, wondering if there is any chance of an update on resolving this issue within the library? There are a number of things that make the source issue a pain, including:
- The svg-loader issue for Dart-SASS
- For Node-SASS (workaround), many other SCSS functions in the BlueprintJS library aren't supported.
Given it is a few functions, wondering if it would be possible to take another look?
Thanks
@pbower yes I'm interested in taking another look at the tooling issues here but a lot of things have changed since the original post so I think we should start a new thread and only concern ourselves with Blueprint v5.x, Node v18+, and dart-sass. Can you please file a new issue and describe your environment and the problems you're facing in more detail?
Hi Adi,
Sure thing, I will do this later today and provide further details.
In summary - the underlying need mostly relates to overriding the Blueprint CSS _files with non-default values, to implement custom styles (particularly for the light blue colour, which is quite light against a white background), with more of a navy-like colour, as well as application-specific fonts.
This then results in the need to compile the SCSS files when building the application, which causes issues in the build process as describes.
Will comment with the issue number here once logged.
Thanks for your help with this!!
Regards,
Peter
Get Outlook for iOShttps://aka.ms/o0ukef
From: Adi Dahiya @.> Sent: Friday, November 10, 2023 10:33:26 AM To: palantir/blueprint @.> Cc: Peter @.>; Mention @.> Subject: Re: [palantir/blueprint] Unable to compile BluePrint 4 SCSS with webpack sass-loader (Issue #6051)
@pbowerhttps://github.com/pbower yes I'm interested in taking another look at the tooling issues here but a lot of things have changed since the original post so I think we should start a new thread and only concern ourselves with Blueprint v5.x, Node v18+, and dart-sass. Can you please file a new issue and describe your environment and the problems you're facing in more detail?
— Reply to this email directly, view it on GitHubhttps://github.com/palantir/blueprint/issues/6051#issuecomment-1804843279, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AI27BYRORI5MXPGAA35RI53YDVR4NAVCNFSM6AAAAAAWRG5LUCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMBUHA2DGMRXHE. You are receiving this because you were mentioned.Message ID: @.***>
@pbower Did you ever create that new issue? I'm encountering the same thing and can't seem to find it if you have.
Looks like sass-loader fixed the underlying issue (https://github.com/webpack-contrib/sass-loader/issues/774) but SassSvgInlinerFactory still fails with exactly the same problem - anyone have any insight?
Looks like sass-loader fixed the underlying issue (webpack-contrib/sass-loader#774) but SassSvgInlinerFactory still fails with exactly the same problem - anyone have any insight?
No insights, except that it's makes it very difficult to use Blueprint 5, given that it breaks the project from compiling, including Storybook, without workarounds that rely on aging legacy plugins.
Failed to compile. SassError: (path: #5f6b7c)) isn't a valid CSS value. node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[7].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[7].use[2]!./node_modules/resolve-url-loader/index.js??ruleSet[1].rules[5].oneOf[7].use[3]!./node_modules/react-scripts/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[7].use[4]!./src/styles/initialise-theme-palette.scss undefined ╷ 39 │ background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-icon-color))); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unknown function treated as plain CSS ╵ node_modules/@blueprintjs/core/src/components/breadcrumbs/_breadcrumbs.scss 39:54 @import node_modules/@blueprintjs/core/src/components/_index.scss 5:9 @import node_modules/@blueprintjs/core/src/blueprint.scss 18:9 @import src/styles/scss-overrides/blueprint-js/custom-overrides.scss 8:9 @import src/styles/initialise-theme-palette.scss 1:9 root stylesheet
Which is a shame as it's such a great set of components.
The below fix got me through the last 6 months by craco-ing around webpack, but now that dependencies for various project are forced to update, it and storybook has broken:
/* eslint-disable */
const CracoEsbuildPlugin = require("craco-esbuild"); const inliner = require("@vgrid/sass-inline-svg");
module.exports = { plugins: [{ plugin: CracoEsbuildPlugin }], style: { sass: { loaderOptions: { // functions from blueprint : https://github.com/palantir/blueprint/blob/develop/packages/core/scripts/sass-custom-functions.js sassOptions: { functions: { "svg-icon($path, $selectors: null)": inliner("./resources/icons", { optimize: true, encodingFormat: "uri", }), }, }, }, }, }, babel: { plugins: ["@emotion","@emotion/babel-plugin"], }, };
It relied on this plugin which now appears to be dead and incompatible- [email protected] │ repo: https://github.com/artisanofcode/storybook-preset-craco
If there's any way you guys can fix this stuff will be much appreciated.
I wonder if it couldn't be better to simply deprecate svg-icon function because it's only there for solely 2-3 components in the main base. :)