sasso

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: Apache-2.0, MIT Imports: 7 Imported by: 0

README

sasso-go

A pure-Go (no cgo) binding to the sasso SCSS-to-CSS compiler. It embeds the sasso WebAssembly module and runs it with wazero, so it has no native dependencies, needs no C toolchain, and builds with CGO_ENABLED=0. The resulting binaries are fully static and trivially cross-compile to any target Go and wazero support.

go get github.com/momiji-rs/sasso-go

Usage

package main

import (
	"fmt"
	"log"

	sasso "github.com/momiji-rs/sasso-go"
)

func main() {
	css, err := sasso.Compile(`.a { .b { color: #336699 } }`)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Print(css)
	// .a .b {
	//   color: #336699;
	// }

	// Compressed output:
	min, _ := sasso.Compile(`.a{color:#336699}`, sasso.WithStyle(sasso.Compressed))
	fmt.Println(min) // .a{color:#369}
}

A Sass error is returned as a *sasso.Error:

_, err := sasso.Compile("a { color: ")
var se *sasso.Error
if errors.As(err, &se) {
	fmt.Println("sass error:", se.Message)
}
Source maps
res, err := sasso.CompileWithSourceMap(".a { color: red }")
// res.CSS        -> the CSS string
// res.SourceMap  -> source-map v3 JSON (includes the original source content)

Why pure Go?

  • No cgo, no C compiler. Just go get and build.
  • CGO_ENABLED=0 and cross-compilation work out of the box — produce a static linux/amd64, linux/arm64, windows/amd64, darwin/arm64, ... binary from any host, no cross C toolchain.
  • One self-contained dependency (wazero, itself pure Go).
  • Fast. Once the runtime is warm, a compile is on the order of microseconds — on the test machine roughly a thousand times faster than spawning the dart-sass CLI once per compile.

Scope and limitations

This binding is string-in / CSS-out: it compiles a single SCSS source string into CSS. The embedded wasm module is freestanding and has no filesystem access, so the following are not supported here:

  • @use / @import that load other files
  • custom importers / load paths

If you need file-based loading or a custom importer, use the sasso C ABI (cgo) or a binding built on it. For the common "compile this stylesheet" case, the wasm path is all you need — inline @use/@import of built-in modules (sass:math, sass:color, ...) and everything that operates on a single source string works.

Startup cost

wazero's optimizing compiler translates the embedded ~2 MB wasm to machine code on first use — a one-time cost of roughly a second on the first Compile, after which each compile takes tens of microseconds. The runtime is initialized lazily and kept alive for the life of the process, so you pay it once per process.

To avoid paying it even once per process, cache the compiled module on disk with UseCompilationCache — the first run ever populates the cache (~1 s); every later process start reads the cached machine code and is ready in ~20–30 ms:

cacheDir, _ := os.UserCacheDir()
sasso.UseCompilationCache(filepath.Join(cacheDir, "sasso-go")) // before the first Compile

Alternatively, for short-lived one-shot processes, opt into wazero's interpreter (no machine-code compilation), which starts ~10× faster at the cost of slower per-compile throughput:

sasso.UseInterpreter(true) // call once, before the first Compile
Engine Cold start Warm per-compile
Optimizing compiler (default) ~1 s ~tens of µs
Optimizing compiler + UseCompilationCache ~20 ms (after first run) ~tens of µs
Interpreter (UseInterpreter) ~80 ms ~ms

(Numbers are order-of-magnitude on an Apple M2 Max; your mileage varies.)

Concurrency

A single shared wasm instance backs the package and is guarded by a mutex. Compile is safe to call from multiple goroutines, but calls are serialized.

Versioning

sasso-go has its own version, which floats independently and pins a specific sasso core (the embedded wasm). This release bundles sasso core 0.6.1 (sasso.CompilerVersion); the package version is reported by sasso.Version().

License

Dual-licensed under either of MIT or Apache-2.0 at your option, matching the sasso core.

Documentation

Overview

Package sasso is a pure-Go (no cgo) binding to the sasso SCSS-to-CSS compiler.

It embeds the sasso WebAssembly module and runs it with the wazero runtime, so it has no native dependencies, requires no C toolchain, and builds with CGO_ENABLED=0. That makes the resulting binaries fully static and trivial to cross-compile to any target Go and wazero support.

Usage

css, err := sasso.Compile(".a { .b { color: #336699 } }")
if err != nil {
	log.Fatal(err)
}
fmt.Print(css)

