はじめに
Reactを使う時、css-loaderで:local(.className)
または:local{...}
と宣言した場合にclassNameがハッシュ化されexportされる。
それらのモジュールをimportする時、vscode(またはその他IDE)のIntelliSenseを使えると大変便利だと思う。
その方法をメモします。
やり方
フォルダ構成
+- demo-app/
+- package.json
+- tsconfig.json
+- webpack.config.js
+- html/
+- index.html
+- scripts/
+- foo.tsx
+- styles/
+- foo.scss
+- foo.scss.d.ts
css-loaderの導入
割愛します。
一応webpack.config.js
のextensions
の領域に下記の拡張子を追加するのを忘れずに。
resolve: {
extensions: [... ".sass", ".scss", ".css"]
}
スタイルの記入
// ここはGlobal Style
* {
color: royalblue;
}
// ここはScroped Style
:local {
.bar {
background-color: aquamarine;
}
.baz {
font-size: 2em;
}
}
スタイルの仮導入
.d.ts
を作成しなくても、tsファイルの中で下記の記述のようにrequire()
を使えば、別に導入できなくもないですが、TSスタイルではないので、ちゃんとimport
できるようにする。
const style = require('styles/foo')
型定義ファイル.d.ts
の作成
TSにJSファイルを導入する時と同じように、ファイル名.d.ts
を作成すればOK。
記述の仕方はこちらを参考していた。
declare module '*.scss' {
const content: {
bar: string;
baz: string;
};
export default content;
}
TSにimport
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import styles from 'styles/foo.scss' // 拡張子省略不可
const Hello: React.FC<{}> = props => (
<div className={styles.bar}>Hello World!
</div>
)
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Hello />,
document.body.appendChild(document.createElement('div')),
)
})
問題なければ、変数styles
を呼ぶ時、定義したclassはIntelliSenseに表示される。
結果
結果はこんな感じになる
ここのclass名はコンパイルする度に変わる。
注意点
上記foo.scss.d.ts
の書き方だと、下記の構文でのみ読み込める
import styles from 'styles/foo.scss'
以下のexport default content
を修正すれば、別の書き方でimportできる
declare module '*.scss' {
const content: {
bar: string;
baz: string;
};
- export default content;
+ export = content;
}
import * as styles from 'styles/foo.scss'
// または
import {foo, bar} from 'styles/foo.scss'
ちょっとスマートな使い方
前述のやり方だと、1つ.scss
ファイルに1つ.d.ts
ファイルを作らなきゃいけなくなるので、スタイルファイルが多い場合は大変見づらい。
styles/
配下にindex.d.ts
を作って、先ほどstyles/foo.scss
の内容を移動すればいいと思う。
declare module 'styles/foo.scss' {
const content: {
bar: string;
baz: string;
};
export = content;
}
declare module 'styles/bar.scss' {
const content: {
baz: string;
};
export = content;
}
こう記述すると、より綺麗にまとまると思う
余談
railsのwebpackerを使う時、デフォルトはjs/tsファイルのみwatchするが、下記の記述をconfig/application.rb
に追加すれば、cssファイル(とscssファイル)もwatchしてくれる。
Webpacker::Compiler.watched_paths += %w(PATH/TO/STYLES/**/*.css PATH/TO/STYLES/**/*.scss)
詳しい使い方はここを参照してください。
参考
https://qiita.com/nullabletypo/items/d3ac5f15f2405f9ac3fd
https://stackoverflow.com/questions/40382842/cant-import-css-scss-modules-typescript-says-cannot-find-module
https://qiita.com/terrierscript/items/56d2cc15f76df50dfee7