はじめに
Elmで書かれたアプリケーションをSassで装飾したい。
ついでにホットリロード(以下HMR)な環境にしたい。
あると思います。
開発環境
macOS Catalina 10.15.2
docker desktop 2.1.0.5
Elm 0.19.1
なお、以下の作業は全てElmがインストールされたDockerコンテナ上で行っております。
プロジェクトの初期化
まずは開発環境上でElmがインストールされてるかを確認してみます。
$ elm --help
Hi, thank you for trying out Elm 0.19.1. I hope you like it!
バッチリですね。
プロジェクトディレクトリを作成していきましょう。
$ mkdir qiita && cd qiita
$ yarn init
$ elm init
$ ls
elm.json package.json src
ここまででプロジェクトの初期化は完了です!
依存ライブラリのインストール
yarn add
で必要なライブラリをインストールしていきます。
webpack関連
$ yarn add webpack webpack-cli webpack-dev-server -D
Babel関連
$ yarn add @babel/core @babel/preset-env babel-loader -D
必須ではないのですが、
エントリーポイントのJavaScriptにES6を使いたかったためインストールしています。
ついでに.babelrc
ファイルも追加しておきましょう。
$ touch .babelrc
{
"presets": [
"@babel/preset-env"
]
}
Sass関連
$ yarn add node-sass sass-loader css-loader style-loader -D
Elm関連
$ yarn add elm-webpack-loader elm-hot-webpack-loader -D
webpackで.elm
ファイルを処理するためにはローダーを用意する必要があります。
今回はHMRを利用したいのでそのためのローダーも追加でインストールしています。
elm-webpack-loader
elm-hot-webpack-loader
依存ライブラリのインストールは以上となります!
最後にpackage.json
にコマンドを登録しておきましょう。
{
"name": "qiita",
〜中略〜
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server"
},
〜後略〜
}
webpack.config.jsの記述
下準備が整ったところで設定ファイルを書いていきましょう!
$ touch webpack.config.js
まずは雛形を書いてみます。
const path = require('path');
const webpack = require('webpack');
module.exports = (env, arg) => {
return {
plugins: [],
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname),
},
devServer: {},
module: {
rules: []
}
}
};
ここから各種設定項目を埋めてまいります。
プラグインの追加
plugins: [
new webpack.HotModuleReplacementPlugin()
],
今回はHMRを利用したいのでプラグインを追加しています。
開発サーバの設定
devServer: {
hot: true,
stats: 'errors-only',
port: 3000,
host: '0.0.0.0',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: '/' }
]
}
},
devServer.hot
をtrue
にすることでHMRを有効化しています。
また、SPA開発時はdevServer.historyApiFallback
オプションを設定することで、
常にSPAのエントリーポイントとなるファイルを返すことが可能です。
上記の例では常にindex.html
を返すようにしています。
ローダーの設定
module: {
rules: [
{
test: /\.elm$/,
exclude: [/elm-stuff/, /node_modules/],
use: [
{ loader: 'elm-hot-webpack-loader' },
{
loader: 'elm-webpack-loader',
options: {
cwd: __dirname,
optimize: (argv.mode == 'production') ? true : false
debug: (argv.mode == 'development') ? true : false,
}
}
]
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.js$/,
exclude: [/elm-stuff/, /node_modules/],
loader: 'babel-loader'
}
]
}
.elm
ファイルを処理する際、webpackのmodeによって
Elmのビルド時にデバッグモードか最適化モードかが切り替わるよう設定しています。
また、ローダーの適用順ですが、elm-hot-webpack-loaderのドキュメントに従い、
「elm-webpack-loader」-> 「elm-hot-webpack-loader」となるようにします。
まとめ
設定は以上となります!
最後に出来上がったコードを再掲します。
const path = require('path');
const webpack = require('webpack');
module.exports = (env, argv) => {
return {
plugins: [
new webpack.HotModuleReplacementPlugin()
],
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname),
},
devServer: {
hot: true,
stats: 'errors-only',
port: 3000,
host: '0.0.0.0',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: '/' }
]
}
},
module: {
rules: [
{
test: /\.elm$/,
exclude: [/elm-stuff/, /node_modules/],
use: [
{ loader: 'elm-hot-webpack-loader' },
{
loader: 'elm-webpack-loader',
options: {
cwd: __dirname,
optimize: (argv.mode == 'production') ? true : false,
debug: (argv.mode == 'development') ? true : false,
}
}
]
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.js$/,
exclude: [/elm-stuff/, /node_modules/],
loader: 'babel-loader'
}
]
}
}
};
エントリーポイントとindex.htmlの作成
まずはindex.html
ファイルを作成しましょう。
$ touch index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
</head>
<body>
<div id="elm"></div>
<script src="/main.js"></script>
</body>
</html>
続いてエントリーポイントとなるJSファイルです。
$ touch ./src/index.js
import { Elm } from './Main.elm'
import './sass/main.scss'
Elm.Main.init({
node: document.getElementById('elm')
})
Main.elmとmain.scssの作成
$ touch src/Main.elm
module Main exposing (main)
import Html exposing (..)
import Html.Attributes exposing (..)
main =
div [ class "container" ]
[ h1 [] [ text "hello elm!!" ] ]
最後にmain.scss
ファイルを作成します。
$ mkdir src/sass
$ touch src/sass/main.scss
.container {
display: flex;
justify-content: center;
align-items: center;
h1 {
font-size: 48px;
color: #428A09;
}
}
お疲れ様でした!
全ての初期ファイルがこれで完成しました!
開発サーバの起動
それでは早速開発サーバを起動してみましょう。
$ yarn dev
Main.elm
やmain.scss
を編集すると自動的に反映される様子が分かるかと思います!
さいごに
ここまでで、プロジェクトディレクトリ下の構成は以下のようになります。
.
├── src
│ ├── Main.elm
│ ├── index.js
│ └── sass
│ └── main.scss
├── node_modules
├── elm_stuff
├── .babelrc
├── elm.json
├── index.html
├── package.json
├── webpack.config.js
└── yarn.lock
ファイル数が少ないためsrc
ディレクトリ下に.elm
も.js
も.scss
もまとめて入れてしまっていますが、
実際のプロジェクトではディレクトリ構成はもう少し工夫する必要はありそうです。
ともあれ、私達はElmとSassが使えてHMRな環境を手に入れることができました!
今年はElmも勉強してきたいです。