35
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

wiredep, gulp-injectでlink, scriptをhtmlに自動注入

Last updated at Posted at 2015-08-09

最近はgulpgruntでビルドプロセスを自動化していかないとやってられない、というような流れになってきている気がしますが、gulpgruntもいろんなライブラリが出まくっていて、一つ覚えたと思ったらもう新しくてさらに効率のいいライブラリが出てきたりしてますよね。。。と、愚痴を言っていても仕方ないのですが、今回はlinkタグとかscriptタグを自動で注入(inject)してくれるgulpのライブラリ、wiredepgulp-injectの基本的な使い方について検証したのでまとめます。
指摘事項や、「こうしたらほうがいいよ?」などありましたら遠慮無くコメント欄やメッセージなどで気軽に教えていただけると喜びますm(__)m

はじめに

まず、下のようなページがあったとします。

<html>

<head>
  <link rel="stylesheet" href="../../bower_components/bootstrap/dist/css/bootstrap.css" />
  <link rel="stylesheet" href="../../bower_components/font-awesome/css/font-awesome.css" />
  <link rel="stylesheet" href="styles/app.css">
</head>

<body>
  <div id="main-region"></div>
</body>

<script src="../../bower_components/react/react.js"></script>

<script src="app/app.js"></script>

</html>

すごいシンプルなので、ここからは問題はあまり見えてこないんですけど、bower使って便利ライブラリをいろいろとインストールしていって、cssやらscriptやらが増えてくると、いちいち自分でindex.htmlに書いてられないですよね?おまけにこれに各アプリケーション特有のcssscriptも増えていくのがほとんどのケースだと思います。これを全部管理するっていうのは人間のやることじゃない。って考える人は世の中にいっぱいいて、そうなるとやっぱり便利ツールは出現するんです。そこで登場するのがwiredepgulp-inject

こんなことをします。
wiredep.gif

ライブラリについて

wiredep

Wire Bower dependencies to your source code.

と、githubで書かれているように、bower install --saveしたライブラリをhtmlに自動で注入してくれるのがwiredepです。dependenciesを見ながらhtmlに注入してくれるので、(やや難がありますが)注入順についても意識しなくても良いという特徴があります。

gulp-inject

A javascript, stylesheet and webcomponent injection plugin for Gulp, i.e. inject file references into your index.html

と、githubに書かれているように、bowerに特化せず、cssやらscriptやらを注入できるのがgulp-inject(多分)。 依存関係とかを勝手にいい感じにやってくれる って機能はないはずなので、今回はgulp-injectをアプリ特有のcssscriptに使おうと思います。

下準備

あらかじめ入れてある前提で話を進めるnpm packagegulp(もちろん)とgulp-load-pluginsです。
今回のように小規模なサンプルの場合gulp-load-pluginsはどう考えても必要ないけど、たいていの場合私はgulp-*系なライブラリを多用するのでgulp-load-pluginsを使います。これについては詳しく説明しません。ってなわけでインストールしておきます。

npm install --save-dev gulp gulp-load-plugins

wiredepgulp-injectもインストールしちゃいましょう。

npm install --save-dev wiredep gulp-inject

wiredep関連の作業

html編集

bower経由でインストールしているライブラリのタグをcssならbower:cssで、scriptならbower:jsで下のように囲んで、元のタグは消しちゃいます。ここにwiredepが自動注入してくれるようになるからです。

src/client/index.html
<html>

<head>
  <!-- bower:css -->
  <!-- endbower -->
  <link rel="stylesheet" href="./styles/app.css">
</head>

<body>
  <div id="main-region"></div>
</body>

<!-- bower:js -->
<!-- endbower -->
<script src="./app/app.js" charset="utf-8"></script>

</html>

gulpfile.js編集

それではgulpfile.jsの編集をします。書きっぷりとしては下のように書いておけば(たいていの場合)完了です。

gulpfile.js
gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;

  return gulp
    .src('./src/client/index.html')
    .pipe(wiredep()) // wiredep bower dependencies
    .pipe(gulp.dest('./src/client')) // output the index.html
})

ただし、今回の例の場合うまくいきません。仮にgulp wiredepと実行してもタスクは完了して何も注入されていないことに気づきます。

何故かと言うと、wiredepの仕組み上、注入するための情報が不足しているからです。
wiredepが自動注入する際に参考にしている情報は各ライブラリの.bower.jsonmainの内容とdependenciesの内容です。
今回使っているbootstrap.bower.jsonを見ると、

// 割愛

