<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="ja-JP" xmlns="http://www.w3.org/2005/Atom">
  <id>https://blog.satooshi.jp</id>
  <link rel="alternate" type="text/html" href="https://blog.satooshi.jp"/>
  <link rel="self" type="application/atom+xml" href="https://blog.satooshi.jp/atom.xml"/>
  <link rel="hub" href="https://satooshi.superfeedr.com"/>
  <link rel="hub" href="https://pubsubhubbub.appspot.com"/>
  <title>
    <![CDATA[北村聡士のブログ]]>
  </title>
  <updated>2019-01-06T08:59:00Z</updated>
  <author>
    <name>
      <![CDATA[北村聡士]]>
    </name>
  </author>
  <entry>
    <id>https://blog.satooshi.jp/2019/01/06/look-back-2018</id>
    <published>2019-01-06T08:59:00Z</published>
    <updated>2019-01-06T08:59:00Z</updated>
    <link rel="alternate" type="text/html" href="https://blog.satooshi.jp/2019/01/06/look-back-2018"/>
    <title type="html">
      <![CDATA[2018年を振り返る]]>
    </title>
    <content type="html">
      <![CDATA[<p>2017年末から都内の会社で働き始めて、一年ほど経過しました。新しい年でもあるので、自分が一年間どんな仕事をやってきたのか、振り返ってみることにしました。ベトナムから帰国して一年半ほどが経過し、仕事をするのも久しぶりだったので、入社前後は不安要素が多かった気がします。</p>

<p>会社としては、</p>

<ul>
<li>若いベンチャー</li>
<li>平均年齢も若め</li>
<li>B向けwebサービスの開発

<ul>
<li>webはRails + React</li>
<li>iOSアプリとAndroidアプリもある</li>
</ul></li>
</ul>

<p>という属性です。</p>

<!-- more -->

<h2>問題多発</h2>

<p>入社してすぐの頃はバグが頻発していて、全体的に慌ただしい状況でした。この問題はずっと引きずっていて、当時に比べればかなりマシになってきているものの、まだ収束していません。入って一ヶ月ぐらいの頃に、社内会議で「全然テストしてないですよね？」という発言をした記憶があります。</p>

<p>原因としては、</p>

<ul>
<li>仕様・設計に対してテストするべきはずが、まずい設計のせいで自動テストが書けない

<ul>
<li>アプリケーションアーキテクチャがまずい</li>
<li>数百行の長いメソッドを久しぶりに見た</li>
<li>god object的なやつも見た</li>
<li>適切にレイヤー分けできていない</li>
</ul></li>
<li>仕様が不定なせいでテストケースも不定・実装漏れが発生

<ul>
<li>画面コンポーネントをテストしてない</li>
<li>画面遷移・シナリオテストをしていない</li>
</ul></li>
</ul>

<p>といった要因でした。</p>

<h2>性能バグ</h2>

<p>サービス停止につながる致命的なバグもありました。春先にかけて、ユーザー数の多い企業が利用開始となり、利用者が増える月末にサービス停止が多発しました。主な原因としては、DB負荷です。参照系のAPIに関してはおよそ一ヶ月ほどで収束しました。平均レスポンスタイムは600-670ms程度から、5月以降から現在までは120-150ms程度で推移しています。更新系はまだ遅い場合があるものの、対処できてません。</p>

<h3>Railsのeager_loadが多用されている</h3>

<p>10個以上のテーブルがjoinされている箇所がありました。<code>preload</code>にして大体解決しました。</p>

<h3>N+1問題</h3>

<p>これも<code>preload</code>にして大体解決しました。</p>

<p>どちらにせよ、データ数が少ない状態でしかテストしておらず、100件程度のデータを入れればすぐにわかるような問題がずっと放置されていました。</p>

<h3>ページネーションしていない</h3>

<p>あればあるだけデータを表示してしまう一覧画面がいくつかあり、1000件のデータが表示されるまで1分近く待つような状況もありました。致命的なところはページネーションするようにして解決しました。</p>

<h3>pluckした長いidリストがログに出ていた</h3>

<p>あるテーブルのidを<code>pluck</code>して、それを後続のSQLに渡していた箇所があり、それがスロークエリーを引き起こしていました。さらにスロークエリーのログに、そのSQLのwhere句にある長いidリストが大量に書き込まれてしまい、ログファイルを保管していたサーバーのディスク容量が圧迫され、停止するというのもありました。</p>

<ul>
<li>スロークエリーの基準を緩くした</li>
<li><code>pluck</code>から<code>select</code>に変えて、SQLを1つにまとめた</li>
</ul>

<h3>スロークエリー</h3>

<p>あとはほとんどが普通のスロークエリーだったので、NewRelicでレスポンスの遅いAPIを見つけてチューニングしていきました。必要なindexが無かったもの・非効率なSQLなど、この辺はセオリー通りの対応です。</p>

<h3>今振り返ってみて</h3>

<p>月末の利用者が多いというサービス特性があるにも関わらず、実質的に月末ちゃんと動かないサービスを提供してお金をもらうのは詐欺に近いものがあるなと思いました。対応が後手回ってしまっていたのも、手が回っていなかった事以上に、チームの作業限界を大幅に超過していた事に気が付かなかったのが根本的なヤバさかなと思いました。後述するPM不在のデメリットがもろに出ていたように思います。</p>

<h2>プロジェクト管理の話</h2>

<p>どのレベルでもマネージメント能力のある人が一人もいません。それを象徴するような愚痴を聞くこともあります。そういった現状に課題を感じた開発メンバーが主体となり、秋ごろからはPMBOK勉強会が始まりました。</p>

<p>自分も一応参加してみて、基本的な知識が全くない状態で仕事をしている人が多いという事実が分かりました。自分の場合はSIer出身なので、上流から下流まで、多少なりとも開発に関わることは勉強したり、仕事で一通り使う機会があったためその基礎はあったと思っていますが、このあたりの知識の欠如が発覚してこれが仕事の仕方にも大きく影響しているように思いました。</p>

<p>一番ヤバいのは、炎上しているのにそれに気づける環境にないという事です。</p>

<p>以前にも、1on1ミーティングでこの辺りの必要性は話をしてみたものの、あまり理解されているようには思えません。スキル・知識がないことを非難するつもりは全くなくて、毎月5-10時間程度の勉強時間を確保すれば、より円滑な仕事ができるのに、そうしない・できない理由はなんなんだろうかというのが自分の問題意識です。</p>

<ul>
<li>何かが足りていないけどそれが何であるか、理解できていない</li>
<li>何かが足りていないという自覚が無い</li>
</ul>

<p>という可能性なのかなと思っていますが。日本人の場合、社会人になると本を読まない・勉強しないというのはすでによく知られた話のようで、2018年はそういった記事をちょくちょく見かけました。</p>

<h3>朝会</h3>

<p>入社以前から、朝会をやっていて、</p>

<ul>
<li>昨日やったこと</li>
<li>今日やること</li>
</ul>

<p>をチームで共有しています。しかし、各自のタスクはその人自身しか把握していないため、先週言っていたタスクが終わっていないなど、進行中のタスクが多くなる状況が発生しています。</p>

<p>主にPRの指摘・修正が繰り返し発生している状態で、別の割り込みタスクが発生し、・・・というのが原因でした。カンバンの本を読むと、どこかのタイミングで作業調整をして、進行中のタスクを終わらせるというのが一般的な話のようです。</p>

<ul>
<li>終わらせることを最優先にする</li>
<li>終わるまで始めない</li>
</ul>

<p>という話をしてみたものの、ユーザーからの問い合わせに対して、当日中に一次回答するという目標もあり、なかなか完遂するのは難しい状況です。</p>

<h3>PRがたまる問題</h3>

<p>よく聞くプルリクエストがたまる問題も発生しました。各自が優先事項をもってタスクに取り組んでいますが、チームとしての優先事項が見えてないと、完了するPRが増えないという話です。開発者同士でレビューしているので、レビュワーも同様に開発タスクを持っていて、自身のタスクとレビューとどちらを優先するべきなのか、判断をつけられなくなっていました。</p>

<p>現状としては、自分が専任レビュワーになっているような状況です。一日中レビューしているので、全くPRがマージされないという状況はかなり減りましたが、それでも複数人からPRが来るので、変更点の多いPRだとなかなかレビューが進まないという課題が残っています。</p>

<h2>自動テスト</h2>

<p>秋ごろからは、Rails5へのバージョンアップも見据えて、自動テストを増やすべく、毎週木曜日がテストの日になりました。テストで有名な業界人である「らいおんさん」の写真を私がslackに貼りつつ、各自が「今日はxxのテストを書きます」と宣言してテストを書いていくスタイルです。</p>

<p>レビューをしていて、RSpecの使い方が分からないという人が多数だったため、esaにガイドラインを書きつつ啓蒙していきました。現在は主に2種類の自動テストを書いています。e2eテストは未着手なので、system spec/feature specはまだ対応できていません。</p>

<ul>
<li>ドメイン層のユニットテスト</li>
<li>アプリケーション層のインテグレーションテスト</li>
</ul>

<h3>途中経過</h3>

<p>取り組みを始めて1ヶ月ほどで、メンバーの書くテストコードが劇的に良くなったと実感しています。木曜日という練習時間を確保したことで、テストコードを書くハードルが下がり、各自の案件のPRでもテストコードをちゃんと書けるようになりました。また、バグのあるコードを書いていても、しっかりテストが失敗したという状態になってきました。</p>

<h3>カバレッジ</h3>

<p>サービス上、重要なクラスに対しての自動テストを増やすのが目的なので、個人的にはカバレッジxx%という目標はあまり意味があるとは思っていませんが、開発チームの目標としてはまだ30%台という状況です。</p>

<h2>手動テスト</h2>

<p>画面遷移を伴うシナリオテストなど、実際に手を動かして実施するテストも依然として必要ではあります。テストケースをどう記述するかで迷っている部分はありますが、あまりガッチリした操作・期待値を書くとメンテ辛そうという気がしています。テストケースをmdファイルに書いて、githubで見ながらテストできるといいかなと思ってます。</p>

<ul>
<li>メニュー &gt; xx登録画面を開く

<ul>
<li>xxに金額を入力する</li>
<li>保存する</li>
</ul></li>
<li>メニュー &gt; xx一覧画面を開く

<ul>
<li>保存したデータが表示されていること</li>
</ul></li>
</ul>

<p>みたいな感じで。実際には不正データの場合にちゃんとエラーメッセージが出てくるかどうかとか、もうちょっと細かいことを書いていくと思います。</p>

<h2>勉強</h2>

<p>上で書いているように、直近の課題はスキルの底上げです。過去の失敗から反省すべきこと・これから達成したいことに対して、レベルと装備が足りていないという状況だからです。レビューの時間を増やしたのもその一環で、設計がまずいコードをどう改善するか理解してもらうという意図もありますし、テストの書き方を社内ドキュメントに書いたのもそういう目的です。</p>

<p>時間を確保して実際に行動するというのが大事なところで、テストに関しては実際に業務時間を割り当ててメンバーにやってもらったら意外なほど上手になったわけですし、スキルの習得に関して不得意なわけでもなく、やったらやった分効果が出てくるのかなと思っているところです。</p>

<p>自分が先頭に立ってやっている部分が大きいので、業務時間にコードを書く時間が全然なくなったという現実もあります。あと何ヶ月続けるんだろうかと考えると、この点に関しては不満ですね。正直な事を言えば、各自で「練習時間」を増やして欲しいですし。早く帰ってその時間を確保して欲しいですが、残業している人がかなり多く、組織としては残業しても全く構わないという方針なので、そう簡単に変わらないだろうなという諦めもあります。間違った方向に時間を使って失敗してきたように見えるので、どうなのかなと思っていますが。とはいえ、実業務で使っている技術にキャッチアップできていない状況を放置しても、大して良い事がないのは前職で経験しています。つまりこの辺りが現在のチームの最大速度になります。</p>

<p>現職まで1年半近く仕事をしてなかったため、入社してからはRailsの使い方を思い出すとか、昔読んだ技術書を読み返すとか、新しい事を覚えるのにあまり時間を使えなかったので、今年は少しずつ時間を取っていきたいです。</p>
]]>
    </content>
    <author>
      <name>
        <![CDATA[北村聡士]]>
      </name>
    </author>
  </entry>
  <entry>
    <id>https://blog.satooshi.jp/2016/12/19/resize-image-by-gulp</id>
    <published>2016-12-19T22:15:00Z</published>
    <updated>2016-12-19T22:15:00Z</updated>
    <link rel="alternate" type="text/html" href="https://blog.satooshi.jp/2016/12/19/resize-image-by-gulp"/>
    <title type="html">
      <![CDATA[gulpで画像サイズ変更]]>
    </title>
    <content type="html">
      <![CDATA[<p>ブログに使う画像を処理する時に、リサイズしてファイルサイズを軽量に調整してほしい。gulpだとimageminを使うようだ。</p>

<!-- more -->

<h2>説明書</h2>

<ul>
<li><a href="https://github.com/scalableminds/gulp-image-resize">https://github.com/scalableminds/gulp-image-resize</a>

<ul>
<li>ImageMagick、GraphicsMagickを使ってリサイズするやつ</li>
</ul></li>
<li><a href="https://github.com/sindresorhus/gulp-imagemin">https://github.com/sindresorhus/gulp-imagemin</a>

<ul>
<li>gif, jpeg, png, svg画像のロスレスオプティマイザーがバンドルされている</li>
</ul></li>
</ul>

<p>元画像が別ファイルとして残っているので、ロスレスである必要もないし、ファイルサイズを抑えられる別のオプティマイザーを使う。</p>

<ul>
<li><a href="https://github.com/imagemin/imagemin-jpegoptim">https://github.com/imagemin/imagemin-jpegoptim</a></li>
<li><a href="https://github.com/pornel/pngquant">https://github.com/pornel/pngquant</a></li>
</ul>

<h3>環境</h3>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>node -v
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>v6.9.1
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm -v
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'>3.10.8</div></div></pre></div></figure>

<h3>インストール</h3>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>npm install --save-dev gulp-image-resize gulp-imagemin imagemin-jpegoptim imagemin-pngquant</div></div></pre></div></figure>

<h3>imagesタスク</h3>

<figure class='code-highlight-figure'><figcaption class='code-highlight-caption'><span class='code-highlight-caption-title'>images.babel.js</span></figcaption><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">gulp</span> <span class="nx">from</span> <span class="s1">&#39;gulp&#39;</span><span class="p">;</span>
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">gulpLoadPlugins</span> <span class="nx">from</span> <span class="s1">&#39;gulp-load-plugins&#39;</span><span class="p">;</span>
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">pngquant</span> <span class="nx">from</span> <span class="s1">&#39;imagemin-pngquant&#39;</span><span class="p">;</span>
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">jpegoptim</span> <span class="nx">from</span> <span class="s1">&#39;imagemin-jpegoptim&#39;</span><span class="p">;</span>
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">$</span> <span class="o">=</span> <span class="nx">gulpLoadPlugins</span><span class="p">();</span>
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">imageSrc</span> <span class="o">=</span> <span class="s1">&#39;frontend/app/images/**/*.+(jpg|jpeg|png|gif|svg)&#39;</span><span class="p">;</span>
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">imageBase</span> <span class="o">=</span> <span class="s1">&#39;frontend/app/images&#39;</span><span class="p">;</span>
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">imageDest</span> <span class="o">=</span> <span class="s1">&#39;public/images&#39;</span><span class="p">;</span>
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kd">var</span> <span class="nx">imageminOptions</span> <span class="o">=</span> <span class="p">&#x7b;</span>
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">optimizationLevel</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">progressive</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">interlaced</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">svgoPlugins</span><span class="o">:</span> <span class="p">[&#x7b;</span><span class="nx">cleanupIDs</span><span class="o">:</span> <span class="kc">false</span><span class="p">&#x7d;]</span>
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;;</span>
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kd">var</span> <span class="nx">getPlugins</span> <span class="o">=</span> <span class="p">(</span><span class="nx">pngQuality</span><span class="p">,</span> <span class="nx">jpegQuality</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="k">return</span> <span class="p">[</span>
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">$</span><span class="p">.</span><span class="nx">imagemin</span><span class="p">.</span><span class="nx">gifsicle</span><span class="p">(),</span>
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">jpegoptim</span><span class="p">(&#x7b;</span><span class="nx">progressive</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">max</span><span class="o">:</span> <span class="nx">jpegQuality</span><span class="p">&#x7d;),</span>
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">pngquant</span><span class="p">(&#x7b;</span><span class="nx">quality</span><span class="o">:</span> <span class="nx">pngQuality</span><span class="p">,</span> <span class="nx">speed</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">posterize</span><span class="o">:</span> <span class="mi">4</span><span class="p">&#x7d;),</span>
</div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">$</span><span class="p">.</span><span class="nx">imagemin</span><span class="p">.</span><span class="nx">svgo</span><span class="p">(),</span>
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="p">];</span>
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;;</span>
</div></div><div data-line='27' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='28' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kd">var</span> <span class="nx">getResizeOptions</span> <span class="o">=</span> <span class="p">(</span><span class="nx">width</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='29' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="k">return</span> <span class="p">&#x7b;</span>
</div></div><div data-line='30' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">width</span><span class="o">:</span> <span class="nx">width</span><span class="p">,</span>
</div></div><div data-line='31' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">upscale</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</div></div><div data-line='32' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">imageMagick</span><span class="o">:</span> <span class="kc">true</span>
</div></div><div data-line='33' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="p">&#x7d;;</span>
</div></div><div data-line='34' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;;</span>
</div></div><div data-line='35' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='36' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;images:mobile&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='37' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="kr">const</span> <span class="nx">resizeOptions</span> <span class="o">=</span> <span class="nx">getResizeOptions</span><span class="p">(</span><span class="mi">400</span><span class="p">);</span>
</div></div><div data-line='38' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="kr">const</span> <span class="nx">plugins</span> <span class="o">=</span> <span class="nx">getPlugins</span><span class="p">(</span><span class="s1">&#39;70-90&#39;</span><span class="p">,</span> <span class="mi">60</span><span class="p">);</span>
</div></div><div data-line='39' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='40' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="k">return</span> <span class="nx">gulp</span><span class="p">.</span><span class="nx">src</span><span class="p">(</span><span class="nx">imageSrc</span><span class="p">,</span> <span class="p">&#x7b;</span><span class="nx">base</span><span class="o">:</span> <span class="nx">imageBase</span><span class="p">&#x7d;)</span>
</div></div><div data-line='41' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">changed</span><span class="p">(</span><span class="nx">imageDest</span><span class="p">))</span>
</div></div><div data-line='42' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">imageResize</span><span class="p">(</span><span class="nx">resizeOptions</span><span class="p">))</span>
</div></div><div data-line='43' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">imagemin</span><span class="p">(</span><span class="nx">plugins</span><span class="p">,</span> <span class="nx">imageminOptions</span><span class="p">))</span>
</div></div><div data-line='44' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">rename</span><span class="p">((</span><span class="nx">path</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='45' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="nx">path</span><span class="p">.</span><span class="nx">basename</span> <span class="o">+=</span> <span class="s1">&#39;-small&#39;</span><span class="p">;</span>
</div></div><div data-line='46' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">&#x7d;))</span>
</div></div><div data-line='47' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">gulp</span><span class="p">.</span><span class="nx">dest</span><span class="p">(</span><span class="nx">imageDest</span><span class="p">));</span>
</div></div><div data-line='48' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;);</span>
</div></div><div data-line='49' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='50' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;images&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;clean:public:images&#39;</span><span class="p">,</span> <span class="s1">&#39;images:mobile&#39;</span><span class="p">]);</span></div></div></pre></div></figure>

<p>このタスクを実行すると、モバイル向けに小さめサイズの画像を生成できる。</p>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'>npm run gulp images</div></div></pre></div></figure>

<h3>運用方法</h3>

<p>一度最適化した画像は何度も最適化する必要はないし、最適化が完了した画像はS3などに保存しておいて、必要な時に取りに行く方がgulpの実行時間が減らせると思う。と考えると、defaultタスクからはimagesタスクを外しておいて、画像を追加した時だけimagesタスクを実行し、S3に保存するというのが良さそう。</p>

<p>S3に画像をアップロードすると、AWS Lambdaで画像を最適化して、S3に保存してくれる、というのが一番いい方法かもしれない。その場合、どのくらいのファイルサイズになるか、最適化オプションを調整したい時にはこのタスクが役に立つと思う。</p>
]]>
    </content>
    <author>
      <name>
        <![CDATA[北村聡士]]>
      </name>
    </author>
  </entry>
  <entry>
    <id>https://blog.satooshi.jp/2016/12/18/save-shipping-on-bodybuilding-com</id>
    <published>2016-12-18T16:02:00Z</published>
    <updated>2016-12-18T16:02:00Z</updated>
    <link rel="alternate" type="text/html" href="https://blog.satooshi.jp/2016/12/18/save-shipping-on-bodybuilding-com"/>
    <title type="html">
      <![CDATA[bodybuilding.comで送料を抑えてサプリメントを買う]]>
    </title>
    <content type="html">
      <![CDATA[<p>アメリカ最大のフィットネスサイト、<a href="https://www.bodybuilding.com">bodybuilding.com</a>では筋トレに役立つ記事や、<a href="https://www.youtube.com/user/bodybuildingcomvideo">YouTubeでトレーニング動画</a>などを配信している。また、筋トレ用サプリメントやシェーカーなどの品揃えが豊富で、安く販売されており、筋トレ業界のアマゾンと言っていい存在だ。この記事では送料を抑えて、安く購入する方法を紹介する。</p>

<p>アマゾンのコメント欄を見ると、日本の筋トレ業界では<a href="http://jp.iherb.com/">iHerb</a>が人気らしい。</p>

<!-- more -->

<h2>筋トレしてます</h2>

<p>ベトナムで生活するようになってから、体調が非常に悪くなったこともあり、2年前から適度な有酸素運動を、1年半前から自重トレーニングを始め、今年7月に日本に帰国してからジムに通ってウェイトトレーニングを始めた。9月の記録を見返すと太ももが5cm以上太くなっている。2016年4月からは食事を全て見直して、体調は劇的に改善した。現在のBIG3の1rep maxはこの通り。</p>

<ul>
<li>ベンチプレス 72.5kg</li>
<li>スクワット 100kg</li>
<li>デッドリフト 115kg</li>
</ul>

<p>さて。日本で必要なサプリメントを買おうとすると、そもそも売ってないか、非常に値段が高い。筋トレといえばアメリカ。サプリメント大国なので、手頃な値段で筋トレ用サプリメントが販売されている。</p>

<p><a href="https://www.bodybuilding.com">bodybuilding.com</a>では海外シッピングにも対応しているのだが、送料が高い。重量や配送日数にもよるが、ちょっと重いものになると¥2,000以上はかかる。しかし、軽い商品であれば¥400程度に送料を抑えることができる（円安になってきたので、現時点では¥448になっている）。</p>

<h2>どの商品が¥400で配送できるのか</h2>

<p>具体的には、400gまでの商品を注文すると一番安い価格帯の送料が適用されるようだ。</p>

<h3>シェーカー</h3>

<p>プロテインやアミノ酸などのサプリメントを混ぜるのに欠かせないのがシェーカー。有名ブランドBlenderBottleの中で最大サイズの<a href="http://jp.bodybuilding.com/store/blenderbottle/pro45.html">BlenderBottle Pro45</a>をカートに入れてみた。</p>

<p><img src="/images/2016-12-18-blenderbottle1.png" width="640"  ></p>

<p>送料は¥448となっている。</p>

<h3>クレアチン</h3>

<p><a href="http://jp.bodybuilding.com/store/opt/crea.html">Optimum Nutritionのクレアチン</a> 300gをカートに入れてみた。</p>

<p><img src="/images/2016-12-18-creatine1.png" width="640"  ></p>

<p>これも送料は¥448だった。</p>

<h3>EAA</h3>

<p><a href="http://jp.bodybuilding.com/store/cellucor/alpha-amino.html">CellucorのAlpha Amino</a> 30 servingsをカートに入れてみた。一杯で12.7gなので、重量は381gである。</p>

<p><img src="/images/2016-12-18-alpha-amino1.png" width="640"  ></p>

<p>送料は¥448。</p>

<h3>グルタミン</h3>

<p><a href="http://jp.bodybuilding.com/store/prima/glut.html">PrimaForceのGlutaForm</a> 400gをカートに入れてみた。</p>

<p><img src="/images/2016-12-18-gluta-form1.png" width="640"  ></p>

<p>送料¥448。</p>

<h3>BCAA</h3>

<p><a href="http://jp.bodybuilding.com/store/gaspari-nutrition/aminolast.html">Gaspari NutritionのAMINOLAST</a> 420gをカートに入れてみた。</p>

<p><img src="/images/2016-12-18-aminolast1.png" width="640"  ></p>

<p>送料は¥1,804となった。</p>

<h2>400g以下であれば送料は安い</h2>

<p>結果としては、400g以下の商品であればSuperSaverの送料を¥448に抑えることができることが分かった。アミノラストがギリギリアウトなのが悔しい。</p>

<p>Super Saverで注文すると、安い代わりに配送日数がかかる。何度か注文した結果、7-21日程度で配送された。届かなかったことは今のところ一度もない。クリスマスシーズンのせいか、PriorityとEconomyが異常に高い。</p>
]]>
    </content>
    <author>
      <name>
        <![CDATA[北村聡士]]>
      </name>
    </author>
  </entry>
  <entry>
    <id>https://blog.satooshi.jp/2016/12/17/watch-file-and-reload-web-browser-by-gulp-browsersync</id>
    <published>2016-12-17T19:51:00Z</published>
    <updated>2016-12-17T19:51:00Z</updated>
    <link rel="alternate" type="text/html" href="https://blog.satooshi.jp/2016/12/17/watch-file-and-reload-web-browser-by-gulp-browsersync"/>
    <title type="html">
      <![CDATA[gulpとBrowsersyncを使ってファイル変更検知と自動ブラウザリロードする]]>
    </title>
    <content type="html">
      <![CDATA[<p>gulpと<a href="https://browsersync.io/">Browsersync</a>を使うと、scssファイルの変更を検知したら、コンパイルしてブラウザを自動リロードすることができる。</p>

<!-- more -->

<h2>説明書</h2>

<ul>
<li><a href="https://browsersync.io/docs/gulp">Browsersync + Gulp.js</a></li>
</ul>

<h3>環境</h3>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>node -v
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>v6.9.1
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm -v
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'>3.10.8</div></div></pre></div></figure>

<h3>インストール</h3>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm install browser-sync --save-dev
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>browsersync@1.0.0 /home/vagrant/work/browsersync
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>└─┬ browser-sync@2.18.5</div></div></pre></div></figure>

<h3>stylesタスク</h3>

<p><a href="/2016/12/14/libsass-with-gulp">gulpからlibsassを使う</a>の記事に書いたのと同じタスクを使う。cssを書き出した後に<code>browserSync.stream()</code>を入れておく。</p>

<figure class='code-highlight-figure'><figcaption class='code-highlight-caption'><span class='code-highlight-caption-title'>styles.babel.js</span></figcaption><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">gulp</span> <span class="nx">from</span> <span class="s1">&#39;gulp&#39;</span><span class="p">;</span>
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">gulpLoadPlugins</span> <span class="nx">from</span> <span class="s1">&#39;gulp-load-plugins&#39;</span><span class="p">;</span>
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">browserSync</span> <span class="nx">from</span> <span class="s1">&#39;browser-sync&#39;</span><span class="p">;</span>
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">$</span> <span class="o">=</span> <span class="nx">gulpLoadPlugins</span><span class="p">();</span>
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">src</span> <span class="o">=</span> <span class="s1">&#39;frontend/app/styles&#39;</span><span class="p">;</span>
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">const</span> <span class="nx">dist</span> <span class="o">=</span> <span class="s1">&#39;public/assets/styles&#39;</span><span class="p">;</span>
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;styles&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="k">return</span> <span class="nx">gulp</span><span class="p">.</span><span class="nx">src</span><span class="p">(</span><span class="nx">src</span> <span class="o">+</span> <span class="s1">&#39;/*.scss&#39;</span><span class="p">)</span>
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">plumber</span><span class="p">())</span>
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">sourcemaps</span><span class="p">.</span><span class="nx">init</span><span class="p">())</span>
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">sass</span><span class="p">.</span><span class="nx">sync</span><span class="p">(&#x7b;</span>
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="nx">outputStyle</span><span class="o">:</span> <span class="s1">&#39;expanded&#39;</span><span class="p">,</span>
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="nx">precision</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span>
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="nx">includePaths</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;.&#39;</span><span class="p">]</span>
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">&#x7d;).</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="nx">$</span><span class="p">.</span><span class="nx">sass</span><span class="p">.</span><span class="nx">logError</span><span class="p">))</span>
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="c1">//.pipe($.autoprefixer(&#x7b;browsers: [&#39;last 1 version&#39;]&#x7d;)) // vendor prefixを使いたい場合</span>
</div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">sourcemaps</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">))</span>
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">gulp</span><span class="p">.</span><span class="nx">dest</span><span class="p">(</span><span class="nx">dist</span><span class="p">))</span>
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">browserSync</span><span class="p">.</span><span class="nx">stream</span><span class="p">());</span>
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;);</span>
</div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;styles:minify&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;styles&#39;</span><span class="p">],</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="k">return</span> <span class="nx">gulp</span><span class="p">.</span><span class="nx">src</span><span class="p">(</span><span class="nx">dist</span> <span class="o">+</span> <span class="s1">&#39;/**/*.css&#39;</span><span class="p">,</span> <span class="p">&#x7b;</span><span class="nx">base</span><span class="o">:</span> <span class="nx">dist</span><span class="p">&#x7d;)</span>
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="k">if</span><span class="p">(</span><span class="s1">&#39;*.css&#39;</span><span class="p">,</span> <span class="nx">$</span><span class="p">.</span><span class="nx">minifyCss</span><span class="p">(&#x7b;</span><span class="nx">compatibility</span><span class="o">:</span> <span class="s1">&#39;*&#39;</span><span class="p">&#x7d;)))</span>
</div></div><div data-line='27' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">$</span><span class="p">.</span><span class="nx">rename</span><span class="p">((</span><span class="nx">path</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='28' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="nx">path</span><span class="p">.</span><span class="nx">basename</span> <span class="o">+=</span> <span class="s1">&#39;.min&#39;</span><span class="p">;</span>
</div></div><div data-line='29' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">&#x7d;))</span>
</div></div><div data-line='30' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">gulp</span><span class="p">.</span><span class="nx">dest</span><span class="p">(</span><span class="nx">dist</span><span class="p">));</span>
</div></div><div data-line='31' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;);</span></div></div></pre></div></figure>

<h3>serveタスク</h3>

<ul>
<li>notify: trueにすると、画面右上に&quot;Connected to BrowserSync&quot;みたいなメッセージが表示される</li>
<li>proxy: Railsアプリを動かしている場合は、webrickなどのIPやポート番号を設定する</li>
<li>port: ブラウザーからアクセスする場合のポート番号。開発時にhttp://192.168.35.21:3000を開いていた場合はhttp://192.168.35.21:9000になる</li>
<li>ui: 設定用画面を有効にするかどうか。<code>{port: 9001}</code>にすると9001番ポートで設定用画面にアクセスできる。</li>
</ul>

<figure class='code-highlight-figure'><figcaption class='code-highlight-caption'><span class='code-highlight-caption-title'>serve.babel.js</span></figcaption><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">gulp</span> <span class="nx">from</span> <span class="s1">&#39;gulp&#39;</span><span class="p">;</span>
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="kr">import</span> <span class="nx">browserSync</span> <span class="nx">from</span> <span class="s1">&#39;browser-sync&#39;</span><span class="p">;</span>
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;serve&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;serve:styles&#39;</span><span class="p">],</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;);</span>
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="s1">&#39;serve:styles&#39;</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">&#x7b;</span>
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">browserSync</span><span class="p">(&#x7b;</span>
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="c1">// show &quot;Connected to BrowserSync&quot; at right-top when reloaded</span>
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">notify</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="c1">// proxy original http://192.168.35.21:3000</span>
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">proxy</span><span class="o">:</span> <span class="s1">&#39;192.168.35.21:3000&#39;</span><span class="p">,</span>
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="c1">// Let&#39;s access to http://192.168.35.21:9000</span>
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">port</span><span class="o">:</span> <span class="mi">9000</span><span class="p">,</span>
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nx">ui</span><span class="o">:</span> <span class="kc">false</span>
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="c1">//ui: &#x7b;port: 9001&#x7d;</span>
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="p">&#x7d;);</span>
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nx">gulp</span><span class="p">.</span><span class="nx">watch</span><span class="p">(</span><span class="s1">&#39;frontend/app/styles/**/*.scss&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;styles&#39;</span><span class="p">]);</span>
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;);</span></div></div></pre></div></figure>

