Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sass Bundle Laravel Package

symfonycasts/sass-bundle

A Symfony bundle that compiles Sass/SCSS to CSS using Dart Sass and integrates with AssetMapper. It provides build and watch commands, source maps, and simple configuration for modern asset pipelines.

Deep Wiki
Context7

Getting Started

  1. Install and let Flex wire it up. composer require symfonycasts/sass-bundle — the Flex recipe registers the bundle and drops a config/packages/sass.yaml. If you're not using Flex, add Symfonycasts\SassBundle\SymfonycastsSassBundle to config/bundles.php.
  2. Look at config/packages/sass.yaml first. That file defines the two paths that matter: where your .scss entries live (sass_path, typically assets/styles) and where compiled .css lands (css_path, also under assets/ so AssetMapper can serve it). Everything else in the bundle is downstream of those two knobs.
  3. Create an entry file. assets/styles/app.scss with a few rules (or @use some partials) is your first real use case.
  4. Compile once: php bin/console sass:build. Confirm a sibling .css file appears in css_path.
  5. Wire it into a page. Because the output lives inside assets/, AssetMapper already knows about it. Either <link rel="stylesheet" href="{{ asset('styles/app.css') }}"> in base.html.twig, or import './styles/app.css' from your app.js entrypoint if you prefer bundling through importmap.
  6. Switch to watch mode for daily work: php bin/console sass:watch in a second terminal next to symfony serve. Edit a partial, refresh the browser, see the change. That's the 90% loop.

First pitfall to know before you start: the very first build downloads the Dart Sass binary for your platform. If you're offline, behind a proxy, or in a locked-down CI, the build will hang or fail before any SCSS is even parsed — see Gotchas.

Implementation Patterns

Entrypoints vs. partials. Dart Sass compiles every non-partial .scss it finds under sass_path; anything starting with _ is treated as a partial and skipped as an output. So the conventional layout is one thin entry per page/section and a shared library:

assets/styles/
  app.scss              -> app.css
  admin.scss            -> admin.css
  _variables.scss
  _mixins.scss
  components/_buttons.scss
  pages/_dashboard.scss

app.scss is just @use 'variables'; @use 'components/buttons'; .... Keep entry files declarative; put real rules in partials.

Module system. Use @use/@forward (not @import). Give each partial a namespace and forward a shared API from an _index.scss so callers do @use 'components' as c; instead of reaching into deep paths. This is also what protects you from the Dart Sass @import deprecation warnings.

Dev workflow. Run two watchers in parallel: sass:watch for SCSS→CSS and asset-map:compile --watch (or just symfony serve) for AssetMapper's importmap rebuilds. A composer dev script using concurrently or a Procfile-style setup pays for itself immediately:

"scripts": {
  "dev": ["php bin/console sass:watch", "symfony serve"]
}

Deploy pipeline. The build order matters: sass:build must run before asset-map:compile, because the latter fingerprints whatever CSS exists at that moment. In a Dockerfile, that's typically composer install --no-dev, sass:build, asset-map:compile, all during image build. Add sass:build to a post-install-cmd only if you're sure the binary is available at install time.

Per-page CSS. Since each entry compiles independently, you can emit a small app.css plus admin.css, checkout.css, etc., and include only the ones a given template needs. This is a legitimate reason to use this bundle instead of a single bundled stylesheet — take advantage of it.

Programmatic use. The bundle exposes the compiler as a service (a SassBuilder-style object). If you need compilation triggered from a custom command, a test bootstrap, or a deploy script that isn't a shell call, inject it rather than shelling out to sass:build.

Where you shouldn't fight it. This bundle is intentionally a thin wrapper around the Sass CLI scoped to AssetMapper. If you need PostCSS, autoprefixing, CSS modules, or a full frontend toolchain, that's Webpack Encore / Vite territory. Don't try to bolt a plugin pipeline onto this.

Gotchas and Tips

  • The binary download is the #1 support issue. First sass:build fetches Dart Sass and stores it under var/. Consequences: it needs network access and a writable var/; cache:clear may remove it and force a re-download; CI images that build offline need the binary pre-provisioned and pointed to explicitly via the bundle's binary path config, or a sass executable on PATH.
  • sass_path vs css_path mismatch with AssetMapper. If you point css_path outside the directories AssetMapper scans, the CSS compiles fine but {{ asset(...) }} 404s or asset-map:compile never sees it. Either keep output under assets/ (the default and the happy path) or register the extra directory in asset_mapper.paths.
  • Compiled CSS and git. Generated CSS inside assets/ is an artifact. Gitignore it and make sure every clone/CI runs sass:build — otherwise a fresh checkout has a broken importmap the first time someone runs asset-map:compile. Conversely, don't gitignore and skip the build step in your deploy.
  • Stale output after editing only a partial. Dart Sass tracks dependencies, but the bundle also does its own mtime-based skip logic. If you edit an included partial and nothing changes, delete the bundle's cache directory (or touch the entry file) before assuming the compiler is broken. Watch mode is usually immune; one-shot builds are where this bites.
  • Watch mode and config edits. sass.yaml changes are not hot-reloaded — restart sass:watch after touching paths or output style. Also restart after composer require of anything that affects the binary.
  • Docker/WSL/network mounts. Native file watchers often miss changes on bind-mounted volumes. Run sass:watch with a polling flag if the bundle exposes one (check sass:watch --help) or fall back to re-running sass:build on save via a small file-watcher script.
  • @import deprecation noise. Recent Dart Sass versions emit deprecation warnings for @import, and the bundle passes them straight through. Migrate to @use, or, if the config surface allows, silence specific deprecations; long-term, don't pin an old binary just to hide warnings — you'll hit the same wall later.
  • Source maps in production. Source maps are great in dev and dead weight (plus a potential source-disclosure smell) in prod. Toggle output style/source map emission per environment in sass.yaml — compressed + no maps for prod, expanded + maps for dev.
  • Windows and executable bits. The downloader picks the right binary per OS, but if you override the binary path, make sure it's actually executable and, on Windows, that the .exe/.bat shim is pointed at correctly. "Permission denied" or "not a valid Win32 application" almost always means a misconfigured binary path.
  • Watch/refresh race. With two watchers, the browser can reload before sass:watch has written the new CSS, so you see the old styles on HMR/live-reload. Either add a small debounce to your livereload setup or compile on save via an editor task and let asset-map:compile --watch pick it up.
  • Extension point worth knowing. The builder is a normal Symfony service — you can decorate or override it to add CLI arguments (e.g., --style=compressed, --no-source-map, --load-path=...) without forking the bundle. That's the safest way to add behavior the config doesn't expose yet.
  • Maturity check. This is a small, focused package (a few dozen stars) from a well-known Symfony educator. It's dependable for the narrow job it does, but don't expect a rich plugin ecosystem or rapid triage; if you hit an edge case, budgeting time to read the bundle source is more realistic than waiting for a fix.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package