AWS SystemManagerを使って、簡単にサーバー監視やIDS等を導入する

こんにちは kotamat です。 最近は社内セキュリティの向上に取り組んでおり、その一環でAWS System Managerを導入してみたら非常に簡単にいろいろなものがセットアップできたので、そちらの紹介をさせていただきます。

EC2へのソフトウェアインストールの課題感

複数のEC2インスタンスが必要かつ、どのインスタンスにもインストールするソフトウェアがある時、皆さんはどうしているでしょうか? 予めそのサーバーに必要なソフトウェアがわかっている場合はインストールした状態でAMIに固め、それをAutoScalingのAMI設定にしたり、EC2立ち上げ時にそのAMIベースに起動することによってすべてのインスタンスに反映することができるかと思います。

ただ、すでにインスタンスが立ち上がっている場合、それぞれのインスタンスにわざわざsshで入ってインストールしたり、AnsibleやChefを使って一括インストールをしていたかと思いますが、前者はインスタンス数が増えてきたときに対応が難しく、後者に関してはインフラ構成にもよりますが、踏み台の設定が必要だったり、構成管理ツール用に書き換える手間が発生します。

そういった中でAWSのSystemManagerは上記を解決するツールとして有用だったため、今回使用してみることにしました。

SystemManagerって何?

AWS Systems Manager は、Amazon EC2 インスタンス、オンプレミスサーバーと仮想マシンや他の AWS リソースを大規模に設定および管理する機能のコレクションです。Systems Manager には、AWS リソース間で運用データを簡単に一元化し、タスクを自動化できる統一されたインターフェイスが含まれています。Systems Manager はインフラストラクチャで運用上の問題を検出して解決するための時間を短縮します。Systems Manager は、インフラストラクチャのパフォーマンスと設定についての詳細を提供し、リソースとアプリケーションの管理を簡素化することで大規模なインフラストラクチャの運用と管理を簡単にします。

先日の発表で注目されたSessionManagerを始め、たくさんの機能を内包している物となっており、EC2やオンプレサーバーの一括管理に向いている物となっています。

今回はその中でもRun Commandを使ったツールのインストール方法について紹介させてもらいます。

RunCommand

ユーザ任意のターゲットインスタンスに対して、一括でコマンドを実行できるものです。

Dockerのコマンドを一括実行する AWS-RunDockerAction や、AmazonInspectorのエージェントを一括でインストールする AmazonInspector-ManageAWSAgent など便利コマンドももちろんありますが、 AWS-RunShellScript といった、シェルスクリプトを実行してくれるコマンドもあります。 こちらはsudo権限を付与できる任意のコマンドを打つことができるため、今回の背景のような外部ツールの一括インストールには非常に向いています。

導入方法

EC2のロールにIAMポリシーを付与する。

まず、AWS SystemManagerが管理対象としてEC2インスタンスを認識できるようにします。 AmazonLinux系であれば、最初からデーモンプロセスがインストールされている状態で起動しますので、 EC2ロールに対して arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM を付与するだけで大丈夫です。

EC2にタグをつける

SystemManagerのRunCommandでは、インスタンスのタグを指定して一括実行が可能なので、 タグをつけて運用していない場合は予めタグを付けておきましょう。 Env:production などのタグを予め指定しておく形をおすすめします。

RunCommandを設定する。

AWS SystemManager > Run Commandからコマンドの実行を選択します。

f:id:kotamat:20190401075406p:plain

コマンドの中から AWS-RunShellScript を選択します。

f:id:kotamat:20190401075503p:plain

コマンドのパラメータのところでは、任意のシェルスクリプトを記述します。 SaaS型のサーバー監視ツールやIDSでは公式でスクリプトを提供していることが多いと思いますので、そちらを記載します。

f:id:kotamat:20190401075611p:plain

ターゲットは手動での指定かタグでの指定ができます。 手動で指定を行ってもいいのですが、本番環境のみインストールしたいというパターンも多いかと思いますので、 Env:production などのタグを予め指定しておいて、そこにインストールする形をおすすめします。

f:id:kotamat:20190401080150p:plain

出力オプションでは、コマンドの結果の出力先を指定できます。 コマンドの出力を2500文字以上出力したい場合はS3のバケット指定を、CloudWatchLogsで確認できるようにしたい場合は、CloudWatch出力にチェックし、設定を行います。 CloudWatchに関しては、デフォルトで /aws/ssm/AWS-RunShellScript に書き込まれるので、それで問題なければロググループ名を空白にします。

