LoginSignup
21
8

More than 1 year has passed since last update.

Laravelを使わなくても利用できるlaravel-mixでTypeScriptとSassの簡単なコンパイル環境を作ろう

Last updated at Posted at 2022-08-26

はじめに

フロントでTypeScriptやSass、テンプレートエンジンなどをコンパイルするときgulpやwebpackがよく使われます。
個人的な印象ですが、両者とも記述が複雑化しやすく長文化しやすく管理が大変そうです。
loaderの順番を気にしたり設定オプションも盛りだくさんで、時間をかけて理解しないといけないので積極的に進めたくはありません。
そこでおすすめしたいのがlaravel-mixです。

ざっくり言うとlaravel-mixはwebpackを簡単に書けるようにしたものです。
webpackを使いやすくしてくれるので当然webpackのバンドルやコンパイルなどの機能を持っています。
その名の通り「Laravel」使うんじゃないの?と思われるかもしれませんが、Laravelを使わなくてもlaravel-mixは使えます!
Laravel知らないよって人でも大丈夫です。

本記事ではlaravel-mixを使ってTypeScriptとSassをコンパイルするような環境を作っていきます。

環境を作ろう

準備

まずは練習用のディレクトリを作ってlaravel-mixのファイルを編集できるところまでやってみます。
mix-practiceというディレクトリを作ってnpm init -ypackage.josnファイルを作成します。

コマンドライン
mkdir mix-practice
cd mix-practice
npm init -y

これでlaravel-mixをインストールできるようになりました。
いざインストール!

コマンドライン
npm install laravel-mix --save-dev

インストールは開発環境だけでよいので--save-devをお忘れなく。
インストールできたらlaravel-mixを記述するファイルを作ります。
webpackのファイル名がwebpack.config.jsであるように
laravel-mixのファイル名はwebpack.mix.jsです。

コマンドライン
touch webpack.mix.js

ではこのファイルの先頭で先ほどインストールしたlaravel-mixを読み込ませておきます。

webpack.mix.js
const mix = require('laravel-mix');

ここまででディレクトリ構成はこうなってます。

ディレクトリ構成
mix-practice
├─ node_modules/
├─ package-lock.json
├─ package.json
└─ webpack.mix.js

laravel-mix編集(TypeScript)

次は実際にlaravel-mixの記述をしてみてwebpackとの違いを体験してみましょう。
ではwebpack.mix.jsに書いていきましょう。
まずはTypeScriptです。

webpack.mix.js
const mix = require('laravel-mix');

mix.setPublicPath('dist');
mix.ts('src/ts/index.ts', 'dist/js');

とりあえずこれだけです。一瞬すぎる…
.setPublicPath()でコンパイル先(公開するディレクトリ)を指定します。
.ts()の第一引数にはコンパイル元を指定します。
バンドルしたいときは配列で指定します。

mix.ts(['src/ts/index.ts', 'src/ts/sample.ts'], 'dist/js')

第二引数には出力先を指定します。
src/ts/index.tsをコンパイルしてdist/jsに出力しなさいということですね。

それではwebpack.mix.jsを実行させるためにpackage.jsonscriptsを書き換えましょう。

package.json
"scripts": {
  "build": "mix",
  "watch": "mix watch",
  "production": "mix --production"
},

これでひとまずTypeScriptをコンパイルできるところまできましたが
肝心のtypescriptやts-loaderをインストールしてません。
手動で

コマンドライン
npm install typescript ts-loader --save-dev

としてもいいのですがlaravel-mixに任せるとwebpack.mix.jsの内容読んで依存解決して自動にインストールまでしてくれます。
ということで先のスクリプトを実行してみます。

コマンドライン
npm run build

実行後に以下のように出力されて

コマンドライン
Additional dependencies must be installed. This will only take a moment.
Running: npm install ts-loader typescript --save-dev --legacy-peer-deps
Finished. Please run Mix again.

package.jsonにts-loaderとtypescriptが追加されています。
ちなみにここでPlease run Mix again.の指示通りもう一回npm run buildとしてもsrc/ts/index.tsがないのでエラーになります。

それではtsconfig.jsonindex.tsを作りましょう。
まずtsconfig.jsonを作成します。

コマンドライン
tsc --init

tsconfig.jsonの設定は触り始めたらキリがない(嘘、勉強不足で把握しきれてない)ので設定しておけば良さげなところだけをピックアップしておきます。

tsconfig.json
{
  "compilerOptions": {
    "target": "es2015",
    "lib": ["DOM", "ESNext"],
    "module": "ES2015",
    "sourceMap": true,
    "strict": true,
  }
}

次にコンパイル元のディレクトリsrc/ts/とファイルindex.tsを作成します。

ディレクトリ構成
mix-practice
├─ node_modules/
├─ src
│  └─ ts
│     └─ index.ts
├─ package-lock.json
├─ package.json
└─ webpack.mix.js
index.ts
const greet = (text: string) => {
  console.log(text);
}

greet('hello, world');

それではコンパイルしてみます。

コマンドライン
npm run build

下記が表示されれば成功です。

webpack compiled successfully

dist/js/index.jsができていることを確認しましょう。

ディレクトリ構成
mix-practice
├─ dist
│  ├─ js
│  │  └─ index.js
│  └─ mix-manifest.json
├─ node_modules/
├─ src
│  └─ ts
│     └─ index.ts
├─ package-lock.json
├─ package.json
└─ webpack.mix.js

