🧭

Sass: @import全盛の既存プロジェクトを最短で@use移行する実践ガイド(破壊しない段階移行)

に公開

@import だらけで変数が何度も展開されてウザい…」「でも一括置換で壊したくない…」
そんな現場向けに、ほぼ一括@use へ移行できる橋渡し(互換)方式をまとめました。
ビルドを壊さずに段階的に“真の @use 流儀”へ寄せていきます。


TL;DR(結論)

  • いきなり全置換は危険@use は名前空間付きで、裸の $var / @include が使えなくなるため。
  • まずは @forward を使った「バレル(index)」を作成し、
    各所の複数 @import1行の @use ... as * に置換 → 既存の書き味を保持。
  • その後、時間のある箇所から as * をやめて名前空間化(衝突・多重展開から卒業)。

🔍 事前チェック(ここだけは見て)

  • テーマ系の変数!default を付けておく(将来 with (...) で上書き可能にするため)
// /_base/_variables.scss
$brand-color: #0a0 !default;
$space-s: 8px !default;
  • 割り算 / を将来直す方針(当面は放置でも可だが、警告源)
    • 置き換え先:@use "sass:math";math.div(10px, 2)

1) 「バレル(再エクスポート)」を作る

/_base/_index.scss を新規作成し、よく使うベース資産を @forward で束ねます。

// /_base/_index.scss
@forward "variables";
@forward "mixins";
@forward "functions"; // あれば

これにより、下流は index を 1回使うだけで、variables/mixins などをまとめて参照できます。


2) 既存の @import を「ほぼ一括」で @use

Before(よくあるやつ)

@import "../_base/variables";
@import "../_base/mixins";
// ...その他いろいろ

After(1行に集約)

@use "../_base/index" as *;
  • as * により、従来どおり $brand-color@include media-sp を「裸」で使えます。
  • つまり ビルドを壊さず @use へ移行可能(まずは“挙動の互換”を得る)。

ポイント:@use は同一モジュールを1回しか評価しないため、多重展開・重複CSSが解消されます。


3) “真の @use 流儀”へ段階移行

余裕が出た箇所から、as * をやめて 名前空間を導入します。

@use "../_base/index" as base;

.button {
  color: base.$brand-color;
  @include base.media-sp {
    font-size: 14px;
  }
}

テーマ上書きが必要な場合は、エントリ付近で with (...) を使います(変数側に !default 必須):

// theme-entry.scss(例)
@use "../_base/variables" with (
  $brand-color: #f33
);
@use "../_base/mixins";

🧩 一括置換の正規表現メモ(サンプル)

プロジェクトごとにパス深度が違うため、よくあるパターンを複数用意しておくと一撃で置換しやすいです。
以下は VS Code の「正規表現モード」を想定。

2行セットの import を 1行の use

Find:

^\s*@import\s+["']\.\.\/_base\/variables["'];\s*\n\s*@import\s+["']\.\.\/_base\/mixins["'];\s*$

Replace:

@use "../_base/index" as *;

パス深度違い(../../_base/... など)も同様にパターンを用意。
あるいは、(_base/variables|_base/mixins) でグルーピングして全体を index に置換する方法もアリ。


📂 フォルダ設計の勘所(例)

sass/
├─ _settings/          // トークン(色/余白/タイポ等)
├─ _mixins/            // mediaや関数群
├─ _base/              // variables/mixins/functions + _index.scss
├─ _module/            // ユーティリティ(.mod-***)
├─ _layout/            // レイアウト(.l-***)
└─ app.scss            // エントリ

🚧 ありがちハマりポイント

  • 変数の上書きができない? → !default + with (...) をセットで。
  • 割り算の警告 → @use "sass:math" + math.div() に。
  • as * はダメ? → 「まず壊さない移行」ではアリ。最終的に外す方向で。
  • 同じ index を複数回 @use? → 評価は1回だけ。安心。

🎯 サンプル:@import 全盛の既存ファイルを救う

Before

@import "../_base/variables";
@import "../_base/mixins";

.card {
  color: $brand-color;
  @include media-pc { padding: 20px; }
}

After(互換フェーズ)

@use "../_base/index" as *;

.card {
  color: $brand-color; // 互換維持
  @include media-pc { padding: 20px; }
}

After(本移行フェーズ)

@use "../_base/index" as base;

.card {
  color: base.$brand-color;
  @include base.media-pc { padding: 20px; }
}

✅ チェックリスト

  • _base/_index.scss を作り、@forwardvariables/mixins を束ねた
  • @import@use "../_base/index" as *; に置換
  • 出力CSSが重複していないか確認
  • 触る箇所から as * を外し、名前空間化
  • 必要なら !default + with (...) でテーマ上書き
  • 将来の math.div 置換計画を立てた

🔗 参考リンク

Discussion