<h2>npm-scripts</h2>

<p><a href="https://docs.npmjs.com/misc/scripts">説明書</a>によると、package.jsonに&quot;scripts&quot;フィールドを設定しておくと、<code>npm run gulp</code>でnode_modules/.bin/gulpを実行できるようになる。</p>

<figure class='code-highlight-figure'><figcaption class='code-highlight-caption'><span class='code-highlight-caption-title'>package.json</span></figcaption><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7b;</span>
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="nt">&quot;scripts&quot;</span><span class="p">:</span> <span class="p">&#x7b;</span>
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="nt">&quot;gulp&quot;</span><span class="p">:</span> <span class="s2">&quot;gulp&quot;</span>
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="p">&#x7d;</span>
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="p">&#x7d;</span></div></div></pre></div></figure>

<p>これで、<code>npm run gulp serve</code>としておくと、勝手にコンパイル＋自動リロードができるようになった。</p>

<h2>他のツールを使う場合</h2>

<ul>
<li><a href="https://github.com/Browsersync/recipes">https://github.com/Browsersync/recipes</a>

<ul>
<li>他のツールとの組み合わせの設定例が載ってる。</li>
</ul></li>
</ul>
]]>
    </content>
    <author>
      <name>
        <![CDATA[北村聡士]]>
      </name>
    </author>
  </entry>
  <entry>
    <id>https://blog.satooshi.jp/2016/12/16/bump-package-version-npm-shrinkwrap</id>
    <published>2016-12-16T23:11:00Z</published>
    <updated>2016-12-16T23:11:00Z</updated>
    <link rel="alternate" type="text/html" href="https://blog.satooshi.jp/2016/12/16/bump-package-version-npm-shrinkwrap"/>
    <title type="html">
      <![CDATA[npm shrinkwrapしたパッケージのバージョンを上げる]]>
    </title>
    <content type="html">
      <![CDATA[<p><a href="/2016/12/15/npm-shrinkwrap-to-lock-down-versions">前回の記事</a>でnpmパッケージのバージョンを固定する方法を書いた。固定したバージョンをアップデートする場合、更新されたnpm-shrinkwrap.jsonを配布した後に実施するのは<code>npm install</code>だった。</p>

<!-- more -->

<h2>説明書</h2>

<ul>
<li><a href="https://docs.npmjs.com/cli/update">npm update</a>

<ul>
<li><code>npm update</code>すると、全パッケージが最新版に更新される(package.jsonで指定されているsemverでの最新版の事)</li>
<li><code>npm update pkg</code>すると、指定したパッケージが最新版に更新される</li>
</ul></li>
</ul>

<h3>固定したバージョンをアップデートする</h3>

<p><code>npm update</code>、<code>npm update pkg</code>で更新するか、<code>npm install pkg@version</code>で更新する。特殊な事情でsemverを変えたくない場合に<code>npm install</code>することになるんだと思う。</p>

<p>npmのバージョン。</p>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>node -v
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>v6.9.1
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm -v
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'>3.10.8</div></div></pre></div></figure>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>cat npm-shrinkwrap.json 
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="o">&#x7b;</span>
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="s2">&quot;name&quot;</span>: <span class="s2">&quot;shrinkwrap-test&quot;</span>,
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="s2">&quot;version&quot;</span>: <span class="s2">&quot;1.0.0&quot;</span>,
</div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="s2">&quot;dependencies&quot;</span>: <span class="o">&#x7b;</span>
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="s2">&quot;jquery&quot;</span>: <span class="o">&#x7b;</span>
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;version&quot;</span>: <span class="s2">&quot;3.0.0&quot;</span>,
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;from&quot;</span>: <span class="s2">&quot;jquery@3.0.0&quot;</span>,
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;resolved&quot;</span>: <span class="s2">&quot;https://registry.npmjs.org/jquery/-/jquery-3.0.0.tgz&quot;</span>
</div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="o">&#x7d;</span>,
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="s2">&quot;jquery-ui&quot;</span>: <span class="o">&#x7b;</span>
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;version&quot;</span>: <span class="s2">&quot;1.12.0&quot;</span>,
</div></div><div data-line='13' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;from&quot;</span>: <span class="s2">&quot;jquery-ui@1.12.0&quot;</span>,
</div></div><div data-line='14' class='code-highlight-row numbered'><div class='code-highlight-line'>      <span class="s2">&quot;resolved&quot;</span>: <span class="s2">&quot;https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.0.tgz&quot;</span>
</div></div><div data-line='15' class='code-highlight-row numbered'><div class='code-highlight-line'>    <span class="o">&#x7d;</span>
</div></div><div data-line='16' class='code-highlight-row numbered'><div class='code-highlight-line'>  <span class="o">&#x7d;</span>
</div></div><div data-line='17' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="o">&#x7d;</span>
</div></div><div data-line='18' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='19' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm update jquery-ui
</div></div><div data-line='20' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test
</div></div><div data-line='21' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery-ui@1.12.1 
</div></div><div data-line='22' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='23' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm ls --depth 0
</div></div><div data-line='24' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test
</div></div><div data-line='25' class='code-highlight-row numbered'><div class='code-highlight-line'>├── jquery@3.0.0
</div></div><div data-line='26' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery-ui@1.12.1</div></div></pre></div></figure>

<h3>配付後に更新する場合は<code>npm install</code></h3>

<p>サーバーにnpm-shrinkwrap.jsonを配付した後に実行するのは、<code>npm install</code>である。<code>npm update</code>すると、npm-shrinkwrap.jsonを無視して全パッケージを更新することになる。ここでは、別ディレクトリにnpm-shrinkwrap.jsonをコピーして試してみる。</p>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm install
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test2
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery-ui@1.12.1 
</div></div><div data-line='4' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='5' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm ls --depth 0
</div></div><div data-line='6' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test2
</div></div><div data-line='7' class='code-highlight-row numbered'><div class='code-highlight-line'>├── jquery@3.0.0
</div></div><div data-line='8' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery-ui@1.12.1
</div></div><div data-line='9' class='code-highlight-row numbered'><div class='code-highlight-line'> </div></div><div data-line='10' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm update
</div></div><div data-line='11' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test2
</div></div><div data-line='12' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery@3.1.1</div></div></pre></div></figure>

<p><code>npm update</code>するとバージョンを上げていないjqueryの最新版3.1.1がインストールされてしまった。元に戻す場合には、もう一度<code>npm install</code>する。</p>

<figure class='code-highlight-figure'><div class='code-highlight'><pre class='code-highlight-pre'><div data-line='1' class='code-highlight-row numbered'><div class='code-highlight-line'><span class="nv">$ </span>npm install
</div></div><div data-line='2' class='code-highlight-row numbered'><div class='code-highlight-line'>shrinkwrap-test@1.0.0 /home/vagrant/work/shrinkwrap-test2
</div></div><div data-line='3' class='code-highlight-row numbered'><div class='code-highlight-line'>└── jquery@3.0.0</div></div></pre></div></figure>
]]>
    </content>
    <author>
      <name>
        <![CDATA[北村聡士]]>
      </name>
    </author>
  </entry>
</feed>