Choose the output style with WithStyle:

css, _ := sasso.Compile(src, sasso.WithStyle(sasso.Compressed))

A Sass error (bad syntax, undefined variable, ...) is reported as an *Error.

Scope

This binding is self-contained string-in / CSS-out: it compiles a single SCSS source string into CSS. The embedded wasm module is freestanding and has no filesystem access, so @use / @import that load other files and custom importers are NOT supported here. If you need file-based loading or a custom importer, use the sasso C ABI (cgo) or a binding built on it (for example sasso-python / sasso-ruby). For most "compile this stylesheet" use cases the wasm path is all you need.

Concurrency

A single shared wasm instance backs the package and is guarded by a mutex, so Compile is safe to call from multiple goroutines, but calls are serialized.

Versioning

sasso-go has its own version (see Version) that floats independently and pins a specific sasso core (see CompilerVersion), which is the version of the bundled wasm module.

Index

Constants

View Source
const CompilerVersion = "0.6.1"

CompilerVersion is the version of the bundled sasso core (the wasm module). The wasm module does not export a version string, so this is tracked here and updated whenever the embedded sasso.wasm is refreshed.

Variables

This section is empty.

Functions

func Compile

func Compile(scss string, opts ...Option) (string, error)

Compile compiles an SCSS source string and returns the resulting CSS.

On a Sass error the returned error is an *Error carrying the compiler's diagnostic message.

func UseCompilationCache added in v0.1.1

func UseCompilationCache(dir string)

UseCompilationCache persists wazero's compiled wasm module to an on-disk cache in dir, so the optimizing compiler's one-time module compilation (~1s, see UseInterpreter) is paid only ONCE, ever — across process restarts. The first run with a given dir populates the cache; every subsequent start reads the cached machine code and is ready in roughly 20ms. The cache is keyed by the wazero version and the module's content, so stale entries are ignored automatically and the dir is safe to share across sasso-go versions.

Call it once before the first Compile (the engine is built once); calling it afterward has no effect. An empty dir disables the cache (the default). A dir that can't be created surfaces as an error from the first Compile. A good choice is a subdirectory of os.UserCacheDir.

func UseInterpreter

func UseInterpreter(b bool)

UseInterpreter selects wazero's interpreter engine instead of its default optimizing compiler. Call it once before the first Compile; calling it after the engine is built has no effect.

Trade-off: the optimizing compiler (default) compiles the embedded wasm to machine code, which costs roughly a second of one-time startup but then runs each Compile in tens of microseconds. The interpreter starts about ten times faster but runs each Compile a couple of orders of magnitude slower. Prefer the interpreter for short-lived processes (a CLI compiling a few files); prefer the default for servers or batch jobs that compile many times.

func Version

func Version() string

Version returns the sasso-go package version. sasso-go's version floats independently of the bundled compiler; see CompilerVersion for the core it pins.

Types

type Error

type Error struct {
	Message string
}

Error is returned when the Sass compiler reports an error (syntax error, undefined variable, and so on). Its Message is the compiler's diagnostic.

func (*Error) Error

func (e *Error) Error() string

type Option

type Option func(*options)

Option configures a Compile call.

func WithStyle

func WithStyle(s Style) Option

WithStyle sets the output style (Expanded or Compressed). The default is Expanded.

type Result

type Result struct {
	CSS       string
	SourceMap []byte
}

Result bundles the CSS and the source map produced by CompileWithSourceMap.

func CompileWithSourceMap

func CompileWithSourceMap(scss string, opts ...Option) (Result, error)

CompileWithSourceMap compiles SCSS and also returns a source map (JSON).

The returned Result.CSS is the CSS and Result.SourceMap is the source-map JSON. The source map includes the original source content. On a Sass error the returned error is an *Error.

type Style

type Style int

Style selects the CSS output style.

const (
	// Expanded is dart-sass's default human-readable output.
	Expanded Style = iota
	// Compressed minifies the output (no whitespace, short hex, ...).
	Compressed
)

Directories

Path Synopsis
cmd
demo command
Command demo is a tiny consumer of the sasso-go package: it compiles an SCSS snippet, prints the CSS, and (when a dart-sass binary is available) benchmarks in-process compilation against spawning dart-sass once per compile.
Command demo is a tiny consumer of the sasso-go package: it compiles an SCSS snippet, prints the CSS, and (when a dart-sass binary is available) benchmarks in-process compilation against spawning dart-sass once per compile.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL