Gruntの復習(5) 色々なタスクを追加しよう
Gruntの基本的なところはおさえられた気がするので、他にどのようなことができるか見てみることにします。
grunt-contribを見てみる
前回書いたように、contrib
と付いているプラグインはいわば公式プラグインのような扱いなのですが、その中で初めての人向けによく使いそうなものをまとめたプラグインがあります。その名もgrunt-contribプラグイン。ありがたい。
gruntjs/grunt-contrib · GitHub
ということで、まずはこのgrunt-contribプラグインに入っているものを見て、その中から自分に必要そうなものを選ぶのがよさげです。ということで見てみましょう。
- grunt-contrib-clean ファイル・フォルダの掃除
- grunt-contrib-coffee CoffeeScriptコンパイル
- grunt-contrib-compass Sass+Compassコンパイル
- grunt-contrib-compress ファイル・フォルダの圧縮
- grunt-contrib-concat ファイル結合
- grunt-contrib-connect Webサーバ起動
- grunt-contrib-copy ファイル・フォルダのコピー
- grunt-contrib-cssmin CSSの圧縮
- grunt-contrib-csslint CSSのLint
- grunt-contrib-handlebars Handlebarsコンパイル(JST)
- grunt-contrib-htmlmin HTMLのminify
- grunt-contrib-imagemin 画像のminify
- grunt-contrib-jade Jadeのコンパイル
- grunt-contrib-jasmine Jasmine実行
- grunt-contrib-jshint JSHint実行
- grunt-contrib-jst UnderScoreコンパイル(JST)
- grunt-contrib-less LESSコンパイル
- grunt-contrib-nodeunit NodeUnit実行
- grunt-contrib-qunit QUnit実行
- grunt-contrib-requirejs RequireJS最適化
- grunt-contrib-sass Sassコンパイル
- grunt-contrib-stylus Stylusコンパイル
- grunt-contrib-uglify UglifyJSでJSのminify
- grunt-contrib-watch watch
- grunt-contrib-yuidoc YUIDocコンパイル
逆の観点から見ると、これらのツールがよく使われている、ということになりますね。
grunt-contribを使う
今までと同様にnpm install grunt-contrib --save-dev
を実行して、Gruntfile.coffeeにgrunt.loadNpmTasks 'grunt-contrib
と書くだけ。これで上記がすべて使えるようになります。上記はnpm一発で入りますし、個別に書く必要がないので、楽ですね。
ということで、grunt-contribを使って用途にあったものを作るのがよさそうです。
grunt-contribで気をつけるところ
すでにgrunt-contribほげほげプラグインを使っているところにgrunt-contribプラグインをnpm install
すると、他プラグインとのバージョン依存でエラーになったりすることがあります。以下はgrunt-contrib-cssminを入れていたところにgrunt-contribを入れて出たエラーです。
npm ERR! peerinvalid The package grunt-contrib-cssmin does not satisfy its siblings' peerDependencies requirements! npm ERR! peerinvalid Peer grunt-contrib@0.8.0 wants grunt-contrib-cssmin@~0.6.2 npm ERR! System Darwin 13.0.0 npm ERR! command "node" "/Users/masataka/.nodebrew/current/bin/npm" "install" "grunt-contrib" "--save-dev" npm ERR! cwd /Users/masataka/src/grunt-test npm ERR! node -v v0.11.10 npm ERR! npm -v 1.3.23 npm ERR! code EPEERINVALID npm ERR! npm ERR! Additional logging details can be found in: npm ERR! /Users/masataka/src/grunt-test/npm-debug.log npm ERR! not ok code 0
Peer grunt-contrib@0.8.0 wants grunt-contrib-cssmin@~0.6.2
とありますので、npm install grunt-contrib-cssmin@~0.6.2 --save-dev
とバージョン指定インストールを実施するか、npm uninstall grunt-contrib-cssmin
とアンインストールしてしまうのも手です。そして再度npm install grunt-contrib --save-dev
すると。
現場からは以上です。
@pageでの長さ単位はem,ex以外にしよう
とあるWebサイトをPDF化するにあたり、偶数ページと奇数ページでマージンを変更する必要があったのですが(いわゆるノド余白)、OS標準の機能やAcrobatでもなかなかうまくいかず、以下の助言が。
@suzukima @page:left {margin: 〜;} @page:right {margin: 〜;} って効かないですかね
— ろす@ぱらむしる (@lost_and_found) 2014, 1月 14
そうかPaged Mediaって聞いたことがあったわ。Paged Mediaは印刷など、ページの概念が存在するメディアに関する仕様です。@page
は、印刷時のCSSを指定するものと考えるといいでしょう。そして@page:left
で左側ページ、@page:right
で右側ページのCSSを指定することができます。早速以下のCSSを適用してみました。
@page { margin: 1em; } @page: left { margin-right: 3em; } @page: right { margin-left: 3em; }
しかし効かない。ちょろっと調べてみると、:left - CSS | MDNではFirefox未実装、Chromeは?なのでまだ実装されてないのかな、とその場はさっくり諦めました。
しかし、その後帰路にて「もしかしたらベンダプレフィックスが必要だったのかも」と気になってきたので、まずは仕様から読んでみることにしました。
仕様はこちら。CSS2.1のお話です。
で、@pageについて書いてある13.2.1 Page marginsのところを見てみると、こんな文が。
The page context has no notion of fonts, so 'em' and 'ex' units are not allowed.
emとexは使えないとな!これか!ということで以下を試してみたところ、
@page { margin: 1cm; } @page: left { margin-right: 5cm; } @page: right { margin-left: 5cm; }
できた!
言われてみればたしかにpage contextにはフォントの概念はないよな…
これでやりたかったことが1つ解決しました。@lost_and_found さん、ありがとうございます!
ちなみにPaged Mediaの次の仕様はCSS Paged Media Module Level 3として標準化中、現在Workind Draftです。ヘッダやフッタを挿入したり、ページ数を入れたりとかできるらしいです。楽しみですね。
Gruntの復習 (4)watchタスクを追加しlivereloadしよう
またかよ禁止。
Gruntの復習 (3)タスクの書き方 - 鴨のいいカモですの続きで、まずはwatchタスクのみとりあげてみることにしました。自分が今Gruntを使っているのはこのwatchタスクがあるからです。watchタスクは、ファイルを監視し、ファイルに変更があると指定したタスクを実行します。これで、変更ごとにコマンドを実行する手間から開放されます。
さらに、livereloadと呼ばれるブラウザ再読み込み機能もあり、とても便利です。ぜひ使いましょう。
ということで、前回作成した以下のGruntfile.jsにwatchタスクを追加してみることにしましょう…の前に、これをCoffeeScriptにしましょう。
module.exports = (grunt) -> grunt.initConfig # 実行タスク uglify: options: report: 'min' dest: options: beautify: true files: 'dest/js/scripts.min.js': ['src/js/*.js'] build: files: 'build/js/scripts.min.js': ['src/js/*.js'] # タスク読み込み設定 grunt.loadNpmTasks 'grunt-contrib-uglify' # タスク定義 grunt.registerTask 'default', ['uglify']
すっきり!わかりやすい!ということで、さっそくwatchタスクの追加をしましょう。
watchタスクのためのプラグインを探す
プラグイン検索にはPlugins - Grunt: The JavaScript Task Runnerを使うといいでしょう。頭にcontrib-
とついてるのはGruntのいわば公式プラグインですので、迷った時はそちらをつかうといいかと。
watchで検索するとgrunt-contrib-watchが出てくるので、それを使いましょう。
grunt-contrib-watchの下準備
まずはいつものようにプラグインを追加します。検索結果から見られるドキュメントgrunt-contrib-watchにあるように、以下のコマンドを実行します。
npm install grunt-contrib-watch --save-dev
そして、Gruntfile.coffeeに以下を追加してタスク読み込みさせます。
grunt.loadNpmTasks 'grunt-contrib-watch'
watchタスクの記述
とても簡単で、基本的にはターゲットに監視対象をfiles
で、監視対象変更時に実行したいタスクをtasks
で指定するだけです。以下はsrc/js/*.js
の変更時に、タスクuglify:dest
を実行する例です。
watch: scripts: files: ['src/js/*.js'] tasks: ['uglify:dest']
watchタスクの実行
今までと同じように、grunt watch
と実行するだけです。すると、以下のように監視状態となります。
% grunt watch Running "watch" task Waiting...
ここで、監視対象であるファイルを変更すると…
Waiting...OK >> File "src/js/a.js" changed. Running "uglify:dest" (uglify) task File "dest/js/scripts.min.js" created. Original: 129 bytes. Minified: 134 bytes. Done, without errors. Completed in 0.571s at Wed Jan 08 2014 11:33:07 GMT+0900 (JST) - Waiting...
と表示されます。無事uglify:dest
タスクが実行されました!
これで、わざわざコマンドを実行する手間から開放されます。便利!CoffeeScriptやLESSやSassなどのプリコンパイルが必要な言語にぴったりですね。
livereloadの実行
開発中のよくあるシーンに、ファイルを更新したらWebブラウザの再読み込みを行う、というのがありますが、watchタスクでそれを自動化することができます。
それを確かめるために、dest/index.htmlを適当に準備しておきましょう。
watchのlivereloadオプション有効化
watchにlivereloadオプションがあるので、それを有効化します。watchの記述を以下のようにしましょう。
watch: options: # 追加 livereload: true #追加 scripts: files: ['src/js/*.js'] tasks: ['uglify:dest']
これで、grunt watch
とすると、対象ファイル変更時にWebブラウザへ更新依頼を出すサーバが立ち上がるようになります。が、Webブラウザ側でそれを受け取ることができませんので、その準備をしましょう。
Webブラウザへのlivereloadプラグインの追加
Webブラウザ側で更新依頼を受け取るようにするにはいくつか方法がありますが、楽なのはWebブラウザにliveleload対応プラグインを追加することです。How do I install and use the browser extensions? – LiveReload Help & Supportを参考に、WebブラウザへLiveReload用拡張を追加しましょう。
あとは、grunt watch
を実行し、index.htmlをWebブラウザで開いてプラグインで追加されたボタンを押せば、準備完了です。
src/js/*.js
を変更して保存すると、ブラウザで再読み込みが発生するはず、です。
…しない人は、Webサーバを立ち上げずに、ローカルのindex.html
を見ていないからかもしれません。
Webサーバ立ち上げ
ということで、せっかくなのでwatchついでに確認用のWebサーバを立ち上げておきましょう。これにはgrunt-contrib-connectを使います。
例のごとく
npm install grunt-contrib-connect --save-dev
して、
grunt.loadNpmTasks 'grunt-contrib-connect'
です。
3000番ポートでWebサーバが立ちあがるように、以下の記述を追加します。ドキュメントルートはdestにしています。
connect: server: options: port: 3000 base: 'dest'
これでgrunt connect
とすればサーバが立ち上がるのですが、せっかくなのでwatchとあわせてサーバが立ち上がるようにしましょう。
connectとwachtを実行するタスクを新しく定義します。名前はcwで。grunt.registerTask()
を使います。
grunt.registerTask 'cw', ['connect', 'watch']
これでgrunt cw
とすればサーバが立ち上がり、かつwatchの監視状態となります。
Webブラウザでlocalhost:3000にアクセスすればindex.html
が開くはずですので、そこでlivereloadプラグインのボタンを押し、src/js/*.js
を更新すれば、ブラウザが再読込されるはず、です!
このlivereload、地味なようですがとても快適で、これ無しではやってられなくなります。再読み込みだけさせてタスクを起動しない、という使い方もしているくらいです。未体験な方はぜひお試しください。
次回こそは色々なタスクを…
Gruntの復習 (3)タスクの書き方
Gruntの復習 (2)Gruntfile.jsを書く - 鴨のいいカモですにて色々タスクを追加してみると予告していたのですが、タスクの記述方法をきちんと理解していなかったことに気づいたので、そこを調べてみることにしました。
この部分です!
uglify: { dest: { // ターゲットdest files: { 'dest/js/scripts.min.js': ['src/js/*.js'] } } }
公式サイトのドキュメントであるConfiguring tasks - Grunt: The JavaScript Task Runnerを参考に。
まず基本
JSONで書く…と思ったら、JSONではなくJavaScriptだそうで。ということでJSONだけではなく、JavaScriptで処理を書いてもよいそうです。
タスクについて
Gruntはタスクランナーとありますが、そのタスクは、上記でいうとuglify
の箇所です。Gruntはなにもしないと何もタスクが使えませんが、前に書いたgrunt.loadNpmTasks()
でタスクを読み込むことで、利用可能なタスクを追加することができます。
プラグインの追加によってどのような名前のタスクが追加されるかは、追加するプラグインのドキュメントを確認してください。
タスクは、前回記述したようにgrunt タスク名
で実行することができます。
ちなみに、現在使えるタスクはgrunt --help
で確認することができます。「Available tasks」の箇所に利用可能なタスクが表示されるはずです。
ターゲットについて
タスクには、ターゲットと呼ばれるものを指定することができます。上記でいうとdest
の箇所です。ターゲットは任意の名前にすることができます。そして、複数定義することもできます。それにより、ターゲットごとに違う設定を実現することができます。以下はターゲットごとにminify結果の配置先を変更した例です。
uglify: { dest: { // ターゲットdest files: { 'dest/js/scripts.min.js': ['src/js/*.js'] } }, build: { // ターゲットbuild files: { 'build/js/scripts.min.js': ['src/js/*.js'] } } }
ターゲットを指定して実行するには、grunt タスク名:ターゲット名
でOKです。
ターゲットを指定しないでgrunt タスク名
とすると、全ターゲットを実行します。
変換元および変換先のファイル指定について
Gruntでは多くのタスクでファイルの変換や移動を行います。それらファイルの変換元と変換先は、ターゲットごとに以下の方法で指定することができるようです。
Compact Formatを用いる方法
以下のように、src
に変換元、dest
に変換先を指定します。
target: { src: ['src/a.js', 'src/b.js'], dest: 'dest/c.js', }
Lintのように出力先が不要な場合は'dest'を省略します。また、これにオプションのプロパティをつけくわえることも可能のようです。
Files Object Formatを用いる方法
以下のように、files
を使い、変換元(src/*.js)と変換先(dest/c.js)を指定します。また特徴として、次のようにマッピングを複数持つことができます。
target: { files: { 'dest/c.js': ['src/a.js', 'src/b.js'], 'dest/f.js': ['src/d.js', 'src/e.js'] } }
ただし、オプションのプロパティを付け加えることはできないようです。
Files Array Formatを用いる方法
files
を使い、かつsrc
とdest
も指定します。マッピングを複数持て、かつオプションのプロパティを付け加えることができるようです。ただ、記述が冗長ですね。
target: { files: [ {src: ['src/a.js', 'src/b.js'], dest: 'dest/c.js'}, {src: ['src/d.js', 'src/e.js'], dest: 'dest/f.js'} ] }
変換元と変換先それぞれのファイル指定には、直接指定の他にpath/**/*.js
のような、いわゆるGlobパターンも使用することができます。
optionsについて
options
プロパティを使用することで、タスクのデフォルト設定を上書きすることができます。options
プロパティはタスクごとのみではなく、ターゲットごとに指定することができます。こんな感じですね。
uglify: { options: { report: 'min' }, dest: { // ターゲットdest options: { beautify: true }, files: { 'dest/js/scripts.min.js': ['src/js/*.js'] } }, build: { // ターゲットbuild files: { 'build/js/scripts.min.js': ['src/js/*.js'] } } }
全体でreport: 'min'
(minifyのレポート出力)にし、ターゲットdest
のみbeautify: true
(デバッグ用に読みやすく整形)としています。
これで基本的なタスクの書き方はおさえられた感じです。その他にもファイル指定が便利になるプロパティや、テンプレートや外部データのインポートなどができるようです。詳しくは参考にしたConfiguring tasks - Grunt: The JavaScript Task Runnerを見てください。
次回は色々とタスクを追加してみようと思います、がはてさて。
Gruntの復習 (2)Gruntfile.jsを書く
前回の(1)インストールから初期設定に続き、実行するタスクを記述するGruntfile.jsを作成してみます。
Gruntfile.jsの構成
Gruntfile.jsは以下のような構成になっています。
module.exports = function(grunt) { grunt.initConfig({ // ここに実行タスクを記述する }); // プラグインを使用するときにタスクを読み込む記述を追加 // grunt.loadNpmTasks(''); // デフォルトタスクなどのタスク名を設定 grunt.registerTask('default', []); }
このように、grunt.initConfig()
にタスクを記述し、grunt.registerTask()
でdefaultなどにタスクを指定したり、タスク名を設定したりします。また、Gruntはプラグイン機構によりさまざまな機能を実現しています。プラグインを利用する際には、タスクを読み込むためにgrunt.loadNpmTasks()
を使う必要があります。
Gruntfile.jsへのタスク追加
プラグインgrunt-contrib-uglifyを使い、JavaScriptのminifyを実行してみましょう。
プラグインのインストール
以下のコマンドを実行します。gruntと同様、--save-dev
のオプションをつけてpackage.jsonへ記述が追加されるようにします。
npm install grunt-contrib-uglify --save-dev
タスク読み込み記述の追加
Gruntfile.jsへ以下を追記し、grunt-contrib-uglifyのタスクを読み込んで、使えるようにします。
grunt.loadNpmTasks('grunt-contrib-uglify');
現状のGruntfile.jsは以下のようになっています。
module.exports = function(grunt) { grunt.initConfig({ // ここに実行タスクを記述する }); // プラグインを使用するときにタスクを読み込む記述を追加 grunt.loadNpmTasks('grunt-contrib-uglify'); // デフォルトタスクなどのタスク名を設定 grunt.registerTask('default', []); }
実行タスクの記述
grunt.initConfig()
内に実行するタスクを記述します。ここでは仮に、src/js/*.js
をminifyしてdest/js/scripts.min.js
に出力するようにします。記述後のGruntfile.jsは以下のようになっています。
module.exports = function(grunt) { grunt.initConfig({ // ここに実行タスクを記述する uglify: { dest: { files: { 'dest/js/scripts.min.js': ['src/js/*.js'] } } } }); // プラグインを使用するときにタスクを読み込む記述を追加 grunt.loadNpmTasks('grunt-contrib-uglify'); // デフォルトタスクなどのタスクを設定 grunt.registerTask('default', []); }
デフォルトタスクは設定していませんが、この時点でもタスク名を指定したタスクの実行が可能です。今回の場合だと、grunt uglify
でminifyが実行されます。
デフォルトタスクの設定
defaultというタスク名のタスクを指定すると、grunt
を実行するだけでそのタスクが実行されます。ここではuglifyをデフォルトタスクにしてみましょう。grunt.registerTask()
の箇所を以下のように変更します。
grunt.registerTask('default', ['uglify']);
grunt
を実行するだけで、minifyが実行されるようになりました。
これで基本的なGruntfile.jsが完成です。Gruntfile.jsは次のようになります。
module.exports = function(grunt) { grunt.initConfig({ // ここに実行タスクを記述する uglify: { dest: { files: { 'dest/js/scripts.min.js': ['src/js/*.js'] } } } }); // プラグインを使用するときにタスクを読み込む記述を追加 grunt.loadNpmTasks('grunt-contrib-uglify'); // デフォルトタスクなどのタスク名を設定 grunt.registerTask('default', ['uglify']); }
ちなみに、Gruntfile.jsの代わりにCoffeeScriptを使ってGruntfile.coffeeを作成して使用することもできます。特にプラグインや設定の必要もありませんので、Coffeeに慣れている方はどうぞ。個人的にはそんなにCoffee使ってないのですが、Gruntの範疇なら簡単な記述しかしないので特に困ることもなく書けますし、なにより楽なんでいいかなと。
次回は色々とそれっぽいプラグインを追加してみることにします。と思ったのですが、タスクの記述方法についてきちんと理解していなかったため、そこを調べてみることにしました。
Gruntの復習 (1)インストールから初期設定
2014/1/2
Gruntは使っていたのですが、さわりしか使っていない気がしたので、整理も兼ねて学び直すことにしてみました。ちなににGruntのバージョンは0.4.2を使用しています。
インストール
Node.jsのインストール
Gruntの実行にはNode.jsが必要ですので、インストールします。
公式サイトのダウンロードからパッケージを入手してもよいですし、nodebrewを使うのも手です。
grunt-cliのインストール
Gruntのcliツールであるgrunt-cliをインストールします。
Node.jsのパッケージマネージャーであるnpmから、以下のコマンドでグローバル(システムで共有)インストールします。-gがグローバルインストールのオプションです。
npm install -g grunt-cli
プロジェクトへの導入
package.jsonの作成
Gruntの実行には、npmで使用するモジュール群の依存関係やバージョンを管理するpackage.jsonが必要です。この作成のため、プロジェクトの適当なディレクトリ(トップディレクトリなどでよいと思います)などで以下のコマンドを入力します。
npm init
すると、プロジェクト名やバージョン等々聞かれますので、それに答えていくとpackage.jsonができます。ちなみにnameとversionを書いておけば、あとは削除してもOKのようです。
gruntのインストール
先程はcliツールのgrunt-cliをインストールしましたが、今度は本体のgruntをインストールします。これはグローバルである必要はありませんので、package.jsonのあるディレクトリにて、以下のコマンドを実行してインストールしましょう。
npm install grunt --save-dev
ちなみに--save-devがは、このコマンドでインストールしたモジュールをpackage.jsonの記述にも追加する便利なオプションです。このように、必要なモジュールとして追加されています。
{ "name": "grunt-test", "version": "0.0.0", "devDependencies": { "grunt": "~0.4.2" } }
このように、package.jsonに必要なモジュールを記述しておくと、package.jsonを受け取った人はpackage.jsonのあるディレクトリでnpm install
を実行するだけで記述モジュールをインストールすることができます。複数人での開発などに有用ですね。
で、次は実行するタスクを記述するGruntfile.jsの作成ですが、今日はこのへんで次回に。
Bootstrap 3をWebページ制作環境にしよう(3) LESSファイルでのカスタマイズ
えらく前になりましたが、前回のGruntでのwatchとlivereload環境設定ができましたら、最後に書いてあるように、トップディレクトリでgrunt watchreload
を実行し、ブラウザ側の拡張機能をonにして、livereloadが実行されるようにしておきましょう。
今回は、スタイルのカスタマイズにCSSを編集するのではなく、LESSを編集して効率的にやりましょう、という話です。LESSでは変数や関数、mixinなどの機能が使えます。Bootstrap3でもそれらを活用してLESSからCSSを生成していますので、利用者もそれに乗っかってやれば、CSSを直接編集するのに比較して効率的に作業ができちゃいます。
LESSファイルの場所
トップディレクトリ配下のless
ディレクトリ配下にあります。
たくさんあって面食らうと思いますが、それらをざっくり解説します。
Bootstrap3 LESSファイルの解説
bootstrap.less
BootstrapにおけるLESSファイルの親玉です。LESSでは他のLESSファイルを読み込むことができますのが、ここではその機能を使い、色々なLESSファイルを読み込む記述をしています。これがCSSに変換されると、bootstrap(.min).cssになります。
もし使いたくない機能があれば、そn読み込み部分を削除してあげればOKです。
theme.less
Bootstrap3ではフラットデザインにしたくない人向けにbootstrap-theme.cssというスタイルシートを用意していますが、その変換元です。
variable.less
各種変数をここで定義しています。Bootstrap3のカスタマイズサービスで変更可能な変数は大抵ここにあります。このファイルを変更しながら作業するほうがすぐに反映結果を確認することができ、効率的ですね。おそらく、一番変更することになるでしょう。
中の変数については、変数名でなんとなく想像がつくでしょう、ということで割愛します。
mixin.less
clearfixやCSS3機能のベンダプレフィックス付与mixinが定義されています。ここは変更するというよりも、どのようなmixinが定義されているか確認して、余裕があればそれを利用する感じでしょうか。
残りはざっくりとした解説です。
スタイルのベースとなるLESSファイル
- grid.less グリッドの定義
- normalize.less normalize.css のLESS版
- print.less 印刷用スタイル
- scaffolding.less スキャフォルド
- type.less タイポグラフィ
部品定義のLESS
名前でわかると思います。
- alerts.less
- badges.less
- breadcrumbs.less
- button-groups.less
- buttons.less
- carousel.less
- close.less
- code.less
- dropdowns.less
- forms.less
- glyphicons.less
- input-groups.less
- jumbotron.less
- labels.less
- list-group.less
- media.less
- modals.less
- navbar.less
- navs.less
- pager.less
- pagination.less
- panels.less
- popovers.less
- progress-bars.less
- responsive-utilities.less
- tables.less
- thumbnails.less
- tooltip.less
- wells.less
その他
- component-animations.less フェードアウトなどアニメーションの定義
- utilities.less ユーティリティクラス
変更のポイント
まずはvariable.lessを変更して、LESSそのものやBootstrap3でのLESSファイルの構成に慣れてきたらスタイルのベースとなっているものに手を出していく感じになるかと思います。
ということで、このシリーズはひとまずこれで終わり、ということで。