f:id:kotamat:20190401080240p:plain

SNS通知では、コマンド完了等のステータスに関する通知を受け取る設定ができます。

のいずれかのステータスを受信したい場合は設定しましょう。

f:id:kotamat:20190401080635p:plain

Run Commandの実行

あとは実行ボタンを押すだけです。 実行後はコマンド履歴の方に反映されます。

f:id:kotamat:20190401081136p:plain

コマンドの詳細では、実行したインスタンスの一覧が表示されます。

f:id:kotamat:20190401081301p:plain

そして、インスタンスを選択し 出力の表示 を押すと、その実行されたコマンドの標準出力を確認することができます。

f:id:kotamat:20190401081500p:plain

これでコマンドの実行は完了です。

まとめ

今回はSystemManagerの中でもRunCommandに焦点をあてて紹介させてもらいました。 RunCommandを用いることで、単発コマンドを複数のインスタンスに一括で実行することが簡単になるため、 すでに立ち上がっているインスタンスへ監視ツールを導入したいときや、IDSなどのセキュリティツールを導入したいときなどに活用することができるかと思います。

最後に

SCOUTERではエンジニア、デザイナーともに募集しております! 新規事業、絶賛グロース中の事業ともにLaravel, Vue.jsで開発しておりますので、 興味のある方はお声がけください!

体験副業もはじめました!

www.wantedly.com

www.wantedly.com

www.wantedly.com

PHPerKaigi 2019 に参加・登壇してきました。

こんにちはみなさん ゴツメ装備エンジニアこと @niisan-tokyo です。
3/30, 31 でPHPerKaigiに参加・登壇してきましたので、その報告となります。
(3/29の前夜祭は会社の締め会で出れなかったのです。)

PHPerKaigi 2019

PHPerKaigiはPHPer同士の相互交流を主なテーマとし、去年から始まりました。

phperkaigi.jp

このイベントは相互交流に重きをおいているだけあって、トークにおいては必ず質疑の時間がタイムテーブルに盛り込まれていたり、
気軽に聞けるCIやフレームワークの相談会があったり、突発的に喋りたくなった人のためのアンカンファレンススペースがあったりしまして、
様々な楽しみ方ができるようになっています。

また、このイベントの大きな特徴としては運営が非常に親切かつ丁寧というところにあります。
去年、私が「ビールしかないんかぁ」(お酒飲めない人) とつぶやいた直後に烏龍茶がデプロイされたりして、少しの不満も迅速に解消しようという不断の努力を感じます。

なお、LTの時間にビールがデプロイされる予定だったらしいですが、手違いで届いていなかったようです。 これに一番ショックを受けていたのが、当の実行委員長だったというね。

FOOD

私のいつものスタイルとして、カンファレンスで出てきた食事を紹介しています。
今回は朝昼晩と全部あったので、それぞれ載せてみました。

f:id:niikura23:20190401082405j:plain
朝ごはん

朝ごはんはドーナッツですね。
朝から糖分を補給し、頭の回転を良くしようという考えではないだろうかと推測したりしなかったり。

f:id:niikura23:20190401083100j:plain
ランチ

ランチにデプロイされたお弁当ですね。
メルカリさんのランチセッションを聞く前に食べ尽くしてしまいました。

f:id:niikura23:20190401083406j:plain
懇親会ディナー

懇親会で出てきたディナーです。
ちゃんと麦茶もあったりしたので、満足できました。

トーク

たくさんのトークがあったのですが、私が登壇で頭が一杯になってたりするので、印象に残っているのだけ紹介します。

speakerdeck.com

以前から講演をしてもらったり、講演を聞いたりしている郡山先生ですが、とにかく見ている世界が違うのかと思うほどの内容で、これを聞けただけでも参加した意味があったなって思ったほどです。
とりあえず、無心になって資料を見るなり公演を聴くなりして、「REST」ってなんなのかって言うことを、見つめ直すべきだなって思います。

speakerdeck.com

LTのネタで川島さんが話した内容ですが、これ、レギュラートークで聞きたかったなぁって思います。 クラスの依存関係を可視化できる、できたてのツールでして、私も後で使ってみようかなって思います。

登壇

今回は幸運にもCFP通ったので、私も登壇してきました。

f:id:niikura23:20190401085442p:plain
登壇時のワタシ