laravel-mix編集(Sass)

次はSassです。
これも一瞬です。

webpack.mix.js
const mix = require('laravel-mix');

mix.setPublicPath('dist');
mix.ts('src/ts/index.ts', 'dist/js');
mix.sass('src/scss/style.scss', 'dist/css/style.css')
  .options({
    processCssUrls: false
  });

options({processCssUrls: false})はcssで使うbackground-image: url()などのurl()に関する設定です。

scssのコンパイル元と出力先は別の場所です。
そのため以下のようなディレクトリ構成で

root
├─ dist
│  └─ css
│     └─ style.css
└─ src
   ├─ img
   │  └─ sample.png
   └─ scss
      └─ style.scss

scssディレクトリからの相対パス記述で

style.scss
background-image: url('../img/sample.png');

のようにしてしまうとコンパイル後に

style.css
background-image: url('../images/sample.png?3a0834378861f9a4523f166fed2c0be9');

のように書き変わってしまい画像をうまく読み込めません。
そこでprocessCssUrls: falseにしておくとurl()の中身はscssに記述したままでコンパイルされます。
そのため画像はdist/imgの方にコピーするようにしましょう。

手動でコピーするのは面倒なのでこれもlaravel-mixにやってもらいます。

webpack.mix.js
const mix = require('laravel-mix');

mix.setPublicPath('dist');
mix.ts('src/ts/index.ts', 'dist/js');
mix.sass('src/scss/style.scss', 'dist/css/style.css')
  .options({
    processCssUrls: false
  });
mix.copy('src/img', 'dist/img');

これでimgディレクトリごとdistにコピーしてくれます。
あとは適当にscssファイルと画像ファイルを用意します。

style.scss
h1 {
  color: red;
  &.color-blue {
    color: blue;
  }
}
div {
  width: 100%;
  height: 250px;
  background-image: url('../img/sample.png');
}
ディレクトリ構成
mix-practice
├─ dist
│  ├─ js
│  │  └─ index.js
│  └─ mix-manifest.json
├─ node_modules/
├─ src
│  ├─ img
│  │  └─ sample.png
│ ├─ scss
│  │  └─ style.scss
│ └─ ts
│    └─ index.ts
├─ package-lock.json
├─ package.json
└─ webpack.mix.js

これでbuildしてみましょう。

コマンドライン
npm run build

最初はTypeScriptの時と同じように(未インストールの場合)sassとsass-loaderがインストールされます。
必要なパッケージが揃えばbuildができます。
コンパイルが成功すれば以下のようなディレクトリ構成になります。

ディレクトリ構成
mix-practice
├─ dist
│  ├─ css
│  │  └─ style.css
│  ├─ img
│  │  └─ sample.png
│  ├─ js
│  │  └─ index.js
│  └─ mix-manifest.json
├─ node_modules/
├─ src
│  ├─ img
│  │  └─ sample.png
│ ├─ scss
│  │  └─ style.scss
│ └─ ts
│    └─ index.ts
├─ package-lock.json
├─ package.json
└─ webpack.mix.js

確認のためにdist直下にindex.htmlを入れます。
確認だけなので最低限だけ書いてます。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="css/style.css">
  <title>Document</title>
</head>
<body>
  <h1>赤です</h1>
  <h1 class="color-blue">青です</h1>
  <div></div>
  <script src="js/index.js"></script>
</body>
</html>

ブラウザで確認して下記OKなら完了です!お疲れ様です!

  • 「赤です」が赤
  • 「青です」が青
  •  画像が表示
  •  デベロッパーツールのコンソールに「hello, world」が表示

mix-manifest.jsonについて

いつの間にかしれっとmix-manifest.jsonというファイルが出力されています。
これはファイルを変更してもキャッシュが効いてしまって反映されないというのを防ぐキャッシュ回避用のファイルです。
Laravelを使うとscriptファイル呼び出し時のmix()関数でクエリパラメータを生成してキャッシュ回避してくれるようですが
今回のようにLaravelを使わない環境だとあまり意味がない(mix-manifest.json内のファイルにクエリパラメータを追加するプログラムを作るなどしないと)ので出力自体をさせないか、gitignoreなどで対処するのがよいでしょう。
ちなみに私は出力させないように以下のような設定をしています。

webpack.mix.js
const fs = require('fs');
mix.then(() => {
    fs.unlinkSync('dist/mix-manifest.json')
  });

さいごに

larave-mixだと簡単に書けそうな感じがしたでしょうか?
今回はwebpack.mix.jsの中で記述を分けて書きましたがメソッドチェーンにして一気に書くこともできます。

webpack.mix.js
const mix = require('laravel-mix');
const fs = require('fs');

mix.setPublicPath('dist')
  .ts('src/ts/index.ts', 'dist/js')
  .sass('src/scss/style.scss', 'dist/css/style.css')
  .options({
    processCssUrls: false
  })
  .copy('src/img', 'dist/img');

mix.then(() => {
    fs.unlinkSync('dist/mix-manifest.json')
  });

laravel-mixでは他にもVueやReactなどといったフロントフレームワーク、ライブラリの他、EJSやNunjucksなどのテンプレートエンジン、ファイルの変更を監視してブラウザをホットリロードする機能(BrowserSync)、sourceMapなど色々追加できます。
これで面倒なwebpackやgulpから解放されましょう。

参照

21
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
8