DEV Community

j1ngzoue
j1ngzoue

Posted on • Updated on

Notes on using the Sass Package Importer with Vite

With the introduction of Sass's Package Importer feature, loading Sass files has become simpler and more flexible. This article explains how to use Vite in combination with Sass's Package Importer and how to deal with errors you may encounter when doing so.

What is Sass's Package Importer?

The Package Importer feature in Sass, released in 2024, is a revolutionary feature that allows you to import Node.js packages directly. It is more convenient than the traditional @import statement and is suitable for modern Sass projects. This feature simplifies project dependency management and eliminates the need to manually specify the Sass file for a package.

More details are explained in an announcement on the official Sass blog. It seems that most CSS frameworks can use it without any changes at the publisher.
https://sass-lang.com/blog/announcing-pkg-importers/

Also, in line with Package Importer support,

Vite and Sass Integration

Vite is a module bundler popular for its speed and ease of use. It is particularly well suited for front-end development and integrates smoothly with Sass.

Starting with Vite:5.4.0, support for the Sass moder api has been added. If you want to use it, you need to upgrade to version 5.4.0 or higher.
https://github.com/vitejs/vite/blob/v5.4.6/packages/vite/CHANGELOG.md#540-beta0-2024-07-30

You also need to set importers in vite.config.ts as follows
https://sass-lang.com/documentation/js-api/classes/nodepackageimporter/

import { defineConfig } from vite;.
import { NodePackageImporter } from sass-embedded;

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: modern, { scss: { preprocessorOptions: { scss: { preprocessorOptions
        importers: [new NodePackageImporter()], }
      }, }
    }, }
  }, }
});
Enter fullscreen mode Exit fullscreen mode

Internally at build time, the compile function is now called.

Build errors that occur with Vite and their causes

When using the Package Importer with Vite using the sass package, I encountered the following error at build time.

[vite:css] [sass] Error: TypeError: importer.findFileUrl is not a function
Enter fullscreen mode Exit fullscreen mode

This is due to a conflict when trying to use the Vite dependency sass-embedded and the traditional Sass package, as they are recognized as different instances of NodePackageImporter. This error is due to the fact that the instances used inside Sass and Vite do not match.
It is hard to tell from the error, but the error is actually in the following section
https://github.com/sass/embedded-host-node/blob/59dde59163a58a33aa8180dbf8e23d2216913712/lib/src/importer-registry.ts#L84-L109

Solution to the error

To work around this error, you need to change your Vite settings appropriately. Specifically, it is best to proceed with development assuming that Vite does not import Sass packages separately, but uses sass-embedded provided by Vite. official.

This issue is also raised in GitHub Issue #16438. Instead of using the traditional Sass package, you should set css.preprocessorOptions to assume sass-embedded. Note that it is or sass but it doesn't work.

I thought I didn't get an error not too long ago?

I checked and sass-embedded was included in peerDependencies at this time, so it must have been an error since then.
https://github.com/vitejs/vite/commit/1025bb6d8f21c0cb9fe72405d42e0f91bb3f1d8e

Also, it seems that sass-embedded is preferred, so you need to use sass-embedded when using modern in any case.
https://github.com/vitejs/vite/blob/f9691767ad763720065cc7c5c7f369f97b4e7ea8/packages/vite/src/node/plugins/css.ts#L2030-L2046

Since I was using npm at the time of verification, I think the result would have been different if I had resolved peerDependencies and used pnpm for the installation.
Later, I also confirmed that if I actually used pnpm and installed only sass, the build finished successfully with the following code.

import { defineConfig } from “vite”;.
import { NodePackageImporter } from “sass”;

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: “modern”, { importers:[new NodePackageImporter } from “sass”; export default
        importers: [new NodePackageImporter()], }
      }, }
    }, }
  }, }
});
Enter fullscreen mode Exit fullscreen mode

Efficient CSS loading

This should go without saying, but when using the Sass package importer, if you load the entire package like @use “pkg:bulma”; all CSS will be included in the build. This may result in a large CSS file after the build, as many unnecessary styles are included.

In such cases, it is recommended to specify and load only the necessary components. For example, if you want to use only some components of Bulma, specify as follows

@use “pkg:bulma/sass/components/breadcrumb”;.
Enter fullscreen mode Exit fullscreen mode

This way, only the necessary CSS is included in the build, thus compressing the post-build stylesheet and optimizing file size. Even so, unnecessary css will probably be included. In that case, you may need to write your own purge process.

If you want to use only common functions or utilities, it is better to set them to additionalData and load them as before.

import { defineConfig } from “vite”;.
import react from “@vitejs/plugin-react”;
import { NodePackageImporter } from “sass-embedded”;

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        api: “modern”, importers: [new NodePackageImporter()], {
        importers: [new NodePackageImporter()], { additionalData: `@use “pkg:bulma/sass/utilities” as
        additionalData: `@use “pkg:bulma/sass/utilities” as utilities;;`,
      }, }
    }, }
  }, }
  plugins: [react()], `@use “pkg:bulma/sass/utilities” as utilities;;`, }, }
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)