緊張しいたわけではないですが、下むいちゃってますね。 これは反省点ですな。。。

発表資料はこちらです。

speakerdeck.com

内容は見てもらえばわかると思いますが、言及されていない内容に非同期のときのAuthの挙動の説明がないので、補足しておきます。

  1. 一郎くんがログイン => Auth::user() == 一郎くんになるがクリーナーによってリセット
  2. 次郎くんがログイン => Auth::user() == 次郎くんになるがクリーナーによってリセット
  3. 一郎くんが自身の名前を参照 => Auth::user() == 一郎くんになり、viewの描画が始まる前に5秒待つ
  4. 次郎くんが自身の名前を参照 => Auth::user() == 次郎くんになり、viewの描画が始まる前に5秒待つ
  5. 一郎くんが待ち時間後に自身の名前を参照 => Auth::user() == 次郎くんの状態でviewが描画され、クリーナーによってリセット
  6. 次郎くんが待ち時間後に自身の名前を参照 => Auth::user()はクリーナーによりリセットされており、ログアウト状態になった

という、面倒な経緯でした。

まとめ

というわけで、PHPerKaigi 2019 に参加してきたレポートでした。
来年は弊社のメンバーがもっと参加するといいな!

さいごに

現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。

興味のある方は、是非下記からご応募お願い致します!

www.wantedly.com

www.wantedly.com

www.wantedly.com

Vueのコンポーネント単体テストを始めてみよう

こんにちは!
株式会社SCOUTER開発部フロントエンドエンジニアの佐藤(@r_sato1201)です

最近、社内でLaravelのテストについての会話が活発に交わされるようになりました。 その会話を聞いていて、Vueのテストはないのだろうか?と興味を持ったのでテストの導入方法と、簡単なテストを動かしてみたことについて書いてみました。

なぜテストをするのか?

Vueの公式ドキュメントにはテストの利点についてこう記述してあります。

コンポーネント単体テストにはたくさんの利点があります:

コンポーネントがどう動作すべきかのドキュメントを提供します
・過度な手動テストの時間を節約します
・新しい機能におけるバグを減らします
・設計を改良します
リファクタリングを容易にします

自動テストは大規模な開発チームが複雑なコードベースを保つことを可能にします。

テストを書くことで、コンポーネントがどういう振る舞いをするべきかや、 コンポーネントの設計に問題があることに気づけるメリットがあるようです。

テストの導入方法

Vueにはvue-test-utilsというVueコンポーネント単体テストのための公式ライブラリが用意されています。上記に加え、テストフレームワークJestを使うことで簡単にテストを導入することが出来ます。

新しくプロジェクトを作成する際は vue-clivue createコマンドを用いればvue-test-utilsJestを簡単にインストールすることができます。

f:id:ryonnsui1201:20190327034808p:plain

Unit Testingを選択

f:id:ryonnsui1201:20190327034823p:plain

Jestを選択

既存のプロジェクトに導入する際は、devDependencies にvue-test-utils、Jestをインストールしましょう。

yarn add -D @vue/test-utils babel-jest jest vue-jest

※babelを使っていない場合、babel-jestは不要です。

Jestカバレッジも簡単に取ることが出来ます。
package.jsoncollectCoverageオプションを加えることでカバレッジを取ることができるようになり、collectCoverageFromオプションにカバレッジ収集対象のファイルを配列で定義することができます。

"collectCoverage": true,
"collectCoverageFrom": ["**/*.{js,vue}", "!**/node_modules/**"],

f:id:ryonnsui1201:20190329102122p:plain

更に詳しいオプションの詳細については、 Jest configuration documentationも参考にしてみてください。

テストを実践してみよう

テストの書き方を掴むために、propsによる描画のテストを行ってみます。

以下のようなpropsを持つ簡単なコンポーネントを作成します。

RemoveUser.vue

<template>
  <div class="User">
    <span>{{name}}</span>
    <template v-if="isAdmin">
      <button @click="removeUser()">削除</button>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      id: Number,
      name: String,
      isAdmin: Boolean
    },
    methods: {
      removeUser() {
        this.$emit('removeUser', {id: this.id})
      }
    }
  }
</script>

それでは、実際にテストを行ってみましょう。
プロジェクトのtests/unit内にテストファイルを作成します。
テストは.spec.js.test.jsというファイルを作成すれば自動で検知してくれます。

yarn test:unitでテストを実行します。

