はじめに
Java界隈でご飯を食べている私ですが、最近クライアントサイドJavaScriptでの開発(というかnpm)について勉強する機会があったので手順を整理して共有します。
この記事は次のような(ちょっと前の私みたいな)人に向けたチュートリアルです。
- 古めのJavaScriptの知識ならある人(旧石器時代に生きている人)
- jsは公式サイトからDL・配置してhtmlファイルにscriptタグを並べて読み込むものだと思っている(それ以外に何があるのだ?)
- jQueryならある程度は書けるんだけど
- フロント界隈の記事を読むとサッパリ分からん な人
- npmとかrequireとかよく見るけどよくわからん
- Java界隈を軸に活動している人
ここに書いてあることすらもはや古臭くなりつつある感じがしますが、旧石器時代よし少しは前に進めるのではないかと思います。
また、ここに書いてあるのは開発手法の1例であって、これがスタンダードなわけじゃないよ、ということは補足しておきます。
さらに、私も勉強始めたばかりなので、間違ってたり非推奨だったりベターな方法が他にあれば指摘していただけると嬉しいです。
チュートリアル
必要なもの
- お気に入りのテキストエディタ
- 15分から20分程度
Node.jsインストール
最近のフロントエンド開発はNode.jsなしにはありえません。Node.jsと言うとExpressなどに代表されるサーバサイドの実行環境としての情報も混じってくるので初めは混乱しやすいですが、クライアントサイド開発におけるNode.jsはコンパイラや周辺ツールを動かす開発環境です。JavaでいえばJDKの位置づけかな?
ということでNode.jsをインストールしましょう。Windowsなら以下からインストーラをダウンロードして実行してください。
他のOSはパッケージマネージャから導入するのが良いでしょう。
プロジェクト作成
アプリのプロジェクトを作成します。便宜的にfront-devという名前で説明します。
プロジェクト用のディレクトリを作成し、ターミナルからnpm init
コマンドを実行します。gradle init
やmvn archetype generate
のnodeバージョンだと思えばよいかと。
cd 好きなディレクトリ
mkdir front-dev
cd front-dev
npm init
(色々聞かれるが、Enterキー連打)
※npm
コマンドはNode.jsをインストールすると(特別に設定しない限り)一緒にインストールされます。
色々聞かれますがここでは適当に全部エンターを押してしまってください。
この時点でfront-dev
フォルダ配下にpackage.json
が作成されます。依存パッケージなどは後々このファイルに書いていきます。Javaでいうpom.xml
のようなものですね。
{
"name": "front-dev",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
色々書いてありますが今回はscripts
以外使わないので大胆に消してしまいましょう。
{
"scripts": {
}
}
npm-scripts
package.json
を以下のように書き換え、npm run hoge
を実行してみてください。画面にHOGEHOGEと表示されるはずです。
{
"scripts": {
"hoge":"echo HOGEHOGE"
}
}
> npm run hoge
> @ hoge C:\Users\tatesuke\Desktop\front-dev
> echo HOGEHOGE
HOGEHOGE
このように、package.json
のscripts
にコマンドを定義しておくとnpm run 名前
でそのコマンドを実行することができます。ビルドスクリプトの起動などに使います。
ちなみに、start
という名前のscriptは特別で、npm start
のようにrun
を省略して実行することができます。
依存モジュールのインストール
Javaでは依存モジュールのjarをダウンロードしてクラスパスに配置して・・・という作業はもはや時代遅れで、依存性管理はmavenやgradleに任せるようになりました。フロントエンドでも同様で、自分でjsファイルをダウンロードして利用するという方法はもはや時代遅れです。依存性解決はnpmに任せます1。
package.json
を以下のように変更してください。
{
"scripts": {
"hoge": "echo HOGEHOGE"
},
"dependencies": {
"jquery": "^3.2.1"
}
}
このように、dependencys
ブロックに依存パッケージを定義することで、npmが依存性を管理してくれます。この例ではjQueryへの依存を定義しています。
依存モジュールをインストールするにはnpm install
コマンドを実行します。
npm install
※WARNINGが出ますがこのチュートリアルでは無視します。
front-dev
フォルダ配下にnode-modules
というフォルダが作成され、その中にjQueryのソースなどがダウンロードされます。
front-dev
│ package.json
│
└─node_modules
└─jquery
依存モジュールの使用(scriptタグ)
インストールしたパッケージを利用する最も簡単で原始的な方法はscript
タグを利用することです。
以下のようなhtml、jsファイルを作成してブラウザで開いてください。
<!doctype html>
<head>
<meta charset="utf-8">
<title>ハローフロントエンド</title>
</head>
<body>
<div id="container"></div>
<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="index.js"></script>
</html>
(function($){
$("#container").text("jQuery is work!");
})(jQuery);
jQueryが利用できていることがわかると思います。
依存モジュールの使用(require)
npmで管理するパッケージを利用するもっと最近っぽい方法はrequire
を利用する方法です。package.json
に定義した依存パッケージはcommon.jsのrequire関数で読み込む事ができるのです。
先程のhtml、jsを以下の通り変更してください。
<!doctype html>
<head>
<meta charset="utf-8">
<title>ハローフロントエンド</title>
</head>
<body>
<div id="container"></div>
<!-- jqueryのjsを読み込むのをやめる
<script src="node_modules/jquery/dist/jquery.js"></script>
-->
<script src="index.js"></script>
</html>
var jQuery = require("jquery"); //requireでjqueryを読み込む
(function($){
$("#container").text("require is work!");
})(jQuery);
これをブラウザで開くと無事にjQueryが利用でき・・・ません!!
requireの使用
実はブラウザにはrequire関数が実装されていないので動かないのは当然です。ブラウザでrequireを利用できるようにしなければなりません。それにはいくつかのメジャーな方法があります。
- RequireJSを利用する
- Browserifyを利用する
- Webpackを利用する
ここではBrowserifyを使った方法を説明します。
Browserifyはrequireを使ったjsをブラウザで実行でるように変換するツールです。
Browserifyのような周辺ツールもnpmを使ってインストールできます。'package.json'を以下のように変更してください。
{
"scripts": {
"hoge": "echo HOGEHOGE"
},
"dependencies": {
"jquery": "^3.2.1"
},
"devDependencies": {
"browserify": "^14.1.0"
}
}
実行時には使用しないけれどプロジェクトとして利用するツール類はこのようにdevDependencies
ブロックに記述します。mavenで言う「test」や「provided」スコープ、gradleでいう「testCompile」に近いものですね。
続けてmpn install
を実行します。
npm install
これでnode_modules配下にBrowserify(と、Browserifyが依存するモジュール)がダウンロードされました。早速使ってみましょう。次のコマンドを実施してください。
./node_modules/.bin/browserify index.js > out.js
これでrequireで参照されるモジュールをひとまとめにして使えるようにしたout.js
が出力されました。index.html
を以下のように変更してブラウザで開いてください。
<!doctype html>
<head>
<meta charset="utf-8">
<title>ハローフロントエンド</title>
</head>
<body>
<div id="container"></div>
<!-- Browserifyで生成したout.jsを読み込むようにする
<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="index.js"></script>
-->
<script src="out.js"></script>
</html>
無事にrequireで読み込んだjQueryが利用できたはずです。
蛇足ですが、私はこのようにJavaScriptからJavaScriptに変換するという感覚をつかむのに時間がかかりました。やってみたらなんだそんなことかという感じなのですが
npm-script
毎回先程のようなコマンドを打つのは面倒くさいので、npm-scriptとして記述してしまいましょう。
{
"scripts": {
"build": "browserify index.js > out.js"
},
(略)
}
scripts
ブロックではdependencysやdevDependenciesに記述されたモジュールは./node_modules/.bin/
を省いて記述できます。これで、npm run build
でBrowserifyを実行できるようになります。試してみてください。
ビルドスクリプト(Gulp)
実際の開発ではLint(構文チェック)をかけてBrowserifyかけてminify(圧縮)かけて、なんならCSSもSASSやLESSからコンパイルかけて・・・などと、手順が複雑になります。これを行うのにnpm-scriptだけでは役不足です。要するにフロント開発にもビルドスクリプトが必要なのです
JavaScript界隈のビルドツール・タスクランナーはたくさんありますが2大巨塔は以下です。
- Grant
- Gulp
ここではGulpの利用してみましょう。もし、エディタでpackage.jsonを編集していたらそれを閉じてから、次のコマンドを実行してください
npm install --save-dev gulp
いままでは依存モジュールを利用するときにpackage.json
に依存性を記述してからnpm install
を実施していましたが、このように--save-dev
オプションを付けるとpackage.json
のdevDependencies
に追記+npm install
を一括で実施してくれます。package.json
を見ると自動的にgulpが記述されているはずです。
{
(略)
"devDependencies": {
"browserify": "^14.1.0",
"gulp": "^3.9.1" // ←ここが自動で追加されている
}
}
補足ですが、--save
オプションを付ければ同様にdependenciesに追記+
npm install`を一括で実施してくれます。
npm install --save angular
話を戻してビルドスクリプトに戻します。gulpのビルドファイルgulpfile.js
を作成してください。
var gulp = require("gulp");
var browserify = require("browserify");
var fs = require("fs");
gulp.task("build", function() {
var out = fs.createWriteStream('./out.js');
browserify({
entries: ['index.js']
})
.bundle()
.pipe(out);
});
build
というタスクでbrowserifyを呼び出しています。これをpackage.jsonで呼び出すようにします。
{
"scripts": {
"build": "gulp build"
},
(略)
}
これでnpm run build
でgulpを起動してビルドできるようになりました。試してみてください。
npm run build
開発用サーバ
今やJavaScriptの開発でもWebサーバーが必須になってきます。例えばAngularJSのui.routerなんかはWebサーバがないと動きません。しかし、そんなに面倒臭がる必要もありません。開発用サーバもnpmで準備できるからです。
開発用サーバも山のようにありますが、ここではsuperstaticというモジュールを利用してみます。
npm install --save-dev superstatic
ビルドスクリプトの末尾にサーバー起動用のスクリプトを追記してください。
(略)
var superstatic = require('superstatic');
gulp.task("serve", ["build"], function () {
superstatic.server({
port:3000
}).listen();
});
npmから呼び出せるようにします。
{
"scripts": {
"build": "gulp build",
"serve": "gulp serve"
},
(略)
}
これでnpm run serve
を実行するだけでソースコードをビルドしてhttpサーバ起動します。コマンドを実行したあと、以下URLにアクセスすると、index.htmlが表示できるはずです。
npm run serve
watch
開発時には、修正→確認→修正→確認・・・というサイクルを繰り返す事になります。このとき、毎回手動でビルドコマンドを呼び出すの億劫です。そのため、大抵の場合、ソースに変更があったら自動的にビルドを実行する仕組みを導入することになるでしょう。
grup.watch
を使うと指定ファイル・ディレクトリに変化があったときにタスクを自動的に実行できます。ビルドスクリプト末尾に以下を追記してください。
(略)
gulp.task("watch", ["serve"], function () {
gulp.watch("./index.js", ["build"]);
});
例によって、package.jsonにも追記します。
{
"scripts": {
"build": "gulp build",
"serve": "gulp serve",
"watch": "gulp watch"
},
(略)
}
これで、npm run watch
するとビルド→httpサーバ起動⇢index.jsに変更があると自動的に再ビルドを行ってくれます。
試しにnpm run watch
した状態でindex.js
を適当にいじってみてください。ブラウザを更新すると変更が反映されているはずです。
npm run watch
チュートリアルは以上で終了です。
雑多に補足
Bower
npmと同様にパッケージの依存解決を行うツールにBowerがあります。以前は流行っていたようですが、最近は失速気味?でもBowerを使ってるプロジェクトはまだまだあるので、bowerという単語を見ても慌てず「あー依存性管理のやつね」と思えばいいと思います。
###トランスパイラ、コンパイラ
最近、ES6(ES1025)やらTypeScriptという単語をよく聞きます。ES6は新しい仕様のJavaScriptで、TypeScriptはJavaScriptを拡張したプログラミング言語です。「ES6+Babel+Browserifyで開発」とか「TypeScript+Webpack」とか見るとひどくややこしく感じます。が、どちらもブラウザで認識できない形式のコードで実装して、最終的にブラウザが実行できる形のjsに変換するという点を理解してしまえばそんなに難しい話ではありません。
ES6を使った開発では、ES6形式のコードをブラウザが実行できる形に変換(トランスパイル)します。
ES6で書いたコードを書く
↓
(Babel+Browserify)
↓
ブラウザで実行できるコード
TypeScriptを使った開発では、TypeScript形式のコードをブラウザが実行できる形に変換(コンパイル)します。
TypeScriptで書いたコード
↓
(TypeScriptコンパイラ)
↓
ブラウザで実行できるコード
ちなみに今回のチュートリアルで行った手順は
requireを使ったコード
↓
(Browserify)
↓
ブラウザで実行できるコード
同じことですね。
そしてトランスパイラもコンパイラもBrowserifyと同じようにもnpmで管理できるので気軽に試せます。そんなに恐れる必要もないなと思いました。
ディレクトリ構成について
プロジェクトのディレクトリ構成について、これといったものが決まったものはないみたいです。今回は全部ルート配下で作業してしまいましたが、本来はJavaと同じようにsrcフォルダとbuildフォルダに分けて、ソースとビルド成果物を明確に分けるのが良い方法でしょう。
グローバルインストール
npm install -save
やnpm install --save-dev
のほかにもnpm install -g パッケージ名
というコマンドをたたくことができます。-gはグルーバルという意味で、グローバルに機能をインストールします。npm install -g browserify
のように叩くとbrowserifyを普通にコマンドで直接叩くことができるようになります。
以下のコマンドを実行してください。
> browserify index.js > out.js
('browserify' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。)
> npm install -g browserify`
> browserify index.js > out.js
npm install -g
後はbrowserifyをコマンドとして叩けるようになっているのがわかると思います。
終わりに
チュートリアルはいかがだったでしょうか。
私は用語がわけわからな過ぎて無意識にフロント界隈を避けて通ってきましたが、今回このチュートリアル程度の内容を勉強して、なんだそれだけのことだったのかと思う部分が多かったです。
最先端のモダンJavaScriptとまではいきませんが、旧跡時代のJavaScriptからは一歩抜け出せたんじゃないかな、と思います。
この内容がどなたかの参考になればうれしいです。
-
今更ですが、npmはNode Package Managerの略でNode.jsのパッケージ管理システムです。JavaとMavenの関係に似てます。 ↩