4.2 KiB
@advdominion/sass-importer
Кастомный импортёр для sass-embedded, который берёт резолв @use/@forward-импортов на себя и читает файлы через node:fs.
Зачем
В проектах на Yarn PnP пакеты лежат не в node_modules, а внутри .zip по виртуальным путям:
.yarn/__virtual__/@example-example-virtual-.../cache/@example-example-....zip/node_modules/@example/example/...
.zip-путь может открыть только код, читающий файлы через node:fs (в нём есть PnP-хуки). А sass-embedded читает файлы своим отдельным кодом, node:fs не использует, поэтому импорты внутри пакетов не резолвятся. Этот импортёр обходит проблему: он сам превращает импорт в существующий файл (canonicalize) и отдаёт его содержимое через readFileSync (load).
Работает и в node-modules-проектах — там require без PnP-хуков, но тот же резолв остаётся корректным.
Установка
yarn add -D @advdominion/sass-importer
Использование
import { createImporter } from '@advdominion/sass-importer';
const require = createRequire(import.meta.url);
const importer = createImporter(require);
const { css } = compiler.compileString(source, {
importers: [importer],
loadPaths: ['src/styles'],
});
Импортёр принимает require из createRequire(import.meta.url): в PnP он несёт PnP-хуки, в node-modules — обычный require. Это позволяет резолвить и пакеты, и их внутренние относительные импорты одинаково надёжно.
API
createImporter(require): Importer
require— функция резолва (обычноcreateRequire(import.meta.url)), используется для веткиpkg:.- Возвращает объект из двух колбэков для
sass-embedded:canonicalizeиload.
canonicalize(url, ctx) превращает импорт в канонический file:// URL или возвращает null («я не знаю такой файл» — тогда Sass перебирает следующие импортёры/loadPaths).
load(canonicalUrl) отдаёт содержимое файла и его синтаксис (syntax: 'scss'). Если файла нет — бросает Error: Stylesheet not found: <путь>.
Правила резолва
| Приоритет | Вариант | Пример |
|---|---|---|
| 1 | Точное совпадение | @use 'variables' → variables (файл) |
| 2 | Файл с расширением | @use 'variables' → variables.scss |
| 3 | Каталог с _index |
@use './lib' → ./lib/_index.scss |
| 4 | Каталог с index |
@use './lib' → ./lib/index.scss |
Для каталогов берутся _index и index как с .scss, так и с .css. Порядок проверок соответствует порядку перебора Sass, поэтому первая найденная запись — приоритетная.
Виды импортов
pkg:@scope/pkg/path/to/file→require.resolve+ резолв кандидата.file:///abs/path→ кандидат по файловому пути.- относительные (
../../variables) → склейка с каталогом содержащего файла (берётся изctx.containingUrl), затем резолв кандидата. - абсолютные (
/...) и незнакомые схемы (http:,data:) → отдаётnull, резолв остаётся на Sass.
Лицензия
MIT