また、--watchを指定することで、テストコードに変更を検知して、変更があるたびにテスト実行することができます。

RemoveUser.spec.js

import {mount} from '@vue/test-utils'
import RemoveUser from '@/components/RemoveUser.vue'

describe("user", () => {
  const adminPropsData = {
    id: 1,
    name: 'ユーザー1',
    isAdmin: true,
  }
  const userPropsData = {
    id: 1,
    name: 'ユーザー1',
    isAdmin: false,
  }
  test('emitされるか', () => {
    const wrapper = mount(RemoveUser, {
      propsData: adminPropsData
    })
    wrapper.find('button').trigger('click')
    // イベント発火してるかどうか
    expect(wrapper.emitted('removeUser')).toBeTruthy()
    // emit時にidが渡されてくるかどうか
    expect(wrapper.emitted('removeUser')[0]).toEqual([{id: 1}])
  })
  test('nameが正しく表示されているか', () => {
    const wrapper = mount(RemoveUser, {
      propsData: adminPropsData
    })
    expect(wrapper.find('span').text()).toBe(adminPropsData.name)
  })
  test('isAdminの値によって削除ボタンが表示されてるか', () => {
    const adminWrapper = mount(RemoveUser, {
      propsData: adminPropsData
    })
    const userWrapper = mount(RemoveUser, {
      propsData: userPropsData
    })
    expect(adminWrapper.find('button').exists()).toBeTruthy()
    expect(userWrapper.find('button').exists()).toBeFalsy()
  })
})

テストコードを箇所に分けて、説明していきます。

test('emitされるか', () => {
    const wrapper = mount(RemoveUser, {
      propsData: adminPropsData
    })
    wrapper.find('button').trigger('click')
    // イベント発火してるかどうか
    expect(wrapper.emitted('removeUser')).toBeTruthy()
    // emit時にidが渡されてくるかどうか
    expect(wrapper.emitted('removeUser')[0]).toEqual([{id: 1}])
  })

ここでは、コンポーネント内でクリックイベントが発火したときに 正しくemitされているかを確認しています。

ここで

・ボタンをクリックしたときにemitが動いているか
・emit時に、propsで渡したidが返ってくるか
が分かります。

f:id:ryonnsui1201:20190328210955p:plain

test('nameが正しく表示されているか', () => {
        const wrapper = mount(RemoveUser, {
            propsData: adminPropsData
        })
        expect(wrapper.find('span').text()).toBe(adminPropsData.name)
    })

ここでは、propsで渡したnameが正しく描画されているかを確認しています。

f:id:ryonnsui1201:20190328211618p:plain

test('isAdminの値によって削除ボタンが表示されてるか', () => {
  const adminWrapper = mount(RemoveUser, {
    propsData: adminPropsData
  })
  const userWrapper = mount(RemoveUser, {
    propsData: userPropsData
  })
  expect(adminWrapper.find('button').exists()).toBeTruthy()
  expect(userWrapper.find('button').exists()).toBeFalsy()
})

ここでは、権限によって削除ボタンが表示の出し分けをしているかを確認しています。

ここで

・isAdmin = true(管理者) の場合、削除ボタンが表示されている
・isAdmin = false(一般) の場合、削除ボタンが表示されていない

ということが分かります。

f:id:ryonnsui1201:20190328212226p:plain

ちなみに、開発をする上では
① 実装する機能の要件を元にテストコードを書く
② テストコードのに表現されている要件を満たすコードを書く
③ テストが成功する状態を維持しつつリファクタリングしていく

という順番で行うと良いと思います。

さいごに

フロントのテストはどんなものなんだろうと、軽い気持ちでテストについて調べてみました。 導入自体は簡単で手軽に始められますが、何をテストするべきか、しないべきかの切り分けが非常に難しく重要であると感じました。 今回は、Vueコンポーネント単体テストの導入方法、シンプルなテストに留めましたが、 今後、Vuex周りのテストやE2Eテストについても調べ学習していきたいと思います。

現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。

興味のある方は、是非下記からご応募お願い致します!

www.wantedly.com

www.wantedly.com

www.wantedly.com

参考資料

1年間のプログラミングを通して得た3つの教訓

はじめに

こんにちは株式会社SCOUTERでエンジニアをしているhirokinishizawaです。 業務では、SARDINEという人材紹介会社向けの業務管理システムを開発しています。