"main": [
  "less/bootstrap.less",
  "dist/js/bootstrap.js"
],

// 割愛

"dependencies": {
  "jquery": ">= 1.9.1"
},

となっており、注入してほしいdist/css/bootstrap.cssが記述されていません。こんな時は自分のbower.jsonに明示的に情報を付加してあげる必要があります。書きっぷりは下のような感じになります。

bower.json
"overrides": {
  "bootstrap": {
    "main": "dist/css/bootstrap.css",
    "dependencies": {}
  },
  "font-awesome": {
    "main": "css/font-awesome.css"
  }
}

overridesの下にライブラリ名: {プロパティ名: 与えたい値}という具合で情報を増やしてあげます。今回はbootstrapdependenciesであるjqueryも使いたくなかったので明示的にdependenciesを空オブジェクトにしています。ここのそのままにしているとbower:jsで囲まれている箇所にjqueryが意図せず注入されてしまいます。
これでwiredep関連の自動化は完了。gulp wiredepbower関連のライブラリが注入されるはずです。

gulp-inject関連の作業

それでは、各アプリ特有のcssscriptも注入できるようにします(多くの場合app.jsだったりapp.cssだったりするファイルです)。要領はwiredepのときと同様ですが、囲むタグをcssの場合はinject:cssで、scriptの場合はinject:jsとします。
下のようになるはずです。これで手動で書くタグはなくなりましたね!

htmlの編集

src/client/index.html
<html>

<head>
  <!-- bower:css -->
  <!-- endbower -->
  <!-- inject:css -->
  <!-- endinject -->
</head>

<body>
  <div id="main-region"></div>
</body>

<!-- bower:js -->
<!-- endbower -->
<!-- inject:js -->
<!-- endinject -->

</html>

gulpfile.jsの編集

先ほどのwiredepタスクにちょっとコードを足します。

gulpfile.js
gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;

  return gulp
    .src('./src/client/index.html')
    .pipe(wiredep()) // wiredep bower dependencies
    .pipe($.inject(gulp.src(['./src/**/*.js', './src/**/*.css']), {
      relative: true // no need for the './src/client' part
    }))
    .pipe(gulp.dest('./src/client')) // output the index.html
})

gulp-load-pluginsを使っていて、かつそれを$としてrequireしているのでgulp-inject$.injectでアクセス可能になってます。対象ファイルはとりあえずsrc配下のcssjsとしてます。そして、オプションなしでこのまま実行するとlinkscriptタグが./src/clientからパスを初めてしまうので、index.htmlからみた相対パスを注入してもらうようにrelative: trueというオプションを渡しています。
以上で完了です。これでgulp wiredepを実行したらindex.htmlに自動でlinkscriptタグが注入されるようになります。

それぞれのソースの最終形

src/client/index.html
<html>

<head>
  <!-- bower:css -->
  <!-- endbower -->
  <!-- inject:css -->
  <!-- endinject -->
</head>

<body>
  <div id="main-region"></div>
</body>

<!-- bower:js -->
<!-- endbower -->

<!-- inject:js -->
<!-- endinject -->

</html>
gulpfile.js
var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
  lazy: true
});

gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;

  return gulp
    .src('./src/client/index.html')
    .pipe(wiredep()) // wiredep bower dependencies
    .pipe($.inject(gulp.src(['./src/**/*.js', './src/**/*.css']), {
      relative: true // no need for the './src/client' part
    }))
    .pipe(gulp.dest('./src/client')) // output the index.html
})
bower.json
{
  "name": "wiredep-inject-starter",
  "version": "0.0.0",
  "homepage": "https://github.com/kenfdev/wiredep-inject-starter",
  "authors": [
    "Ken Fukuyama <kenfdev@gmail.com>"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "bootstrap": "~3.3.5",
    "font-awesome": "~4.4.0",
    "react": "~0.13.3"
  },
  "overrides": {
    "bootstrap": {
      "main": "dist/css/bootstrap.css",
      "dependencies": {}
    },
    "font-awesome": {
      "main": "css/font-awesome.css"
    }
  }
}

課題

課題というか、このサンプルだけでは足りていないことは、

  • アプリ特有のscriptの依存関係を考えた順番の注入ができていない
  • 実際はcssjsのビルドプロセスが存在するため、このタスク単体では実務では使えない。(依存タスクをもっと作る必要あり)
    などなど、まだまだたくさんあります。
    が、とりあえずはwiredepgulp-injectの雰囲気がつかめたのでよしとしようかと。

おまけ

wiredep-inject-starterとして今回のソースを上げています。

35
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?