【laravel】laravel mixのwebpack.mix.jsの書き換えを省略したい!
初書:2021/1/13
laravel : v8.21.0
php : 7.4.14
接続用リンク:素のPHPしか触ってなかった人がlaravelを触ってみる - Qiita
before -> 【laravel】laravel mixを使ってみる
前書き
前回、laravel mixを一通り(?)触ってみた。それで思ったことが一つ。
「ファイルを生成する度にwebpack.min.jsを書き換えないといけないんですか?」
答えはおそらくyesであり、軽く調べても出てこないということはおそらくそういうことだろう。
もしかしたらこの時点でもしかしたら使い方を間違えているかもしれない、でも間違いに気づくには誰かに聞くしかない
・・・という事で、webpack.min.jsのファイル追加を自動化します。
ファイル一覧を取得する
方法は簡単。フォルダ内のファイルを取得し、順番にmixに投げていけばいい。
という事でまずはファイル一覧を取得してみる。
webpack.min.jsの実行環境はnodeなので、nodeで検索。
Node.jsで高速にファイル一覧を取得するfs.readdirのwithFileTypesオプション - Qiita
fs
を使用すれば良さそう?
という事で、今回は「fs.readdirのwithFileTypesオプションを使った判定方法」に記述してあるshowFiles関数をそのままお借りします。いや、多少不便な所があるのでそこだけ書き換えます。
const showFiles = (dirpath, callback, adddirpath = "") => {
const dirents = fs.readdirSync(dirpath, { withFileTypes: true });
for (const dirent of dirents) {
const fp = path.join(dirpath, dirent.name);
if (dirent.isDirectory()) {
showFiles(fp, callback, adddirpath + "/" + dirent.name);
} else {
callback(fp, adddirpath);
}
}
};
引数adddirpath
の追加と同期処理化です。
adddirpath
は元々の階層からの相対位置を保持しておきます。
同期は後ほど使うmix関数が非同期だと上手くいかないからです。
mixに投げていく
単純に投げるだけではエラーが出るので(mixは一度しか呼べなさそう)、
状態を変数で持っておき、順番に呼び出していく方法をとる事にする。
let mixvar = mix;
dirlist.forEach((e) => {
showFiles("resources/" + e.type, (filename,adddirpath) => {
mixvar = mixvar[e.type](filename, "public/" + e.dir + adddirpath);
});
});
少し面倒なことをしているので、順番に説明。
まずshowFilesの第一引数は、例えばcssならresources/css
となるような形の値。eは後ほど書きます。
第二引数はファイル名がコールバック関数です。
コールバック関数内では、先ほど用意したmixverの関数を呼び出します。が、拡張子によって分けないといけないので、単純にmix.css
やmix.js
のような書き方はできない。そのため、配列型式でmix[css]
やmix[js]
という形で呼び出します。これでも呼び出せるのがjsのいい所(だと思う)。
そして引数には普通に元々のファイル名と出力先ディレクトリです。showFiles
の時にadddirpath
を追加したのは、例えばresources/css/auth/auth.css
の出力先がpublic/css/auth/auth.css
という感じで、階層を同じにするためにメモしていました。
とこんな感じで軽く説明しましたが、肝心のdirlist
(e)の説明です。
設定の例はこんな感じ。
const dirlist = [
{ type: "css", dir: "css" },
{ type: "less", dir: "css" },
{ type: "js", dir: "js" },
{ type: "ts", dir: "js" },
];
dirlist
自体は配列で、1要素はtype
とdir
の要素をもったオブジェクトです。
type
はresources
内のフォルダ名兼拡張子です。なので、拡張子とフォルダ名が一致していない場合は書き換えが必要です。
dir
はpublic
内のフォルダ名です。出力先。
このオブジェクトを、自身が使っている言語の数だけ増やしたり減らしたりします。
完成
出来上がったコードがこちら。
const mix = require("laravel-mix");
const fs = require("fs");
const path = require("path");
const dirlist = [
{ type: "css", dir: "css" },
{ type: "less", dir: "css" },
{ type: "js", dir: "js" },
{ type: "ts", dir: "js" },
];
const showFiles = (dirpath, callback, adddirpath = "") => {
const dirents = fs.readdirSync(dirpath, { withFileTypes: true });
for (const dirent of dirents) {
const fp = path.join(dirpath, dirent.name);
if (dirent.isDirectory()) {
showFiles(fp, callback, adddirpath + "/" + dirent.name);
} else {
callback(fp, adddirpath);
}
}
};
let mixvar = mix;
dirlist.forEach((e) => {
showFiles("resources/" + e.type, (filename,adddirpath) => {
mixvar = mixvar[e.type](filename, "public/" + e.dir + adddirpath);
});
});
mixvar.version(); // 任意
これで、ファイル(言語を増やす場合は別)を増やしても特に書き換えする必要なくコンパイルしてくれます。
終わりに
ところでlaravel mixって一度実行すると全てのファイルを再コンパイルする?そんなことはない?
もう少し色々と探ってみますか、、
その他参考サイト
特定ディレクトリ配下のファイルのみ(またはディレクトリのみ)を取得(Node.js v10.10以降版) - Qiita
Discussion