2019年2月1日でプログラミングというものに出会ってから1年が経ち楽しい時期やつらい時期もありましたが、1年間実務だけやってきた自分が得た教訓をプログラミングを始めたばかりの方やこれから始めてみたいと思っている方に共有をし、少しでもお役に立てればいいなぁと思います。

自分の経歴

入社する前

自分は日大付属の高校に通っていて特にやりたいこともなく大学受験をせずに卒業しました。(決して、決して行けなかったわけではないです!!多分。。。)

卒業をした後も特にやりたいことはなく主に軌道工事、塗装工事、屋上防水工事などいわゆる建築現場職人の仕事をしたり、土日などは父親の仕事の手伝いで3D図面を書いていたりしました。

そんな何の目標もないまま月日が流れ2018年1月に兄の繋がりで弊社CEO中嶋に出会いエンジニアという職業を知りその場で2月から入社をさせていただくことになりました。

入社してから

入社してからの流れは下記のようになります

ProgateでHTML&CSS、JavaScript、PHPを勉強
↓
オウンドメディア作成(jsはほぼやってもらった)
↓
サービスLP作成
↓
NuxtMeetUpのLT登壇
↓
サービス開発

このような流れでサービス開発に合流しました。

ありきたりかも知れませんが自分の得た教訓をこれから話していこうかと思います。

1.遠慮するのは時間の無駄

これはエンジニアに限った話ではないですが経験者、未経験者問わず入社してからわからないことは多々あるかと思います。

  • みんな他の仕事があるし質問するのは悪いのではないか。
  • 質問の回答が自分の求めていた回答ではなく、その時に別の聞き方ができずもう一度同じ質問するのが気まずい。
  • そもそも何で詰まってるのかがわからないから質問が出来ない。

質問したけど質問した内容の意味が分からない時に苦い顔するので再び質問しに行きにくいだったり、皆忙しいから質問しずらいだったり。いろいろな思いがあり質問しに行きずらいことがあるかと思いますが全て時間の無駄使いです、気にせず質問しましょう。

もちろん時間を割いて教えてくれるのですから最低限考えて質問しなければいけないとは思いますが、わからないものは一人で考えても分からないので、とにかく一つ一つ確認しましょう。

実際に自分は結構周りの目を気にしてしまうタイプで半年近くもの期間を無駄にしたなぁと今でも後悔しています。ですが困ったことがあったら質問する。再び分からなくなったら質問するを繰り返した結果自分の成長を実感できたのも事実です。

  • 自分が質問する時に気をつけていたこと
    • コードベースで話が出来ないぐらいわからない時はタスクベースでなにをしたいのかを伝えてまずは調べ方を教えてもらう
    • 調べてもわからない時はどのように検索したのかを先に伝えてその上で相手だったらどういうような対応をするのかを聞く
    • 言っている(回答の)意味が分からない時はちょっと止めてもらい出てきた単語だったりのメモを取り後ほど検索する

など意識していました。ただ自分は開発の質問をテキストでするのが苦手で口頭で聞きたいタイプなのですが、そうではない方もいるのでそこは臨機応変な対応ができる人になりましょう。

2.アサインされたら見積もりや設計を先にしよう

アサインされたのですぐにコードを書き始めるのは一見早いように思えますが、レビューしてもらう人に自分の設計の意図が伝わらず(そもそも設計が出来てないなど)手戻りが発生し結果遅くなることがあります。

現在弊社ではスクラムを導入しておりプランニングの時間をとってチームで見積もりや設計を行っております。フロントエンドが得意な人やサーバーサイドが得意な人、どちらも卒なくこなせる人などいろいろな人がいる中で見積もりを行うわけですから、導入してすぐの頃は見積もりがずれ当初決めていたリリース予定には間に合わなかったり、アサインされた人が設計をやったりしていたので分からない時もありコミュニケーションコストだったり手戻りが起きてしまったりした時にすごく時間がかかってしまうことがありました。

最近では認識のズレは改善されてきて見積もりも大幅にずれることはなくなり、プランニングで時間をかけて見積もりや設計を行うことによってコミュニケーションコストや手戻りが起こることがほぼ無くなってきました。

仮に個人で開発をするときでも自分だけが分かればいいのではありません。もし設計が苦手だとしても癖を付けるために他の人も触るという前提でコンポーネント設計など心がけるのがいいと思います。

3.一つ一つ順番に終わらせていく

