DartSass - An installer for sass

I just published v0.2.0:

  • No longer load config/runtime.exs by default, instead support --runtime-config flag
  • Update initial sass version to 1.39.0
  • mix sass.install --if-missing also checks version
3 Likes

v0.2.1 (2021-09-23)

  • Apply missing --runtime-config flag check to mix sass.install

v0.3.0 (2021-10-04)

  • Support Apple M1 via Rosetta2
1 Like

Hi,
Thank you for the great library. I’m using AWS version of ARM64 and I couldn’t run it, because Dart is not released for that architecture.
My project is built on GitLab CI with Docker, so I’ve created an image for ARM64 with preinstalled Elixir, Dart and Sass. In the description you can find instructions on how to use it with dart_sass library.

I hope that someone may find it useful:
https://hub.docker.com/r/lucidmodules/phoenix-dart

2 Likes

v0.4.0 (2022-01-19)

  • Update Sass version to 1.49.0
  • Attach system target architecture to saved esbuild executable
  • Use user cache directory
  • Add support for 32bit linux
  • Support HTTP_PROXY/HTTPS_PROXY to fetch esbuild
  • Fallback to _build if Mix.Project is not available
  • Allow config :dart_sass, :path, path to configure the path to the Sass executable (or snapshot)
  • Support OTP 24 on Apple M1 architectures (via Rosetta2)
2 Likes

How can i use standalone Tailwind and standalone SASS together ?

Great question! I am not sure :slight_smile:

Can you tell me more about what you’re trying to do, and about how you want the packages to work together?

First, this DartSass installer is awesome. Thank you, @mcrumm!

In terms of using standalone Tailwind and DartSass together, here’s something I’ve been experimenting with that might help…

In educational apps specifically, I often want to avoid using a lot of Tailwind utility classes in templates. To do that, I rely on Tailwind’s @apply directive. And when it’s a fairly significant amount of CSS, it’s often handy to use CSS nesting which is where DartSass comes in.

Here’s an example css/app.scss file that demonstrates the problem in an abbreviated form:

@tailwind base;
@tailwind components;
@tailwind utilities;

.card {
  @apply p-4 bg-blue-300 text-blue-800 rounded-lg;

  & .title {
    @apply text-2xl tracking-tight font-bold;
  }

  & .details {
    @apply pt-4 text-lg font-medium;

    & a {
      @apply underline;
    }
  }
}

Now if you run that file through the Tailwind CLI alone, it won’t flatten out the nesting. (The @tailwind/nesting package isn’t baked into the Tailwind CLI as far as I can tell).

However, you can first run that file through DartSass and then run the result through the Tailwind CLI. In other words, pipe the output of one into the other.

Here’s how I’ve been doing it:

First, setup the watchers in the right order:

  watchers: [
    dartsass: {DartSass, :install_and_run, [:default, ~w(--watch)]},
    tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}
  ]

Then configure dart_sass to process app.scss and drop the result in an intermediate file named app.tailwind.css for example:

config :dart_sass,
  version: "1.49.0",
  default: [
    args: ~w(css/app.scss ../priv/static/assets/app.tailwind.css),
    cd: Path.expand("../assets", __DIR__)
  ]

Finally, configure tailwind to use the DartSass output file as its input and spit out the final output in app.css:

config :tailwind,
  version: "3.0.18",
  default: [
    args: ~w(
      --config=tailwind.config.js
      --input=../priv/static/assets/app.tailwind.css
      --output=../priv/static/assets/app.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ]

I’ve only been experimenting with this for a couple days, so there are likely limitations I haven’t bumped into yet.

Is that the sort of thing you’re trying to do, @hxgdzyuyi?

I look forward to hearing of better ways to do this. :wink:

3 Likes

This looks great to me!

Honestly I am not sure there is much room for improvement on this pattern. It’s essentially what’s recommended by Tailwind when using a preprocessor, whatever the flavor: Using with Preprocessors - Tailwind CSS

Thanks!

The new bit for me is stepping outside the realm of PostCSS (which requires Node) to handle the nesting. For example, typically I’d have a postcss.config.js that puts postcss-nesting in the pipeline:

module.exports = {
  plugins: {
    "postcss-nesting": {},
    tailwindcss: {}
  }
}

But yeah, using DartSass and Tailwind as described is effectively doing the same thing, just without PostCSS (and therefore Node) in the mix. And that’s my primary reason for going this route. :grinning:

2 Likes

Then I used it like this


  watchers: [
    # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
    tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]},
    sass: {
      DartSass,
      :install_and_run,
      [:default, ~w(--embed-source-map --source-map-urls=absolute --watch)]
    }
  ]

thanks !

v0.5.0 (2022-04-28)

  • Support upstream arm64 binaries
  • Update Sass version to 1.49.11

A note about the Sass version
While there are newer releases of the dart-sass package available, v1.50.0+ currently has a broken --watch implementation and must not be used until it is fixed and a new version is released. Fortunately once that happens we should be able to remove the bash runner script from the Elixir package.

2 Likes

v0.5.1 (2022-08-26)

  • Update Sass version to 1.54.5
  • Skip platform check when given a custom path (h/t @jgelens)
  • Use only TLS 1.2 on OTP versions less than 25.
2 Likes

v0.6.0 (2023-04-19)

Potentially breaking change: Due to a change in the upstream package structure, you must specify a :version >= 1.58.0 on Linux platforms.

  • Depend on inets and ssl by josevalim in #30
  • Updated Sass version to 1.61.0 by azizk in #31
  • Renames DartSass.bin_path/0 to DartSass.bin_paths/0.
  • Supports installation of newer upstream packages on Linux platforms. (h/t azizk)
  • Overriding :path disables version checking.
1 Like

PSA:

For those using SASS because of nesting and variables, esbuild might just be enough now. Using 0.17.18 atm.

By setting the target to be chrome58, it will rewrite the new css nesting rules to be functional on browsers that don’t support it. BEM won’t work anymore as the & operator no longer does a strict append in all cases. However, by using CSS variables, I got rid of SASS with a bit of rewriting.

The details

config.exs
config :esbuild,
  version: "0.17.18",
  default: [
    args: ~w(js/app.js --bundle --target=es2016,chrome58 --outdir=../priv/static/assets --external:*.woff2 --external:*.svg),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

app.js

App.js includes the css file for esbuild to generate and dump everything into priv/static/assets

import "../css/app.css"

v0.7.0 (2023-06-27)

This release should be fully compatible with Elixir v1.15+

  • Require Elixir v1.11+
  • Mark inets and ssl as optional apps
  • Ensure the install task only loads the runtime config with --runtime-config