gulpの続きです。前回はSass(SCSS)とTypeScriptを同時にコンパイルする環境を作りました。今回はここにEJSを加えてメタ言語(HTMLテンプレートエンジン、AltCSS、AltJS)フルセットの同時コンパイル環境にてみます。それではいきましょう!
【目次】
- 前回のファイル構成
- HTMLテンプレートエンジンはEJSを選定
- EJSパッケージ(gulp-ejs他)のインストール
- gulpfile.js全体(修正前)
- gulpfile.jsを修正(EJS設定を追加)
- EJSのファイルを作成
- 動作確認(gulpタスク実行)
- gulpfile.js全体(修正後)
- 最後に
※参考:【gulp】Sass(SCSS)とTypeScriptを同時にコンパイルする環境を作る - クモのようにコツコツと
※メタ言語(HTMLテンプレートエンジン、AltCSS、AltJS)まとめ
qiita.com
前回のファイル構成
glup_frontend ├node_modules(中身は省略) ├src │├scss ││├common.scss ││└other.scss │└ts │ └common.ts ├dest │├css ││├common.css ││└other.css │├js ││└common.js │├index.html │└other.html ├gulpfile.js ├package.json ├package-lock.json └tsconfig.json
- 「src」フォルダの中のscssファイルが「dest」フォルダでcssファイルにコンパイルされる
- 「src」フォルダの中のtsファイルが「dest」フォルダでjsファイルにコンパイルされる
今回はここにHTMLテンプレートエンジンも追加したい。これでHTML、CSS、JSフルセットのメタ言語のコンパイル環境になる。
HTMLテンプレートエンジンはEJSを選定
HTMLテンプレートエンジンはこれまでPug、EJS、Markdownのコンパイルを体験した。
※参考:【HTML】PugをGulpでコンパイルしてみる(メタ言語初コンパイル!) - クモのようにコツコツと
※参考:【HTML】EJSをGulpでコンパイルしてみる(SyntaxErrorでちょい苦戦) - クモのようにコツコツと
※参考:【HTML】MarkdownをGulpでHTMLにコンパイルしてみる - クモのようにコツコツと
今回はこの中で、EJSを選定する。SCSSやTypeScriptと同様、ネイティブHTMLの書式が残る上位互換的なメタ言語。
※参考:【HTML】EJSをGulpでコンパイルしてみる(SyntaxErrorでちょい苦戦) - クモのようにコツコツと
この時は「ejs」フォルダの中のejsファイルをルート直下にindex.htmlとしてコンパイルした。今回はSass(SCSS)やTypeScriptと同様に「src」フォルダにコンパイルしたい。
EJSパッケージ(gulp-ejs他)のインストール
まずターミナルを開きcd
コマンドで「gulp_frontend」フォルダに移動する。
cd /(フォルダ)/gulp_frontend
EJSのコンパイルに必要な下記のパッケージをインストールする。
- gulp-ejs:EJSコンパイル
- gulp-rename:拡張子リネイム(.ejs→.html)
- gulp-replace:空白行削除(任意)
npm install -D gulp-ejs gulp-rename gulp-replace
成功するとpackage.jsonに追記される!
"devDependencies": { "browser-sync": "^2.26.7", "gulp": "^4.0.2", "gulp-ejs": "^5.1.0", // ←追記された! "gulp-rename": "^2.0.0", // ←追記された! "gulp-replace": "^1.0.0", // ←追記された! "gulp-sass": "^4.0.2", "gulp-typescript": "^6.0.0-alpha.1" }, "dependencies": { "@types/node": "^13.13.2", "typescript": "^3.8.3" }
gulpfile.js全体(修正前)
gulpの設定が書かれている「gulpfile.js」、前回はこうだった。
const gulp = require('gulp'); const sass = require('gulp-sass'); const typescript = require('gulp-typescript'); const browserSync = require('browser-sync'); // sassコンパイル gulp.task('sass', (done) => { gulp.src('./src/scss/*.scss') .pipe(sass({ outputStyle: 'expanded' }) ) .on("error", sass.logError) .pipe(gulp.dest('./dest/css')); done(); }); // TypeScriptコンパイル gulp.task('ts', (done) => { gulp.src('./src/ts/*.ts') .pipe(typescript()) .js .pipe(gulp.dest('./dest/js')); done(); }); // リロードするhtml gulp.task('browser-sync', (done) => { browserSync.init({ server : { baseDir : './dest/', index : 'index.html', }, }); done(); }); // リロード設定 gulp.task('browser-reload', (done) => { browserSync.reload(); done(); }); // 監視ファイル gulp.task('watch-files', (done) => { 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", gulp.task('ts')); gulp.watch("./dest/js/*.js", gulp.task('browser-reload')); done(); }); // タスク実行 gulp.task('default', gulp.series(gulp.parallel( 'watch-files', 'browser-sync', 'sass', 'ts' ), (done) => { done(); }));
- 冒頭で
gulp
、gulp-sass
、gulp-typescript
、browser-sync
を読み込んでいる gulp.task
のsass
でsass
ファイルコンパイルを設定gulp.task
のts
でts
ファイルコンパイルを設定gulp.task
のbrowser-sync
でリロードするhtmlを設定gulp.task
のbrowser-reload
でリロード設定gulp.task
のwatch-files
で監視ファイルを設定gulp.task
のdefault
で複数のタスクを同時に実行
詳細は前回の記事を参照
※参考:【gulp】Sass(SCSS)とTypeScriptを同時にコンパイルする環境を作る - クモのようにコツコツと
gulpfile.jsを修正(EJS設定を追加)
EJSのパッケージをインポート
まず冒頭で先程インストールした3つのパッケージをインポートする。
const rename = require("gulp-rename"); const ejs = require("gulp-ejs"); const replace = require("gulp-replace");
- 変数
rename
にrequire()
メソッドでgulp-rename
を読み込む - 変数
ejs
にrequire()
メソッドでgulp-ejs
を読み込む - 変数
replace
にrequire()
メソッドでgulp-replace
を読み込む
EJSのコンパイル設定
// EJSコンパイル gulp.task('ejs', (done) => { gulp.src(["./src/*.ejs", "!./src/_*.ejs"]) .pipe(ejs({}, {}, { ext: ".html" })) .pipe(rename({ extname: ".html" })) .pipe(replace(/[\s\S]*?(<!DOCTYPE)/, "$1")) .pipe(gulp.dest("./dest/")); done(); });
gulp.task()
メソッド実行。第一引数はejs
、第二引数は無名関数で引数はdone
- 無名関数の中は
gulp.src().pipe().pipe().pipe().pipe()
とチェーンになっている src()
の第一引数は「○○.ejs」ファイル、第二引数は「_○○.ejs」ファイル以外(!)- 一つ目の
pipe()
はejs()
メソッドでhtm
lにコンパイル - 二つ目のpipe()はrename()メソッドで拡張子を.htmlにリネイム
- 三つ目のpipe()はreplace ()メソッドで<!DOCTYPE〜より上の行を削除
- 四つ目のpipe()はgulp.dest()メソッドで「dest」フォルダに吐き出す
- 最後に
done()
メソッドを実行
前回と同じくreturn
を使わない書き方にしているのと、「src」や「dest」のフォルダ名を追記した。
※参考:【HTML】EJSをGulpでコンパイルしてみる(SyntaxErrorでちょい苦戦) - クモのようにコツコツと
※参考:【gulp】Sass(SCSS)とTypeScriptを同時にコンパイルする環境を作る - クモのようにコツコツと
監視ファイルにEJSを追加
gulp.watch()
の常時監視にEJSの設定を追加
// 監視ファイル gulp.task('watch-files', (done) => { gulp.watch("./src/*.ejs", 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", gulp.task('ts')); gulp.watch("./dest/js/*.js", gulp.task('browser-reload')); done(); });
gulp.watch()
メソッドに.ejs
ファイルのパスとejs
タスクを追加
タスクの同時実行にEJSを追加
最後にタスクを同時に実行するdefault
タスクにEJSコンパイルのタスクを追加する。
// タスク実行 gulp.task('default', gulp.series(gulp.parallel( 'watch-files', 'browser-sync', 'ejs', 'sass', 'ts' ), (done) => { done(); }));
gulp.series()
メソッドのgulp.parallel()
の中にejs
を追加する。
これで動くか、「dest」フォルダにEJSファイルを作ってみる。
EJSのファイルを作成
「src」フォルダの中にejsファイルを作る
glup_frontend ├node_modules(中身は省略) ├src │├scss ││├common.scss ││└other.scss │└ts ││└common.ts │├index.ejs // 追加 │└other.ejs // 追加 ├dest │├css ││├common.css ││└other.css │├js ││└common.js │├index.html │└other.html ├gulpfile.js ├package.json ├package-lock.json └tsconfig.json
- 「src」フォルダの中に「index.ejs」と「other.ejs」を作る
これでようやく「src」と「dest」フォルダが全く同じファイル構成になった!
index.ejsの内容
最初にTopページ「index.ejs」。前回の「index.html」をベースにする。
<% var h1Title = 'メタ言語同時コンパイル(EJS、Sass(SCSS)、TypeScript)'; %> <!doctype html> <html> <head> <meta charset="UTF-8"> <title><%= h1Title %></title> <link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/other.css"> <script src="js/common.js"></script> </head> <body> <section id="scss"> <h1><%= h1Title %></h1> <p class="lede">CodepenのSettingの旅CSS編第2回。今回はSCSS。LESSに似てる?</p> <section id="nest"> <h2>ネスト(階層化)</h2> <p>SCSSもdivのネストの階層化ができる。この段落は<em>ネスト</em>でスタイルを当てている。<br> ん?この書き方はLESSとほぼまったく同じだ。<br> <span class="bikou">インデントについても厳密でじゃでなくても解釈してくれるようだ(?)</span> </p> </section> <section id="oya"> <h2>親セレクタの参照</h2> <p>おそらくLESSにはないSCSS専用の機能。ネストして「&」に擬似要素を付けると親セレクタを参照できる<br> <span class="bikou">この尾行欄につけている「※」印は「.bikou:before」ではなく「&:before」だけで済んでいる。 </span> </p> </section> <section id="oya"> <h2>TypeScriptで書いたクリックイベント</h2> <button id="btn">ここ押せワンワン</button> </section> <p><a href="other.html">別ページへ</a></p> </section> </body> </html>
- 変数
h1Title
でh1タグに入れたいテキストを設定 - h1タグに
h1Title
を配置
変更点はh1タグを変数h1Title
にしている部分。
※参考:【gulp】Sass(SCSS)とTypeScriptを同時にコンパイルする環境を作る - クモのようにコツコツと
other.ejsの内容
次に別ページ「other.ejs」。前回の「other.html」とEJSでフィズバズのfor文をミックスしている。
<% var h1Title = '別ページ:EJSでフィズバス'; %> <% var h2Title = 'EJSでフィズバズる'; %> <% var count = 30; %> <!doctype html> <html> <head> <meta charset="UTF-8"> <title><%= h1Title %></title> <link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/other.css"> <script src="js/common.js"></script> </head> <body> <section id="scss"> <h1><%= h1Title %></h1> <p>別ページもリロードされるかテストですと。</p> <section> <h2 class="oya"><%= h2Title %></h1> <p>EJSで変数、for文、if文を使ってフィズってバズってみた。</p> <ul> <% for (var i = 1; i < count+1; i++) { %> <% if (i % 3 == 0 && i % 5 == 0) { %> <li>フィズってバズった!</li> <% } else if (i % 3 == 0) { %> <li>フィズった!</li> <% } else if (i % 5 == 0) { %> <li>バズった!</li> <% } else { %> <li><%= i %></li> <% } %> <% } %> </ul> </section> <p class="lede"><a href="/">Topへ</a></p> </section> </section> </body> </html>
※参考:【gulp】Sass(SCSS)とTypeScriptを同時にコンパイルする環境を作る - クモのようにコツコツと
※参考:【HTML】テンプレートエンジンEJSでFizzBuzzる!(Pugとの比較あり) - クモのようにコツコツと
動作確認(gulpタスク実行)
index.ejs→index.htmlコンパイル
それでは挙動を確認しよう。gulpタスク実行!
npx gulp
おお!ブラウザが立ち上がった!
http://localhost:3000/
h1タグが先程の変数のテキスト「メタ言語同時コンパイル(EJS、Sass(SCSS)、TypeScript)」になっている。
コンパイルされた「index.html」のコード
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>メタ言語同時コンパイル(EJS、Sass(SCSS)、TypeScript)</title> <link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/other.css"> <script src="js/common.js"></script> </head> <body> <section id="scss"> <h1>メタ言語同時コンパイル(EJS、Sass(SCSS)、TypeScript)</h1> <p class="lede">CodepenのSettingの旅CSS編第2回。今回はSCSS。LESSに似てる?</p> <section id="nest"> <h2>ネスト(階層化)</h2> <p>SCSSもdivのネストの階層化ができる。この段落は<em>ネスト</em>でスタイルを当てている。<br> ん?この書き方はLESSとほぼまったく同じだ。<br> <span class="bikou">インデントについても厳密でじゃでなくても解釈してくれるようだ(?)</span> </p> </section> <section id="oya"> <h2>親セレクタの参照</h2> <p>おそらくLESSにはないSCSS専用の機能。ネストして「&」に擬似要素を付けると親セレクタを参照できる<br> <span class="bikou">この尾行欄につけている「※」印は「.bikou:before」ではなく「&:before」だけで済んでいる。 </span> </p> </section> <section id="oya"> <h2>TypeScriptで書いたクリックイベント</h2> <button id="btn">ここ押せワンワン</button> </section> <p><a href="other.html">別ページへ</a></p> </section> </body> </html>
h1タグはプレーンテキストになっている。ただ、冒頭の変数設定を書いていた部分の行が開いているんだよなー。やはり「gulp-replace」の行削除設定が効いていないっぽい。
other.ejs→other.htmlのコンパイル
次に別ページ「other.html」も見てみる。
http://localhost:3000/other.html
おお!フィズバズになってる!
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>別ページ:EJSでフィズバス</title> <link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/other.css"> <script src="js/common.js"></script> </head> <body> <section id="scss"> <h1>別ページ:EJSでフィズバス</h1> <p>別ページもリロードされるかテストですと。</p> <section> <h2 class="oya">EJSでフィズバズる</h1> <p>EJSで変数、for文、if文を使ってフィズってバズってみた。</p> <ul> <li>1</li> <li>2</li> <li>フィズった!</li> <li>4</li> <li>バズった!</li> <li>フィズった!</li> <li>7</li> <li>8</li> <li>フィズった!</li> <li>バズった!</li> <li>11</li> <li>フィズった!</li> <li>13</li> <li>14</li> <li>フィズってバズった!</li> <li>16</li> <li>17</li> <li>フィズった!</li> <li>19</li> <li>バズった!</li> <li>フィズった!</li> <li>22</li> <li>23</li> <li>フィズった!</li> <li>バズった!</li> <li>26</li> <li>フィズった!</li> <li>28</li> <li>29</li> <li>フィズってバズった!</li> </ul> </section> <p class="lede"><a href="/">Topへ</a></p> </section> </section> </body> </html>
ソースを見ると、やはり行削除の設定が効いていないなー。やはり「gulp-replace」が動いてない。これについては改めて検証したい。
Sass(SCSS)→CSSコンパイル
念のためSass(SCSS)の修正をしてみる。
srcフォルダの「common.css」のh2タグを
#nest, #oya { background: #fff; padding: 20px; margin: 0 0 20px; h2 { color: brown; font-size: 1.5em; line-height: 1.2; } /* 中略 */ }
茶色から紫にすると…
#nest, #oya { background: #fff; padding: 20px; margin: 0 0 20px; h2 { color: purple; /* ←修正 */ font-size: 1.5em; line-height: 1.2; } /* 中略 */ }
おお、自動リロードで紫になった!
destフォルダの「common.css」もコンパイルされている!
#nest h2, #oya h2 { color: purple; font-size: 1.5em; line-height: 1.2; }
TypeScript→JSコンパイル
srcフォルダの「common.ts」も修正しする。
/* アロー関数 */ const hellow = () => { window.alert('hellow TypeScript!!!!!!!!!!'); window.alert('こんにちは、型スクリプト'); window.alert(title + 'は第' + num + '回です。'); window.alert('おしまい'); }
1個目のアラートの「!」を「?」にしてみる。
/* アロー関数 */ const hellow = () => { window.alert('hellow TypeScript??????????'); // 修正 window.alert('こんにちは、型スクリプト'); window.alert(title + 'は第' + num + '回です。'); window.alert('おしまい'); }
ボタンを押すと、アラートのテキストも変わった!
destフォルダの「common.js」もコンパイルされている!
/* アロー関数 */ var hellow = function () { window.alert('hellow TypeScript??????????'); window.alert('こんにちは、型スクリプト'); window.alert(title + 'は第' + num + '回です。'); window.alert('おしまい'); };
よし!これでHTML、CSS、JSの全てのメタ言語が同時コンパイルされる環境が作れた!
gulpfile.js全体(修正後)
最終的にこうなった。
const gulp = require('gulp'); const rename = require("gulp-rename"); const ejs = require("gulp-ejs"); const replace = require("gulp-replace"); const sass = require('gulp-sass'); const typescript = require('gulp-typescript'); const browserSync = require('browser-sync'); // EJSコンパイル gulp.task('ejs', (done) => { gulp.src(["./src/*.ejs", "!./src/_*.ejs"]) .pipe(ejs({}, {}, { ext: ".html" })) .pipe(replace(/[\s\S]*?(<!DOCTYPE)/, "$1")) .pipe(replace("EJS", "EJS")) .pipe(gulp.dest("./dest/")); done(); }); // sassコンパイル gulp.task('sass', (done) => { gulp.src('./src/scss/*.scss') .pipe(sass({ outputStyle: 'expanded' }) ) .on("error", sass.logError) .pipe(gulp.dest('./dest/css')); done(); }); // TypeScriptコンパイル gulp.task('ts', (done) => { gulp.src('./src/ts/*.ts') .pipe(typescript()) .js .pipe(gulp.dest('./dest/js')); done(); }); // リロードするhtml gulp.task('browser-sync', (done) => { browserSync.init({ server : { baseDir : './dest/', index : 'index.html', }, }); done(); }); // リロード設定 gulp.task('browser-reload', (done) => { browserSync.reload(); done(); }); // 監視ファイル gulp.task('watch-files', (done) => { gulp.watch("./src/*.ejs", 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", gulp.task('ts')); gulp.watch("./dest/js/*.js", gulp.task('browser-reload')); done(); }); // タスク実行 gulp.task('default', gulp.series(gulp.parallel( 'watch-files', 'browser-sync', 'ejs', 'sass', 'ts' ), (done) => { done(); }));
最後に
ということで、ついにフルセットのメタ言語コンパイル環境ができましたー。EJS環境は前回の前回のTypeScriptに比べるとスムーズに作れたと思います。
ただ、改行を詰める「gulp-replace」が動いていないようなので、ちょっと検証しています。これによって正規表現についても詳しくなれそうなので、「補講編」的な感じにまた別の記事に分けて書いてみたいと思います。
それではまた!
※メタ言語(HTMLテンプレートエンジン、AltCSS、AltJS)まとめ
qiita.com