タスクAのレビューをお願いしてその間にタスクBに着手しました。タスクBをやっている最中にタスクAのレビューが終わり修正が必要。そんな時にあなたはどちらを先にやりますか?「タスクAのレビュー対応がそこまで大変ではないので後回し」、「タスクBはまだまだ掛かりそうだから先にタスクAのレビュー対応しておこう」2つだけだったらなんとかなるかと思います。

ですがレビューをお願いしている人にも他の仕事がありレビューが遅れることもあります。タスクA、タスクBまで終わりレビューのお願いをしていてレビューが遅れてしまいタスクCを着手している時にレビューが返ってきてタスクA、タスクBともに膨大な手戻りが必要になった時。そこからさらに緊急度の高いバグ報告が来たら。他にも緊急度高い修正依頼が入ってきたら。焦ってしまいがキャパシティが小さい自分にとってはパンク寸前です。

エンジニアだけの話ではないと思いますがそれぞれタスク毎に何をやるべきなのか、その中で優先度が高いのはどれか。パンク寸前でも時間は待ってくれませんし、その時間に追われてどんどん焦ってくることがあります。ですが一度立ち止まって整理し一つ一つ終わらせていくしかありません。

実際に自分は一度にタスクが増えて焦ってしまい全部に手を出そうとして結果何も進まなかったということを何度かやってしまっています。今でもマルチタスクは苦手ですがメモを使い、やることを全て書き出してから優先度をつけてやっています。

まとめ

  • 成長をするためなら自分より出来る人に質問するしかない(ある程度限度はあります)
  • 見積もりや設計に時間を取られたとしてもしっかり行えばリターンはある
  • 焦らずにやるべきことリストを作って優先度をつけてパンクしないようにする

もちろん自分の性格など関係するとは思いますが、この3つのことで悩んでいる方も少なくはないのではと思います。そんな方に少しでもお役に立ててたら幸いです!

最後に

弊社では事業・サービスが成長していくにあたってメンバーを増やしていきたいと思っています。

興味のある方は下記からご応募いただくか、@hirokiにご連絡ください!!

www.wantedly.com

www.wantedly.com

www.wantedly.com

僕はとりあえず dayjs !

こんにちは、自意識過剰な正義のヒーローでお馴染みの株式会社SCOUTERの石岡 将明( @masaakikunsan )です。

皆さんは、 JavaScript の日付時刻操作をどうやっていますか?

僕は、 JavaScript の Date は罠が多くそのまま使うことをあまり好まず、今までは日付時刻の操作を行うとなれば黙って moment.js をぶっこんでいました。

フロント界隈でも少し前までは、男は黙って moment.js !って流れがありましたが、最近だと dayjs が主流になりつつあります。 今回はその dayjs について書いていきます。

そもそも

JavaScript の Date はいろいろしんどいんですが、個人的にサービス開発においてブラウザの対応をいちいちするのがだるいなと思っています。 そこで前述の通り、これまでは moment.js をぶっこんでいたのですが、 moment.js はファイルサイズが大きく、バンドルサイズが肥大化するというデメリットがありました。

ですがある日、Twitter を見ていたら dayjs と出会い心を奪われてしまい今後は黙って dayjs やなとなりました。

dayjs について

github.com

Day.js は日付と時刻をパース・検証・操作・表示する最小のモダンブラウザ向け JavaScript ライブラリであり、 Moment.js の API との広い互換性を持ちます。 Moment.js を使ったことがあればすぐにでも Day.js を使い始めることができます。

上記はドキュメントの引用なのですが、この通り、dayjs は moment.js を使えれば直ぐ使えるという魅了があります。 そして、 moment.js でのデメリットであったファイルサイズが大きいという問題を day.js では解決してくれています。

つまり、moment.js のような使用感でファイルサイズがめちゃくちゃ小さくなった最強ライブラリといった感じです。 (これまで moment.js を使って人にとっての話)

使い方

ここでは、みなさんの大好きな Nuxt に day.js をぶっこんで sampleを書いていきます

最初に dayjs をいれていきましょう。

$ yarn add dayjs

次にpluginsを定義していきます。

plugins/dayjs.js

import 'dayjs/locale/ja'
import dayjs from 'dayjs'
import Vue from 'vue'

dayjs.locale('ja')

Vue.prototype.$dayjs = dayjs

あとは、nuxt.config.js に下記を追記でglobalでdayjsが使えるようになります。

plugins: ['@/plugins/dayjs']

