Closed Znert closed 2 months ago
You are on your own. sass-embedded is only guaranteed to work with version matched dart-sass, and the version shipped by Nix is usually not the right version. For example, the current version in Nix is a few releases behind, and there was a breaking change for color-4 embedded protocol, which will break if you try to force older version of dart-sass from Nix.
Well, anything is better than not being able to run the sass compiler at all, right?
I tried to apply an pnpm patch
to test my theory out and so far it seems to work fine. But I've only got a very basic project, so I assume there will be dragons later down the line. Will post my code for anyone running into a similar issue tomorrow, because I've also turned off my PC for the day.
As for version missmatch, I would be fine with running an older version of the library. I'll check tomorrow which binary version you support with which package version.
anything is better than not being able to run the sass compiler at all, right?
Yes, but because this can easily break, I don’t think we want to officially support it. As you already discovered you can still patch the package locally yourself.
Another solution is to port the logic used by ruby sass-embedded: https://ntk.me/2023/06/04/invoking-ld-linux-so/ Given that we now have an elf parser that read the interpreter, it should be relatively easy to port the ruby implementation.
As promised, here is the patch I applied for anybody in a similar spot as me:
pnpm patch sass-embedded
(if you don't use pnpm, there is also a patch-package npm package available. But I have no experience with it)pnpm patch
outputs and open the file dist/lib/src/compiler-path.js
.exports.compilerCommand = (() => {
line, add this code:
const binPath = process.env.SASS_EMBEDDED_BIN_PATH;
if (binPath) {
return [binPath];
}
pnpm patch says
In your project root directory, you should now have a folder called patches
with a file called sass-embedded.patch
. For the version of sass-embedded
I had installed, this was the content of the file:
diff --git a/dist/lib/src/compiler-path.js b/dist/lib/src/compiler-path.js
index c274baf174a035c4b568f14e7167900cb29911481b69dcf5b46641315cc65f8b..0beebe20c20cb68248f80048de57696cb44a7b57d873de3fd4ee3eb002adfee6 100644
--- a/dist/lib/src/compiler-path.js
+++ b/dist/lib/src/compiler-path.js
@@ -24,6 +24,10 @@ function isLinuxMusl(path) {
}
/** The full command for the embedded compiler executable. */
exports.compilerCommand = (() => {
+ const binPath = process.env.SASS_EMBEDDED_BIN_PATH;
+ if (binPath) {
+ return [binPath];
+ }
const platform = process.platform === 'linux' && isLinuxMusl(process.execPath)
? 'linux-musl'
: process.platform;
In order to set the SASS_EMBEDDED_BIN_PATH
env variable, I'm using this flake.nix
:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs, ... }:
let
lib = nixpkgs.lib;
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
};
in
{
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
nodejs_20
pnpm
dart-sass
];
SASS_EMBEDDED_BIN_PATH = "${pkgs.dart-sass}/bin/sass";
};
};
}
To make everything work with VSCode, I've installed the direnv extension and setup an .envrc
:
if ! has nix_direnv_version || ! nix_direnv_version 3.0.5; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc" "sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w="
fi
use flake
More details can be found in the nix.direnv
repo.
Obviously this setup won't be very stable. Any update to either the dart-sass
Nix package or the sass-embedded
npm package could easily break the setup. But for now it seems to work...
Edit: I also had to update the vite.config.ts
to get rid of the legacy API message:
diff --git a/vite.config.ts b/vite.config.ts
index 3427d0a..c95006f 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -3,6 +3,13 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [sveltekit()],
+ css: {
+ preprocessorOptions: {
+ scss: {
+ api: 'modern-compiler',
+ },
+ },
+ },
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
},
I agree with @ntkme here that we should actively avoid supporting this officially because it's so easy to get broken. I think the "correct" way to handle it would be to have NixOS build the entire Sass embedded stack and npm link
it into your project.
Makes sense to me. Say I would like to do something like that, how would I go about this?
Looking at your prepare-optional-release.ts
script, you download the pre-built binaries from sass/dart-sass and package them as npm packages. I think I could write a "post init" script to my flake.nix
, that would replace the content of the sass-embedded-linux-x64
(or similar) to use the binaries packaged for/by NixOS.
But I think the result would just be the same: Version mismatch hell :thinking:
I think maybe it would just be simpler to pull a specific version of dart-sass
and the appropriate npm package version of sass-embedded
.
Of course if you can't help me, that's also fine. As long as I have a somewhat working workspace, I'm happy :smile:
I'm not very familiar with NixOS, but I can help you navigate the build process of these packages. When you're building the embedded host, you can pass --compiler-path
and --language-path
flags to npm run init
to have it build against a local version of Dart Sass and the Sass language repo, respectively. So my recommendation would be:
npm run init
with the flags aboveHello, came across when I had the same problem. There is a solution for this called nix-ld, you can read about it here: https://nix.dev/guides/faq#how-to-run-non-nix-executables This lets you install dynamic libraries to be used like "normal" by unpackaged programs. Adding the following to my configuration.nix has solved this issue and similar ones for me:
# Dynamic libraries for unpackaged programs
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
glibc
libcxx
];
FWIW just removing the module apparently works around the problem? Not sure if it just falls back to js or whatever
https://github.com/NixOS/nixpkgs/pull/351966/files
preBuild = ''
# using sass-embedded fails at executing node_modules/sass-embedded-linux-x64/dart-sass/src/dart
rm -r node_modules/sass-embedded*
''
(and I'm now doing the same for rmfakecloud, that appears to have built something and it doesn't look too wrong...)
@martinetd I think it'll fallback on the JS version which is way slower..
I recently wanted to bootstrap a new Sveltekit app and use
sass-embedded
so that I can use SCSS in my web app. But because I run NixOS, I can't use the pre-compiled version of sass-dart you are shipping with thesass-embedded-linux-x64
package - dynamic linking works a little differently on NixOS than on normal Linux distributions.Now, NixOS already provides a working binary via the dart-sass package. However, there is no way for me to instruct
sass-embedded
to use the existing (globally installed)sass
binary instead of the one inside thenode_modules
folder.My idea would be to use some env variable, something like
SASS_EMBEDDED_BIN_PATH
, that I can set in order to point towards the binary I want to use.I'm not sure if you need/want to add some checks to ensure that the
sass-embedded
package is compatible with thesass
binary, but I think it's fair to tell the user "you are on your own if you do this".