※(追記) 2017年に投稿した記事なので 「当時はコレで動きました。」 という話です。
※ これからgulp
の本格導入を考えてる場合は、アテにしない方が良いかもです。
※(追記) gulp4.0.2でタスクを書く場合は、こちらもご参照下さい。
https://qiita.com/DaisukeNishi/items/625419cf6ad36993a7f2
はじめに
IDOMアドベントカレンダー(12日目)に投稿しています。
https://qiita.com/advent-calendar/2017/idom-engineer
初心者向け、gulp+Handlebars.jsを使って効率的に静的なhtmlを作る方法を書きます。
序盤の初期設定などは、既にnpmをお使いの皆さんはご存知かと思いますので、
飛ばして読んだ方が良いかと思います。(また、Macでの制作前提です。)
イマドキ gulp
…? Webpack
や Vite
を使わない理由は?
設定ファイルをゴリゴリかくようなタスクランナーは、需要がないかもしれないですが、
Webpack
を使わない理由はエントリーポイントがJSではないためです。
静的なhtml
を組み立てるだけであれば gulp
で良いと思います。
WEB制作で node.js
を使いはじめる瞬間に
- 「コレ
Apache
じゃないからSSI
使えない。困ったな」 - 「テキストは、
html
と分けてバインディングしたい」 - 「最終的に
html
で納品しなければならない」
みたいな人には、まだ使えると思います。
- SPAで作りたい?
それはまた違う記事をご参照下さいませ。
htmlテンプレートエンジンにあえて、handlebars
をあえて使う理由は?
Github の stars はpug
の方が多いのですが、
npmtrends
では handlebars
の方が多いです。
handlebars.js
で日本語サイトを検索した感じでは
マイナーなライブラリの扱いでしたが、
グラフでみるとメジャーなテンプレートエンジンのようです。
gulp
だと特に追加のインストールも不要です。
http://www.npmtrends.com/handlebars-vs-jade-vs-pug-vs-ejs-vs-hogan.js-vs-mustache-vs-jsrender
ejs
よりとっつきやすく pug
より覚えるのが億劫でないと思います。
- ↓しばらく初期設定が続きます。
(スキップ可)Gitリポジトリを作る。
作成方法は人それぞれですが、
- Githubに
frontend
というリポジトリを作ってgit clone
する
または
-
git init
で local にfrontend
というリポジトリを作って$ git remote add
termminal
cmd
がまったく分からない場合は
SOURCETREE
を使って作れば良いです
https://www.sourcetreeapp.com/
それについての説明は省略します。
(※ gitに置かない選択肢がないと思うので、記載)
- 作成
touch .gitignore
- 記述
/node_modules
/dist
と.gitignore
に書いておいてください。
.gitignore
の参考リンク:
https://qiita.com/inabe49/items/16ee3d9d1ce68daa9fff
これの意味:
ライブラリやコンパイル後のファイルは、commit
する必要がないです。
(スキップ可)Gulpを使う前の下準備
Homebrew のインストール(Mac)
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Nodebrew(node.js:パッケージ/バージョン管理)
$ brew install nodebrew
nvm
や docker
が使う場合は、それでも良い。
たまにパーミッションの問題がありまして、
無いと動かない人も居るため、先に mkdir
しておく。(8.3.0の箇所を打ちかえる)
$ mkdir .nodebrew/src/v8.3.0
node.jsのバージョンを指定してインストールするやり方
(8.3.0の箇所は、使いたいバージョンに打ちかえる)
※2024年現在 Node.js
は v22 が最新ですが、
gulp3〜4系全盛期の Node.jsのバージョンは、ひとケタです。
最新で動かない場合は、あえてバージョンを下げた方が良いです。
$ nodebrew install-binary 8.3.0
最新版node.jsインストールのやり方
$ nodebrew install-binary latest
インストールされたバージョンを一覧で見る
$ nodebrew list
使うバージョンをuse〇〇で選ぶ、(8.3.0の箇所を打ちかえる)
$ nodebrew use v8.3.0
もう一度、一覧をみる。current:に使うモノが選ばれている状態
$ nodebrew list
下記「パスを通す」。
パスを通すとは、ターミナル開くたびにやらなくて良くする事。
「環境変数?パスを通す?」と思って、
bash
や zsh
について調べ始めると、奥が深いので、つまづきポイントになります
最初は「おまじない」と覚えて、後から勉強しましょう。
touch .bashrc
#!/bin/bash
export PATH=$HOME/.nodebrew/current/bin:$PATH
$ source ~/.bashrc
※ 最近は bash ではなく zsh が標準的に使われています。
(スキップ可)プロジェクトに移動する
ターミナルを開いて
$ cd frontend
$ pwd
結果が
/Users/YourName/frontend
となっていれば良いです。
(スキップ可)npmの初期設定
プロジェクトを作る
次に $npm init
コマンドを打ってください。
これは「このプロジェクトの初期化」の意味です。
Package.json
という初期設定ファイルができていればOK。
他人のリポジトリを落としてきたりして、
既にこのファイルがある場合は npm init
をしなくて良いです。
npm init
は対話形式なので、聞かれたとおり素直に、適当に、答えたら大丈夫です。
$ npm init
name: (hoge) hoge
version: (0.0.0)
description:
entry point: (index.html)
test command:test
git repository:frontend
keywords:fuga
author: hoge
license: (BSD) MIT
正確に答えておいた方がもちろん良いと思います。
これくらい適当でも「動かないことはない」。
(↑ここまでが初期設定でした。)
handlebars.js
htmlの元となるファイル(テンプレート)を、
handlebars.js
形式で用意します。
ファイル名は .hbs
とします。
ディレクトリを作りたい構造にファイルを配置します。
下記の例では src
フォルダで
pc
とsp
のソースをウェブサーバーで表示する際の
ディレクトリ構造と一緒の構造で入れておき、
書き出した時に
/dist/pc/
と/dist/sp/
に仕分けされて保存されるようにしたものです。
最初から /pc/
と/sp/
に分けて作り始めると、
後で修正する際、行ったり来たり修正をしなければならず、
クライアントによってはすごく面倒です。
【ファイル&ディレクトリ構成】
frontend
├ .git
├ .gitignore
├ package.json
├ package-lock.json
├ gulpfile.js
├ gulptask
│ ├ assemble_pc.js
│ ├ assemble_sp.js
│ ├ copy.js
│ ├ watch.js
│ └ webserver.js
│
├ src
│ ├ asset
│ │ ├css
│ │ ├images
│ │ └js
│ │
│ ├ data
│ │ └data.json
│ │
│ ├ doc
│ │ ├pages1
│ │ │├index.pc.hbs
│ │ │└index.sp.hbs
│ │ ├pages2
│ │ │├index.pc.hbs
│ │ │└index.sp.hbs
│ │ └pages3
│ │ ├index.pc.hbs
│ │ └index.sp.hbs
│ │
│ ├ layouts
│ │ ├pc.hbs
│ │ └sp.hbs
│ │
│ └ partials
│ ├header.hbs
│ ├footer.hbs
│ └common_meta.hbs
│
├ dist
│ ├ pc
│ └ sp
└ node_modules
/src/layouts/pc.hbs
まず「レイアウトファイル」を用意します。
コレは html
で言うと、
「bodyの外側」を作る時に使います。
下記の例では pc
という名前にしています。
これは最後に出来上がるファイルもPC用とSP用で分けようと思っているためです。
対応ブラウザの関係で、
スマホでしかモダンなタグを使えたり
jQuery
(死語)のバージョンをスマホは最新にできるためです。
レスポンシブで作る場合は、作り分ける必要ないので、
このレイアウトファイルは default.hbs
などにすれば良いです。
{% body %}
が置き換わります。
<!DOCTYPE html>
<html lang="ja" dir="ltr">
<head>
{{>common_meta}}
<title>{{title}}</title>
<link rel="canonical" href="https://sample.jp/{{dir}}/" />
</head>
<body>
<div id="container">
{% body %}
</div>
</body>
</html>
htmlに毎回使うようなパーツを読み込みたい場合は
{{>パーツ名}}
と書きます。
そして /src/partials/
以下に
パーツ名.hbs
と言った感じに用意しておくと、読み込まれます。
GoogleTagManager
header
footer
も、
このやり方で埋め込む事ができます。
これで Apache
がなくても
ローカルでパーツ読み込みができるようになります。
Layouts
の hbs
ファイルでも、
個別の hbs
ファイルの中でも、
下記のような書式で読み込みできます。
{{>common_meta}}
{{>gtm}}
{{>header}}
{{>footer}}
また、下記のようなデータバインディングを
<title></title>
にはさみ込んでいます。
ココは ページ によって毎回異なるので、
可変部分をレイアウト側に書いて良いのかな?
と言う疑問が湧くと思いますが、
ココに書いて良いです。
レイアウト側のtitle
やdir
に
どうやってページ事に変わるテキストを入れるのか?
という事は後で書きます。
{{title}}
{{dir}}
/src/partials/common_〇〇.hbs
パーツの読み込みには、
Partialファイルを用意します。
common_meta.hbs
の中はこんな感じ。
{{>common_meta}}
↓↓↓
htmlに変換すると
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="keywords""/>
上記は include
です。
何か変数を入れる場合は下記のような感じです。
例えば thymeleaf
という変数を true にして gulp
に処理させる場合は
if
文の上が入る感じです。
動的な処理が入る場所に関しては予めif文で分岐させておき、
dist
で確認する時は static
に表示させ、
正式に書き出す場合に thymeleaf
を true
にして書き出すといいです。
true
にするやり方は、色々あるので省略。
{{#if thymeleaf}}
<meta th:substituteby="/pc/common/inc/head :: common_meta" />
{{else}}
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="keywords""/>
{{/if}}
/src/doc/sample/index.pc.hbs
各Pageのファイルを用意します。
Layoutファイル内の {% body %}
の中が置き換わるイメージです。
Layoutにある {{title}}
や {{dir}}
を置き換える場合は
hbs
の先頭に、変数とその中身を書いておくと適用されます。
変数の参照ができないと思ったら :
の後ろに
半角スペースが入っているかを確認してください。
:
の後ろのスペースを詰めて記述すると、
テキストが上手く表示されません
---
title: 「ここでLayoutsの変数をかきかえる」
dir: directory
---
<h1>{{obj.pagename.h1}}</h1>
<h2>{{obj.pagename.h2}}</h2>
<div>{{obj.pagename.description}}</div>
{{obj.pagename.h1}}
や {{obj.pagename.h2}}
はどうするの?
という話ですが
/src/data/data.json
を読みこんでおきます。
ちょっとしたサイトであれば、配列を手で編集できますが、
中規模以上のサイトでは手でJSONを更新するのは大変です。
そうなってきたらサーバーサイドのエンジニアの方に
json
を出すURLを作ってもらうと良いです。
最初からJSONを読み込む前提で作っておけば、
後から本格的なデータバインディングに移行するのもラクですし。
全部ハードコーディングすると、
後で雪だるま式に、大変なことになります。
{
pagename:{
h1:"h1にこれが入ります",
h2:"h2にこれが入ります",
description:"descriptionにコレが入ります。"
}
}
gulp
色々インストールしていく。「--save-dev
」は必ず書くようにする。
必要なプラグインが分かるようにするため。gulp-assembleは古いので使わない。
$ npm install --save-dev gulp
$ npm install --save-dev gulp-htmlmin
$ npm install --save-dev gulp-rename
$ npm install --save-dev gulp-extname
$ npm install --save-dev assemble
$ npm install --save-dev gulp-plumber
$ npm install --save-dev path
$ npm install --save-dev gulp-webserver
$ npm install --save-dev gulp-livereload
【2018.03 追記】「fs」はNode.jsに含まれているので、要らないです。
$ npm install --save-dev fs ← コレ不要
【2018.06 追記】Handlebars自体がインストールされてないような気がしましたので追記しました。
$ npm install --save-dev handlebars
$ npm install --save-dev gulp-handlebars
$ npm install --save-dev require-dir
【2019.02 追記】 gulp-server-livereloadが、古いっぽい。gulp-livereloadにしました。
$ npm install --save-dev gulp-server-livereload ←コレ不要
gulpfile.js
プロジェクト直下に「gulpfile.js」というファイルを作る。
中身は「/gulptask」以下に収納しようと思うので、こんな書き方にする。
(設定ファイルが長くなってくると、メンテがしづらくなってgulp疲れが発生するため)
PCとSPでhtmlを別々にしたいので、タスクを別々に書きました。
(これも中で条件分岐するより2回書いた方が設定ファイル的にラクなため。)
var gulp = require("gulp");
var requireDir = require('require-dir');
requireDir('./gulptask',{recurse: true});
gulp.task('default',
['assemble_pc','assemble_sp','copy','watch']
);
【追記】※あら、gulp v4.0.0だと動かないっすね。
var gulp = require("gulp");
var requireDir = require('require-dir');
requireDir('./gulptask',{recurse: true});
gulp.task('default',
gulp.series(
gulp.parallel(
'assemble_pc','assemble_sp','copy','watch'
)
)
);
// gulp v4.0.0ではこう書く。のかな?
まず1行ずつ丁寧説明していきますと・・・
↓このファイルを実行するのには、「gulp」が必要です。
var gulp = require("gulp");
↓「require-dir」っていうプラグインを使います。
var requireDir = require('require-dir');
↓「requireDir();」を使って「/gulptask」以下にタスクを小分けにして書けるようにする。
↓「{recurse:true}」はオプションで、さらにサブディレクトリを使えるようにするヤツです。
requireDir('./gulptask',{recurse: true});
↓下記は「gulp」の「task」です。
↓タスクの名前は「default」です。
↓タスクの内容は「assemble_pc」と「assemble_sp」と「copy」と「watch」です。
gulp.task('default',['assemble_pc','assemble_sp','copy','watch']);
実行する順番を先に書きました。次に中身を書いて行きます。
/gulptask/assemble_pc.js
gulptasksの下に「assemble_pc.js」というファイルを作ります。
中身はこんな感じで書きました。
var gulp = require('gulp');
var htmlmin = require('gulp-htmlmin');
var rename = require('gulp-rename');
var extname = require('gulp-extname');
var assemble = require('assemble');
var plumber = require('gulp-plumber');
var webserver = require('gulp-webserver');
var livereload = require('gulp-livereload');
var path = require('path');
var fs = require("fs");
var app = assemble();
var obj = JSON.parse(fs.readFileSync("./src/data/data.json", { encoding:"utf8" }));
gulp.task('load', function(cb) {
app.partials('src/partials/*.hbs');
app.layouts('src/layouts/pc.hbs');
app.pages('src/doc/**/*.pc.hbs');
cb();
});
gulp.task('assemble',['load'],function() {
app.toStream('pages')
.pipe(plumber())
.pipe(app.renderFile({layout:'pc',obj:obj}))
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(rename({basename:'index'}))
.pipe(extname('.html'))
.pipe(app.dest('dist/pc/'))
.pipe(livereload());
});
【追記】※あら、gulp v4.0.0では動かないッスね。
var gulp = require('gulp');
var htmlmin = require('gulp-htmlmin');
var rename = require('gulp-rename');
var extname = require('gulp-extname');
var assemble = require('assemble');
var plumber = require('gulp-plumber');
var webserver = require('gulp-webserver');
var webserver = require('gulp-livereload');
var path = require('path');
var fs = require("fs");
var app = assemble();
var obj = JSON.parse(fs.readFileSync("./src/data/data.json", { encoding:"utf8" }));
gulp.task('load', function(cb) {
app.partials('src/partials/*.hbs');
app.layouts('src/layouts/pc.hbs');
app.pages('src/doc/**/*.pc.hbs');
cb();
});
gulp.task('assemble', gulp.series( gulp.parallel('load'),function(){
//明示的なreturnが必要
return app.toStream('pages')
.pipe(plumber())
.pipe(app.renderFile({layout:'pc',obj:obj}))
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(rename({basename:'index'}))
.pipe(extname('.html'))
.pipe(app.dest('dist/'));
}));
//gulp v4.0.0ではこう書く。のかな?
数行ずつまとめて説明します。
下記の部分は必要なプラグインを記した箇所です。(varは今風にカンマでつなげて書いても大丈夫です。)
objにはJSONをパースしたものを格納しておきます。objにJSONを格納しておけば後で呼び出せるので簡易的なデータバインディングができます。JSONファイルではなく、API叩いてJSONを返すヤツをココに組み込んでも良い、と思いますが、それはサーバーサイドのエンジニアさんに手伝ってもらって下さい。
忘れがちですが、分割されたタスクには、もう一度「gulp」を読み込む必要があります。
var gulp = require('gulp');
var htmlmin = require('gulp-htmlmin');
var rename = require('gulp-rename');
var extname = require('gulp-extname');
var assemble = require('assemble');
var plumber = require('gulp-plumber');
var webserver = require('gulp-webserver');
var livereload = require('gulp-livereload');
var path = require('path');
var fs = require("fs");
var obj = JSON.parse(fs.readFileSync("./src/data/data.json", { encoding:"utf8" }));
assembleを格納しておきます。
var app = assemble();
1つ目のタスク「load」は下処理です。色んなものを読み込ませます。
「partials」とは「パーツ」の事です。(headerとかfooterなど)
「layouts」とは「レイアウトファイル」の事です(bodyの外側)
「pages」は、今から組み立てるhtmlファイルの事です。(bodyの内側)
「/**/*.pc.hbs
」は、その階層以下の末尾に.pcと付いてる拡張子hbsのファイル全部、という指定の仕方です。「index.pc.hbs」的な名前の付いたファイルのみ変換されます。「index.sp.hbs」と同じフォルダに置いて作業できるので、作業する時にあちこち行き来せずに済むためラクです。
「cb」は「callback」です。「load」が次に呼び出された場所に値を返す感じです。
gulp.task('load', function(cb) {
app.partials('src/partials/*.hbs');
app.layouts('src/layouts/pc.hbs');
app.pages('src/doc/**/*.pc.hbs');
cb();
});
下記はいよいよ組み立てるタスクです。このタスクは['load']が完了した後に実行されます。
gulpは並列でタスクを処理するので、何も意識しないと読み込みと組み立てが同時に動いてしまいます。タスクの順番がおかしくなる場合は、必ずタスクの名前の後ろに['事前に行なうタスク']を入れておくと順番がバラバラにならずに助かります。
gulp.task('assemble_pc',['load'],function() {
app.toStream('pages')
.pipe(plumber())
.pipe(app.renderFile({layout:'pc',obj:obj}))
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(rename({basename:'index'}))
.pipe(extname('.html'))
.pipe(app.dest('dist/pc/'))
.pipe(livereload());;
});
【追記】※gulp v4じゃ動かないっすね。
gulp.task('assemble', gulp.series( gulp.parallel('load'),function(){
//明示的なreturnが必要
return app.toStream('pages')
.pipe(plumber())
.pipe(app.renderFile({layout:'pc',obj:obj}))
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(rename({basename:'index'}))
.pipe(extname('.html'))
.pipe(app.dest('dist/'));
}));
//gulp v4.0.0だったらこう書く。。のかな?
1個ずつ説明していきますと・・・
コレが「assemble_pc」の外側です。名前の後ろのオプション的な箇所は['load1','load2','load3']とつなげて書く事ができます。
gulp.task('assemble_pc',['load'],function() {○○○});
コレはstream()の新しい書き方?です。
「assemble-stream」というモジュールを使って処理するようです。pagesに格納されたファイルに対して、以下の処理を行ないます。
app.toStream('pages')
gulpのお作法は「.pipe」でタスクを繋いでいきます。
gulp.watchしている時にエラーで処理が止まらないようにする「gulp-plumber」を使っています。watchの使い方に付いては、省略します。
.pipe(plumber())
レイアウトは「pc」を使ってhtmlをrenderingします。「obj:obj」はパースしたJSONをrenderfile内に持って入るために利用します。
.pipe(app.renderFile({layout:'pc',obj:obj}))
htmlをミニファイします。
.pipe(htmlmin({collapseWhitespace: true}))
ファイル名を「index」に変更します。
.pipe(rename({basename:'index'}))
ファイルの拡張子を「.html」に変更します。
.pipe(extname('.html'))
ファイルを書き出す場所は「/dist/pc/」以下を指定します。
.pipe(app.dest('dist/pc/'))
livereloadで更新するようにします。
.pipe(livereload());
同様のファイルをspにも作成します。(省略)
###このタスクだけを実行するには?
$ gulp assemble_pc
/gulptask/copy.js
gulptasksの下に「copy.js」というファイルを作ります。
var gulp = require('gulp');
gulp.task('copy', function() {
gulp.src('./src/asset/**')
.pipe(gulp.dest('./dist/'));
});
【追記】※あ、gulp v4.0.0ではこれじゃ動かないかもですね。
var gulp = require('gulp');
gulp.task('copy',
gulp.series(
// gulp.parallel(
function(){
return gulp.src('./src/asset/**')
.pipe(gulp.dest('./dist/'));
}
)
);
//gulp v4.0.0ではこう書く。のかな?
/src/asset/以下にある画像などのファイルをコピーします。
画像はdistにコピーしてあげないと表示が確認できないので、必ずセットで実行して下さい。
scssやAltJSは別のタスクで処理すると思いますが、もしもトランスパイルしない感じであれば
/src/asset/内に置いて/dist/にコピーして下さい。
###このタスクだけを実行するには?
$ gulp copy
#上記、全部のタスクを実行するには?
$ gulp
または
$ gulp default
#サーバーの立て方(gulp-webserver)
node.jsの簡易的なサーバーを立てる方法は色々ありますが、gulpなら、gulp-webserverを使います。特に「livereload」は最近のモダンなコーディング事情的には、ほぼ必須の仕組みです。(ファイルの変更を監視して自動的にブラウザが自動リロードを書けるものです。ホットリロードとも言います。)これでhtmlやCSSを書き直した時に「F5」や「Ctrl+R」をポチポチ毎回叩かなくて良いです。もっと良いやり方があるかもしれませんが、自分は「webserver」が「livereload」のイベントを拾うのと、「watch」イベントが「ファイルの更新」を監視するイベントを一つにできなかったので、「webserver」のターミナルは、「gulp default」とはターミナル別窓で開いております。(追記:「gulp-connect」はもう古いらしいので「gulp-webserver」に書き換えました。)
var gulp = require('gulp');
var webserver = require('gulp-webserver');
gulp.task('webserver', function() {
gulp.src('dist')
.pipe(webserver({
host: 'localhost',
port: 8888,
livereload: true
}));
});
【追記】※あっ、gulp v4.0.0で動かないかも・・
var gulp = require('gulp');
var webserver = require('gulp-webserver');
gulp.task('webserver', gulp.series( function(){
gulp.src('dist')
.pipe(webserver({
host: 'localhost',
port: 8888,
livereload: true
}));
}));
//gulp v4.0.0 ではこう書く。のかな。
監視の説明がなかったので、追記しました。「gulp-webserver」は「dist」を監視しているので
「src」を更新したら「dist」へ書き出し、「dist」の更新を「livereload」で拾う、という感じでできます。
var gulp = require("gulp");
gulp.task("watch",['assemble_pc','assemble_sp','copy'], function () {
var watcher = gulp.watch("./src/doc/**",['assemble_pc','assemble_sp','copy']);
watcher.on('change', function(event) {
console.log(event.path + 'が変更されました。');
});
});
※あっ、gulp v4.0.0で動かないかも・・
var gulp = require("gulp");
gulp.task('watch',function(){
return gulp.watch('./src/doc/**',
gulp.task(
gulp.series(
gulp.parallel(
'assemble','copy'
)
)
)
);
});
//gulp v4.0.0 ではこう書く?のかな。。
サーバーを立てると「http://localhost:8888」をブラウザで見れるようになり、/dist/以下に書き出されたファイルを表示します。
$ gulp webserver
#npmでタスクを実行するには?
最近はタスクランナー的な抽象化をしないで「$ npm run」で何でもやることになった(らしい)ので、
「gulpをグローバルインストールしたくないよ〜」
「ターミナルに「\$ gulp
」なんて打つの恥ずかしいよ〜」
「npmコマンドでやりたいよ〜」
という場合は、次のようにする。
「package.json
」の「scripts
」に、下記のような記述をする。
(下記、webpack
やらgrunt
やらは説明用に入ってるだけです。適宜削って下さい。)
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npm-run-all build:*",
"build:webpack": "webpack",
"build:gulp": "gulp default",
"build:grunt": "grunt default"
},
このモジュール(npm-run-all)をインストールしておくと
複数のbuild以下のスクリプトを実行できるようになります。
$ npm install --save-dev npm-run-all
そして
$ npm run build
とすれば良いです。(build:
が付いているタスクを全部実行してくれます)
(2021.03.04追記)
ただgulp
を実行したいだけなら、
package.json
に記述を追加しなくても npx
で良いんじゃないか?と思いました。
この辺はNode.jsの進化によって移り変わるので、好みでいいと思います。
$ npx gulp
$ npx gulp default
$ npx gulp assemble_pc
$ npx gulp copy
$ npx gulp watch
いかがでしたでしょうか?「非エンジニア」でも「タスクランナー」を導入することでWeb制作を効率化ができるんじゃないかなと思います。以上です。