それでは、さっそくdayjsで今日の日付が正しく表示されるかみてましょう。 index.vue を書き換えて日付を表示してみます。

<template>
  <section class="container">
    <div>
      <logo />
      <h1 class="title">
        nuxt-dayjs-sample
      </h1>
      <p>現在の時刻: {{ now }}</p>
    </div>
  </section>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  data: () => ({
    now: null
  }),
  mounted() {
    this.now = this.$dayjs().format('YYYY年MM月DD日 HH:mm:ss')
  }
}
</script>

f:id:masaakikunsan:20190320142048p:plain

今日の日付の表示ができました。 あとは、やりたいことをドキュメントを見ながら実装していくだけです。

ファイルサイズ

f:id:masaakikunsan:20190320143203p:plain

※ moment との比較はちょっと用意できなかったので使ってる人は自分で確認してみてください。

さいごに

dayjs は、moment.js をこれまで使っていた人にとっては最高のライブラリです。 moment と書き方が基本的に変わらず、ファイルサイズがめちゃくちゃ小さいので使わない理由がほぼないです。

これまで moment を使ってみた人は移行コストも学習コストもほぼないので乗り換えてみてはいかがでしょうか?

現在、back check チームでは、エンジニアの募集をしております。 僕と一緒にフロントエンドを朝まで語り尽くしたいフロントエンドエンジニアやレベルの高いフロントエンドチームと最高のプロダクトを作って行きたいサーバーサイドエンジニアは是非ご応募お願いいたいします!

www.wantedly.com

www.wantedly.com

Laravel/Vue.js勉強会#8 オールスターズを開催しました

こんにちは、自意識過剰な正義のヒーローでお馴染みの株式会社SCOUTERの石岡 将明( @masaakikunsan )です。

皆様のおかげで、Laravueも第8回目を迎えました。 そこで今回は、今までのLaravue勉強会で協賛頂いた企業様をあつめ、各社からLT登壇していただくという形を試みました。

これまでの協賛頂いた企業様によるLTということもあり、今まで以上に濃い回となりました。

発表内容

グローバルstoreを利用する際はMixinではなくPlugin使った方がいいんじゃないか?説 (田原一樹さん)

f:id:masaakikunsan:20190319162257j:plain

slides.com

レアジョブさんからは、田原さんがMixinの辛さと代替案について話してくれました。 この辺の話をちゃんとしてくれてる資料・スライドはあまりないので是非一度見てみてください。

Laravelを本番環境にデプロイするまで (@yukure3)

f:id:masaakikunsan:20190319162402j:plain

speakerdeck.com

うるるさんからは、@yukure3 さんがLaravelを本番環境にデプロイするまでの話をしてくれました。 @yukure3 さんは新卒でかつ今回初LTだったらしいのですが、初とは思えないぐらいしっかりとLTをしていて良かったなと思いました。 内容もデプロイまでを細かくしっかりと解説していて良いLTでした。

SPAリリース後の問題とその対策 (@frostndays)

f:id:masaakikunsan:20190319162429j:plain

ITプロパートナーズさんからは、@frostndays さんがリリース後に発覚したSPAの問題とその対策でなにをしたかを話してくれました。 SSRをやめVueのライフサイクルに乗っ取りAPIを叩くようにした等色々話してくれました。

アイスタイル特設サイトにおけるVue.jsの導入事例 (@kubotak_public)

f:id:masaakikunsan:20190319162427j:plain

www.slideshare.net

アイスタイルさんからは @kubotak_public さんがVue.jsの導入事例の話をしてくれました。 Vue.js 関連の話はあまりなかったですが、全体的に面白かったので是非スライドを見てみてください。

Laravel Queueの運用管理 (@migrs)

f:id:masaakikunsan:20190319162428j:plain

オープンロジさんからは @migrs さんがCQRSについてどうやっているかの話をメインでしてくれました。 Laravel Telescope は初めて知ったので今度調べて見ようと思いました。

Monolith→MultiRepo→MonoRepoでのリポジトリ戦略 @kotamat

f:id:masaakikunsan:20190319162648j:plain

slides.com

弊社発表枠では CTO の松本がリポジトリ戦略について発表をしました。 弊社では、Monolith→MultiRepo→MonoRepoといった感じにリポジトリ戦略が変わってきており、各々の話やMonoRepoについて話してくれました。

懇親会

f:id:masaakikunsan:20190319162120j:plain

f:id:masaakikunsan:20190319162135j:plain

