Riot.jsで共通のSCSSファイルを読み込む方法

Riot.jsはタグファイル内のstyleタグにscssを指定することで、自動的にscssをコンパイルしてくれるのはとても便利!

だけど、自動でコンパイルしてくれるがゆえにwebpackのloaderを一緒に使うことができないデメリットがある。

単一ファイルでコンポーネントを実装していると、scssの共通変数やmixinを参照したい時がありそんな時に困ってしまう。

webpackのloaderでsass-resources-loaderという共通ファイルを事前に読みこめるライブラリがあるけど、Riot.jsでは先に書いたように使うことができない。

GitHub - shakacode/sass-resources-loader: SASS resources (e.g. variables, mixins etc.) loader for Webpack

Riot.jsを使っていても、styleタグ内で@importで読み込むことはできるけど、毎回そんなめんどくさいことやってられない!

ということで、なんとかできないかと思って、調べてみると対応することができました。

Riot.jsのスタイルのコンパイル方法を変更する

Riot.jsではスタイルのコンパイル方法を独自のものにカスタマイズすることができます。

定義の方法は下記です。

const riot = require('riot);

riot.parsers.css.custom = (tagName, css) => {}

riot.parsers.cssオブジェクトに任意の名前をつけ関数内に処理を記述して、文字列を返すことで、styleタグ内のコードをコンパイルすることができます。

この場合はcustomという名前にして、これをタグファイルで使うには下記のようにします。

<app>
  Hello World
  
  <style type="custom">
   </style>
</app>

typeの部分に任意でつけた名前を指定してstyleタグ内に記述したコードは上記の引数cssで受け取れるようになります。

node-sassで自分でコンパイルする

Riot.jsのstyleタグで共通の変数やmixinを使うには上記で紹介した方法で、自分でコンパイルすることになります。

まずは下記が共通のsassファイルを読み込んだ上で、cssにコンパイルするためのコードです。

const sass = require('node-sass');

const resources = [
  __dirname + '/src/styles/_variables.scss',
  __dirname + '/src/styles/_mixins.scss',
].map((path) => {
  return fs.readFileSync(path, 'utf8'); //存在判定など適宜
}).join('')

riot.parsers.css.custom = (tagName, css) => {
  const result = sass.renderSync({
    data: resources + css
  }).css

  return result.toString();
}

このコードでやっていることはざっと下記のようなフローです。

  1. resourcesでファイル内の文字列を読みこんで1つの文字列する
  2. タグファイルのstyleタグ内のコードをcssで受取り、resourcesと合わせてcssにコンパイル
  3. コンパイルしたものを文字列にして、returnで返す
{%/box%}

やっていることは単純で共通で読み込みたいファイルのコードとstyleタグのコードを合わせてnode-sassでcssにコンパイルしているだけです。

これでtagファイルの変数やmixinも認識してちゃんとコンパイルされるようになります。

自由にコンパイルできるけどやりすぎには注意

今回紹介した方法は単純なものだけど、やろうと思えば複雑なコンパイル方法にすることも可能。

JSと変数を共通するためにstyleタグ内にJSの変数名を書いて、コンパイルするときに文字列にするということもできてしまうがゆえにやりすぎると、styleタグ内が独自のカオス状態になりそうな未来しか見えない。

autoprefixerを使ってみたりあくまでも、sassの基本的な使い方にとどめておくのがよいかと思う。

コウジ
Vue.jsが好きなフリーランスのフロントエンドエンジニアです。 フロントのHTML・CSS・JavaScriptの設計実装をメインに、RubyとNodeでサーバーサイドやってたりもします。
Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発