メタ言語の続きです。前回はimageminを使ってメタ言語コンパイル環境で画像圧縮も実行しました。今回はgulpfile.jsの中のgulp.task()をgulp4で推奨されている関数の形に変更します。その他にもいくつかリファクタリングしました。それではいきましょう!
【目次】
- 前回のおさらい
- package.jsonのnpm scriptに追記
- TypeScriptのJSONファイルのインポート部分を修正
- ファイルのパスを変数化
- gulp.task()を関数化
- 関数をタスク化
- 監視ファイル
- タスク実行
- 動作確認
- 最後に
※参考:前回記事
【gulp-imagemin】メタ言語コンパイル環境で画像圧縮も実行する - クモのようにコツコツと
※参考:【メタ言語】HTMLテンプレートエンジン、AltCSS、AltJSのまとめ
qiita.com
前回のおさらい
「dest/img」フォルダに圧縮された画像が書き出される。
imageminというパッケージを使っている。詳細は前回の記事を参照
※参考:【gulp-imagemin】メタ言語コンパイル環境で画像圧縮も実行する - クモのようにコツコツと
メタ言語環境でこれまで実現したことはこちらのまとめを参照
※参考:qiita.com
今回は機能の追加は行わないがgulpの設定ファイルである「gulpfile.js」を中心にコードのリファクタリングを行う。
package.jsonのnpm scriptに追記
これまで、gulpを起動するときに下記のnpx
コマンドを打っていた。
$ npx gulp
こちらの記事を参考に、起動コマンドの種類を増やしてみる。
※参考:npm run で任意のコマンドを実行する (npm run/start) | まくまくNode.jsノート
package.json
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", "gulp": "gulp", // 追加 "start": "gulp" // 追加 },
gulp
キーを追加(値はgulp
)start
キーを追加(値はgulp
)
gulp
キーを追加することによって下記のコマンドでも起動できるようになった!
$ npm run gulp
start
キーを追加することによって下記のコマンドでも起動できるようになった!
$ npm start
TypeScriptのJSONファイルのインポート部分を修正
前回TypeScriptからJSONファイルを読み込めるようにしたが、よく見たら警告(Warning)が出てた。
Should not import the named export 'unsei' (imported as 'Unsei') from default-exporting module (only default export is available soon)
名前付きエクスポート 'unsei'( 'Unsei'としてインポート)をdefault-exportingモジュールからインポートしないでください(デフォルトのエクスポートのみがまもなく利用可能になります)
はて、名前付きエクスポート?デフォルトエクスポート?今回インポートしているのはJSONファイルなのだが。
「kekka.ts」修正前
import * as Unsei from "../../../json/unsei.json";
「kekka.ts」修正後
import Unsei from "../../../json/unsei.json";
ひとまず* as
をなくしたら警告は出なくなった。
なお、tsのモジュールをインポートする際には名前付きでエクスポートした方がいいようだ(デフォルトだとインポート時に名前をどうにでも変えられちゃうため)
※参考:なぜ default export を使うべきではないのか? - LINE ENGINEERING
※参考:ES modulesのexport defaultは使わないほうがよい - Islands in the byte stream
※参考:Avoid Export Default - TypeScript Deep Dive 日本語版
ファイルのパスを変数化
gulpの各タスクの中にいろいろなファイルのパスがあるが、見通しが悪いのと重複があるため、取り出して変数化した。
こちらはコンパイル前の「src」フォルダのパス
// ファイルパス:コンパイル前 const srcJsonFiles = './src/json/**/*.json'; const srcDataJson = './src/json/data.json'; const srcEjsFiles = './src/ejs/**/*.ejs'; const srcEjsPartial = '!./src/ejs/**/_*.ejs'; const srcScssFiles = './src/scss/**/*.scss'; const srcTsFiles = './src/ts/**/*.ts'; const srcImgFiles = './src/img/**/*' const srcImgFileType = '{jpg,jpeg,png,gif,svg}';
こちらはコンパイル後の「dest」フォルダのパス
// ファイルパス:コンパイル後 const destDir = './dest/'; const destHtmlFiles = './dest/*.html'; const destIndexHtml = 'index.html'; const destCssDir = './dest/css'; const destCssFiles = './dest/css/*.css'; const destJsDir = './dest/js'; const destJSFiles = './dest/js/*.js'; const destImtDir = './dest/img'; const destImgFiles = './dest/img/*';
各タスクの中パスは変数に置き換えている。
これで今後、ファイル名やフォルダ名などが修正になる場合もメンテがしやすくなる。
gulp.task()を関数化
gulp.task()はgulp4では非推奨
以前、こちらにも書いたが、gulp.task()
はgulp4から非推奨になっている。
※参考:【HTML】MarkdownをGulpでHTMLにコンパイルしてみる - クモのようにコツコツと
今のところまだ使えるが将来に備えてgulp4で推奨されている関数の形に変えたい。
gulpのドキュメント
※参考:Async Completion | gulp.js
その他参考にした記事
※参考:絶対つまずかないGulp 4入門(2019年版) - インストールとSassを使うまでの手順 - ICS MEDIA
※参考:gulp4再入門 gulpfileの分割とnodeモジュールの利用 - Qiita
※参考:【自分備忘録】gulp4まとめ(ざっくり) - Qiita
※参考:【gulp4】もう迷わないgulpfile.jsの書き方|Kohei|note
EJSコンパイル
修正前
// EJSコンパイル gulp.task('ejs', (done) => { const data = JSON.parse(fs.readFileSync('./src/json/data.json')); gulp.src(["./src/ejs/**/*.ejs", "!./src/ejs/**/_*.ejs"]) .pipe(plumber()) .pipe(ejs(data)) .pipe(ejs({}, {}, { ext: ".html" })) .pipe(rename({ extname: ".html" })) .pipe(replace(/^[ \t]*\n/gmi, "")) .pipe(gulp.dest("./dest/")); done(); });
修正後
// EJSコンパイル const compileEjs = (done) => { const data = JSON.parse(fs.readFileSync(srcDataJson)); gulp.src([srcEjsFiles, srcEjsPartial]) .pipe(plumber()) .pipe(ejs(data)) .pipe(ejs({}, {}, { ext: '.html' })) .pipe(rename({ extname: '.html' })) .pipe(replace(/^[ \t]*\n/gmi, '')) .pipe(gulp.dest(destDir)); done(); };
gulp.task()
を変数compileEjs
に変更(中身はアロー関数)- パスの部分を先ほどの変数に置き換え
基本的にはこの形式で修正している。関数名は冒頭に設定しているインポート系の変数名とかぶらないよう変えている。
関数化はもう一つgulp.src()
の前にreturn
を入れる方法もある。こちらはコールバックのdone()
は不要。
const 関数名 = () => { return gulp.src(パス) .pipe(処理); .pipe(処理); .pipe(処理…); };
しかしこの形では動かない処理もあったため、今回はより汎用的なdone()
を使う形で統一した。
Sass(SCSS)コンパイル
Sass(SCSS)ファイルをコンパイルしてCSSファイルにする部分。
修正前
// sassコンパイル gulp.task('sass', (done) => { gulp.src('./src/scss/**/*.scss') .pipe(sass({ outputStyle: 'expanded' }) ) .on("error", sass.logError) .pipe(gulp.dest('./dest/css')); done(); });
修正後
// sassコンパイル const compileSass = (done) => { gulp.src(srcScssFiles) .pipe(sass({ outputStyle: 'expanded' }) ) .on('error', sass.logError) .pipe(gulp.dest(destCssDir)); done(); };
webpackのバンドル
TypeScriptのファイルをWebpackでバンドルしJSファイルにする部分。
修正前
// webpackのバンドル実行 gulp.task("webpack", (done) => { webpackStream(webpackConfig, webpack) .pipe(gulp.dest("./dest/js")); done(); });
修正後
// webpackのバンドル実行 const bundleWebpack = (done) => { webpackStream(webpackConfig, webpack) .pipe(gulp.dest(destJsDir)); done(); };
リロードするhtml
browserSyncでリロードするHTMLファイル(index.html)を指定
修正前
// リロードするhtml gulp.task('browser-sync', (done) => { browserSync.init({ server : { baseDir : './dest/', index : 'index.html', }, }); done(); });
修正後
// リロードするhtml const reloadFile = (done) => { browserSync.init({ server : { baseDir : destDir, index : destIndexHtml, }, }); done(); };
リロード設定
browserSyncでリロードを行う設定
修正前
// リロード設定 gulp.task('browser-reload', (done) => { browserSync.reload(); done(); });
修正後
// リロード設定 const reloadBrowser = (done) => { browserSync.reload(); done(); };
画像圧縮
前回追加した画像を圧縮する設定
修正前
// 画像圧縮 gulp.task('imagemin', (done) => { gulp.src('./src/img/**/*.{jpg,jpeg,png,gif,svg}') .pipe(imagemin( [ pngquant({ quality: '65-80', speed: 1 }), mozjpeg({ quality: 80 }), imagemin.svgo(), imagemin.gifsicle() ] )) .pipe(gulp.dest('./dest/img')); done(); });
修正後
// 画像圧縮 const minifyImage = (done) => { gulp.src(srcImgFiles + srcImgFileType) .pipe(imagemin( [ pngquant({ quality: '65-80', speed: 1 }), mozjpeg({ quality: 80 }), imagemin.svgo(), imagemin.gifsicle() ] )) .pipe(gulp.dest(destImtDir)); done(); };
関数をタスク化
こちらは今回初めて書く処理。これまでの関数をタスク化する設定。
// タスク化
exports.compileEjs = compileEjs;
exports.compileSass = compileSass;
exports.bundleWebpack = bundleWebpack;
exports.reloadFile = reloadFile;
exports.reloadBrowser = reloadBrowser;
exports.minifyImage = minifyImage;
exports.タスク名 = 関数名
という形式で関数をタスク化する
監視ファイル
gulp.watch()
で監視するファイルを指定する部分
修正前
// 監視ファイル gulp.task('watch-files', (done) => { gulp.watch(["./src/ejs/**/*.ejs", "./src/json/**/*.json"], gulp.task('ejs')); gulp.watch("./dest/*.html", gulp.task('browser-reload')); gulp.watch("./src/scss/**/*.scss", gulp.task('sass')); gulp.watch("./dest/css/*.css", gulp.task('browser-reload')); gulp.watch(["./src/ts/**/*.ts", "./src/json/**/*.json"], gulp.task('webpack')); gulp.watch("./dest/js/*.js", gulp.task('browser-reload')); gulp.watch("./src/img/**/*", gulp.task('imagemin')); gulp.watch("./dest/img/*", gulp.task('browser-reload')); done(); });
修正後
// 監視ファイル const watchFiles = (done) => { gulp.watch([srcEjsFiles, srcJsonFiles], compileEjs); gulp.watch(destHtmlFiles, reloadBrowser); gulp.watch(srcScssFiles, compileSass); gulp.watch(destCssFiles, reloadBrowser); gulp.watch([srcTsFiles, srcJsonFiles], bundleWebpack); gulp.watch(destJSFiles, reloadBrowser); gulp.watch(srcImgFiles, minifyImage); gulp.watch(destImgFiles, reloadBrowser); done(); };
gulp.task()
を関数化する部分はこれまでと同じgulp.watch()
の第二引数がタスク名(関数名)だけでよくなる
タスク実行
最後のタスク実行はこれまでの関数化と形がちょっと違う。
修正前
// タスク実行 gulp.task('default', gulp.series(gulp.parallel( 'watch-files', 'browser-sync', 'ejs', 'sass', 'webpack', 'imagemin' ), (done) => { done(); }));
修正後
// タスク実行 exports.default = gulp.series( watchFiles, reloadFile, compileEjs, compileSass, bundleWebpack, minifyImage );
exports.default
を定義するgulp.series()
の中身はタスク名(関数名)だけでいい
なお、gulp.series()
の中身は関数名だけにしたが、並列処理にしたい場合はgulp.parallel()
に入れてもいい。
※参考:Gulp - v4 の series と parallel を使って直列・並列処理を制御する - 22時に寝ようと思って2時に寝る。
動作確認
gulpを起動してみる。
$ npm start
localhostの3000でブラウザが起動する! メタ言語や画像に変更を加えるとコンパイルを実行し、修正が反映される。
修正内容(GitHub)
※参考:gulp.task()を関数化、他 · ryo-i/frontendMetaLanguage@f20f5f8 · GitHub
プレビュー画面(GitHab Pages)
※参考:メタ言語同時コンパイル(EJS、Sass(SCSS)、TypeScript)
最後に
ということで、gulp.task()
の関数化をはじめ、いろいろリファクリングしました。細かいところですが、クオーテーションもシングル' '
とダブル" "
が混在していたので、シングルクオーテーションで統一しました。だいぶコードの処理内容が見やすくなったと思います!
次は、この内容をベースに新しいリポジトリにクローンして、メタ言語のフロントエンド開発環境のスタートキットみたいのを作りたく思います。(ここ最近ずっとやりたかったこと、ようやく!w)
それではまた!
※参考:【メタ言語】HTMLテンプレートエンジン、AltCSS、AltJSのまとめ
qiita.com