発表後は、株式会社うるるさんが提供してくれた飲食を囲み懇親会をしました! 株式会社うるるさんありがとうございます。

まとめ

過去協賛企業様はどこも Laravel + Vue をがっつり使用しており非常に内容の濃い回でした。

次回は、株式会社カオナビさんに会場をお借りし 5/22 に開催します。

最後に

SCOUTER社では一緒に頑張ってくれる方を募集しております。 デザイン、エンジニアの皆さん興味のある方はご応募お願いします!

www.wantedly.com

www.wantedly.com

Web猫ブログを TypeScript化しました

先月よりジョインさせていただいている Web屋さんで猫好きな @jiyuujin 今回は度々登場となって申し訳ないですが、自身のWeb猫ブログを TypeScript化した話をさせていただきます。

webneko.info

nuxt-tsを採用します

結論を先に申し上げると nuxt-ts を採用した件で、その導入周りに留まります。導入にあたってかれこれ1年以上、メンテストップ中の公式テンプレート。。 一切頼りにはできません。今年のどこかで必ず更新してほしさあり、新たに出していただけると大変嬉しいですね😊

github.com

Web猫ブログでは個人的なアナウンスこそしていませんでしたが、今回この場を借りて TypeScript化しましたという経緯です。つい最近、 nuxt-ts 不要になるかもという Issue (下記を参照)を見たのですが、とりあえず nuxt-ts をインストールするしかありません。ビルドコマンドも nuxt から nuxt-ts を使うよう変更してあげる必要があります。

yarn add nuxt-ts
yarn add typescript @types/node ts-loader -D

nuxt-ts 不要になるの?

上記でも触れた nuxt-ts 不要になるかも、というのが以下 Issueを見たことでした。 tslint から @typescript-eslint に移行する一環と思いますが、気になる話でした。

github.com

Nuxt.configを TypeScriptで書く

Web猫ブログでは Headless CMSに Contentfulを採用。 Sitemapの生成処理や Makdownのパース処理など単純な設定に縛られず比較的コードを書く箇所が多く存在すると思いますが、これらの実装箇所が全て型安全に書けるようになったことは今までと大きく違う点だと思います。

APIを使うために型定義を設定する

asyncDatafetch などのAPIをを型安全に利用するために自分自身でVueのInterfaceを拡張してあげる必要があります (/types/nuxt.d.tsを作成すると良いでしょう) この辺りはさすがVue界隈と思う部分ですが、丁寧に書いてくださっていることに対しては感謝しかありません。Nuxt公式ページに Context一覧が存在します。そのページと照らし合わせながらぐりぐり型定義を設定します。

ja.nuxtjs.org

declare module 'nuxt' {
  import { Store } from 'vuex';
  import { Route } from 'vue-router';

  export class Builder {
    constructor(nuxt: Nuxt);
  }

  export class Nuxt {
    constructor(config?: NuxtConfig);
  }

  export interface NuxtConfig {
    dev: boolean;
    [key: string]: any;
  }

  export interface NuxtContext<S = any> {
    app: NuxtApp;
    isClient: boolean;
    isServer: boolean;
    isStatic: boolean;
    isDev: boolean;
    isHMR: boolean;
    route: Route;
    req: any;
    res: any;
    store: Store<S>;
    env: any;
    params: any;
    query: any;
    redirect(path: string): void;
    error(params: { statusCode: number; message: string }): void;
    nuxtState: any;
    beforeNuxtRender(fn: Function): any;
  }
}

上記はあくまでミニマムな構成になっています。当ブログではこの構成に加えて、 contentful 用のModelも定義しています。このように必要に応じて随時追加してあげなければならず少々面倒ではありますが、後々を考えると良い「投資」になってくれるかもしれません。

今回はミニマムな構成の下で動作確認をとることができたのでこの辺で。

リポジトリ公開中

ブログでは随時お問い合わせコメント受付中、PRも絶賛受付中です。

Web猫ブログ 本番運用中

今までの TypeScriptを採用していない版です。

github.com

Web猫ブログ β版 (いずれ本番運用予定)

既に切りました、本番運用開始されたら再度アナウンスしたいと思います。

github.com

最後に、

SCOUTERではエンジニア、デザイナーともに募集しております! 新規事業、絶賛グロース中の事業ともにLaravel, Vue.jsで開発しておりますので、 興味のある方はお声がけください!

www.wantedly.com

www.wantedly.com

www.wantedly.com