Ecosystem

Three bundler plugins. Same API surface. Same CSS output.

Lass ships official plugins for Vite, Bun, and Webpack. Each plugin follows the same pattern: intercept .lass imports, transpile to a JavaScript module via @lass-lang/core, execute the module to extract the CSS string, and hand the result to your bundler's CSS pipeline.

The output is always static CSS. No runtime. No client-side JavaScript.

Vite Plugin

@lass-lang/vite-plugin-lass — The flagship integration.

npm install @lass-lang/vite-plugin-lass --save-dev
// vite.config.js
import { defineConfig } from 'vite'
import lass from '@lass-lang/vite-plugin-lass'

export default defineConfig({
  plugins: [lass()]
})

Key features:

How it works:

  1. Intercepts .lass file imports
  2. Resolves .lass to a virtual .css module (e.g., theme.lass -> theme.css)
  3. Transpiles via @lass-lang/core to a JavaScript module
  4. Executes the JS module to extract the CSS string
  5. Returns CSS to Vite's pipeline for standard processing (PostCSS, minification, etc.)

Peer dependency: Vite 5 or 6.

Full README on GitHub


Bun Plugin

@lass-lang/bun-plugin-lass — Native Bun integration.

bun add @lass-lang/bun-plugin-lass --dev

With Bun.build()

import lass from '@lass-lang/bun-plugin-lass'

await Bun.build({
  entrypoints: ['./src/index.ts'],
  outdir: './dist',
  plugins: [lass()],
})

With bunfig.toml (zero-config preload)

# bunfig.toml
preload = ["@lass-lang/bun-plugin-lass/preload"]

This registers the plugin globally — .lass imports work everywhere without explicit plugin configuration.

Key features:

How it works:

  1. Hooks into Bun's onResolve/onLoad plugin API
  2. Transpiles .lass source to JS via @lass-lang/core
  3. Executes JS to extract CSS string
  4. Returns CSS with loader: "css" to Bun's CSS pipeline
  5. For .module.lass: resolves to a virtual .module.css path for CSS Modules scoping

Limitation: Bun's plugin API doesn't support HMR. For development with hot reloading, use Vite with @lass-lang/vite-plugin-lass.

Peer dependency: Bun 1.0+.

Full README on GitHub


Webpack Plugin

@lass-lang/webpack-plugin-lass — Webpack 5 loader and plugin.

npm install @lass-lang/webpack-plugin-lass css-loader mini-css-extract-plugin --save-dev

Plugin mode (recommended)

// webpack.config.js
const { LassPlugin } = require('@lass-lang/webpack-plugin-lass')

module.exports = {
  plugins: [new LassPlugin()],
}

The plugin auto-configures module.rules — no manual loader setup needed.

Manual loader mode

For projects that need custom loader chains:

// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /\.lass$/,
        use: ['@lass-lang/webpack-plugin-lass'],
        type: 'javascript/auto',
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
}

Key features:

How it works (Svelte-style pattern):

  1. First pass: Loader transpiles .lass to JS, executes it to extract CSS
  2. Caches the CSS and returns JS with a self-referencing inline !=! import
  3. Second pass: Loader returns cached CSS to webpack's CSS pipeline
  4. Preamble imports stay in the module graph for watch/rebuild support

Peer dependency: Webpack 5+.

Full README on GitHub


Shared Plugin Utilities

All three plugins share common logic via @lass-lang/plugin-utils:

CLI

For standalone compilation outside of a bundler:

npm install @lass-lang/cli --save-dev
npx lass button.lass dist/button.css
npx lass src/styles/ --out dist/css/

The CLI uses the same @lass-lang/core transpiler as the bundler plugins. Same input, same output.

Full CLI docs on GitHub


Comparison

Vite Bun Webpack
HMR Yes No Watch mode
CSS Modules .module.lass .module.lass .module.lass
TypeScript default Yes Yes Yes
Zero-config lass() bunfig.toml preload new LassPlugin()
Peer dep Vite 5/6 Bun 1.0+ Webpack 5+

Links