Nuxt + Contentful + NetlifyでJAM Stackなブログを作ってみよう

ITプロパートナーズでエンジニアをしているもりと申します。

少し今更感がありますが、ContentfulとNuxtでJAM Stackなブログを作ってみました!

 

まずJAM Stackという聞き慣れない言葉がでてきましたが、JAM Stackとは

Javascript + Api + Markup のことで、HTMLをサーバーサイドで生成してレンダリングするのではなく、javaScriptapiから取得したデータをもとにデプロイ時にHTMLを生成する最新のweb開発アーキテクチャのことです。

詳しくはこちら

 

今回はContentfulをAPIとして、Nuxtを静的サイトジェネレーターとして使用することで

JAM Stackとして実装していきます。

 

Contentful

  1. Contentfulアカウントの作成
  2. スペースの作成
  3. モデルの作成
  4. 記事の作成

Nuxt

  1. Nuxtアプリケーション作成
  2. Contentfulの設定
  3. Contentfulのコンテンツデータ取得
  4. ビルド時のhookと動的ルーティングの生成
  5. ブログページ
Netlify
  1. 事前準備
  2. アカウント作成

 

Contentful

ContentfulとはヘッドレスCMSと呼ばれるコンテンツ管理サービスで、WordPressのように記事の作成や管理ができます。

WordPressと違うのは、Contentfull側でViewのレンダリングは行わず、完全にAPIベースである点です。

記事のデータはAPIを介して取得するため、フロントエンドは自分の好きな技術で好きなように作ることができます。

 

1. Contentfulアカウントの作成

まずはContentfulのアカウントを作成していきましょう。

https://www.contentful.com/

 

Try for free  とあるのでこちらからアカウントを作成します 。

f:id:frostnday:20190515112519p:plain

 

今回はGithubと連携を行います。

f:id:frostnday:20190515112906p:plain

 

名前やメールアドレスなどの必要事項を入力し signUp してアカウントの作成完了です。

2. スペースの作成

次に スペース という大枠になるものを作成します。

スペースとはContentfulの一番大きな領域で、1プロジェクト = 1スペースになります。

公式によると開発用とProduction用といった単位でスペースを作成することもありだそうです。

今回はブログを1つ作成するだけなので、スペースは1つでOKです。

 

早速スペースを作成していきましょう。

まずは左側にあるメニューからCreate spaceをクリックします。

f:id:frostnday:20190515124817p:plain

 

space作成用のモーダルが表示されるので、最初にspaceのタイプを選択します。

今回はFreeプランで作成します。

f:id:frostnday:20190515125413p:plain

 

次にスペース名を決めます。

f:id:frostnday:20190515125837p:plain

今回はシンプルにblogとしておきました。

 あとはConfirm & CreateSpaceをクリックしてスペースの作成完了です!

3. モデルの作成

次にモデルを作成していきましょう。

モデルとはContentfulで作成する記事などのコンテンツのことです。

例えば、 title top_image create_atのように、一つのコンテンツに持っておきたい情報を名前と型を決めて登録します。

今回はブログ記事なので、タイトルやTOP画像、作成日、本文などの情報を持つ記事モデルを作成してみたいと思います。

 

先程スペースを作成したので、TOPページに戻るとCreate spaceが Completedになっていると思います。

そのすぐ下にあるDefine the structure の Create a content type をクリックします。

f:id:frostnday:20190515144917p:plain

モデルの名前と説明を入力しCreateをクリックしましょう。

f:id:frostnday:20190515145206p:plain

 

今回はブログの記事なのでシンプルにarticleとしました。

 

次に、このモデルにフィールドを設定していきます。

f:id:frostnday:20190515155447p:plain

作成後に右側にあるAdd Fieldをクリックします。

 

f:id:frostnday:20190515155735p:plain

クリックすると追加するフィールドの型を決めるモーダルが表示されるので、Textを選択します。

f:id:frostnday:20190515155957p:plain

フィールドの名前を入力してCreateします。

これでText型のブログのタイトルを表すフィールドの作成が完了です。

 

今回は合計5つのフィールドを作成しました。

f:id:frostnday:20190515160333p:plain

これで、1つのコンテンツ(記事)はここで設定した5つのフィールドを持つことができるようになりました!

 

4. 記事の作成

 スペース、モデルの作成が終わったので、実際にコンテンツ(記事)を作成してみましょう。

TOPページには、先程Modelも作成が終わったので、 Define the structureもCompletedになっているかと思います。

 

f:id:frostnday:20190515162113p:plain

  Create your contnet の Add an entry からコンテンツを作成していきます。

 

このように先程設定したフィールドの中身を入力していきましょう。

f:id:frostnday:20190515162526p:plain

 

実際の本文はフィールドタイプをrichTextにしたので、このように文章の途中に自由に画像を差し込んだり、太字にしたり といったことが可能です。

f:id:frostnday:20190515162940p:plain

記事の作成が終わったら、右上のpublishをクリックして作成完了です。


Nuxt

Contentfulでブログ記事の作成が完了したので、次はそのブログを表示するフロントエンドの部分の作成を行います。

 

今回はNuxtを使用してそのフロントエンド部分を作成していこうと思います。

NuxtとContentfulの連携については公式に手順が載っているのでこちらに沿って説明して行きたいと思います。

1. Nuxtアプリケーション作成

では早速Nuxtのアプリケーションを作成していきましょう。

まずはvue-cliを使ってNuxtの新規アプリケーションを作成します。

 

vue-cliのinstall

$ yarn global add @vue/cli-init

 

nuxtアプリケーションの作成

$ vue init nuxt/starter アプリケーション名 

これでnuxtのアプリケーションが作成できたので早速Nuxtを起動してみましょう。

作成したNuxtアプリケーション配下に移動して必要なmoduleをinstallします。

$ yarn install 

installが完了したら実際に起動してみます。

$ yarn dev 

上記コマンドでbuildが開始され、URLが表示されるのでクリックしてみましょう。

 

成功していれば、このような画面が表示されます。

f:id:frostnday:20190515170732p:plain

2. Contentfulの設定

Nuxtのアプリケーションの作成が完了したので、次はContentfulと連携するのに必要なModuleをinstallします。

 

$ yarn add contentful 

 

contentfulと連携するにはapiのキーが必要になるのでそちらを作成しましょう。

作成が必要なのは

・space id

access token

の2つです

 

contentfulのページのヘッダーにあるsettingsからAPIkeysページに移動します。 

f:id:frostnday:20190605133401p:plain

ページに移動すると、SpaceIDとAccessTokenなどが自動で生成されているのでこちらのキーを使用してcontentfulと連携をしていきます。

 

f:id:frostnday:20190605134328p:plain

f:id:frostnday:20190605134607p:plain


contentfulのキーの作成が終わったらそのキーを保存しておく場所をNuxt側に作ります。

プロジェクト直下にenv.jsを作成して以下のようにします。

// ./env.js
{ "CTF_SPACE_ID": "先程作成した Space ID", "CTF_CDA_ACCESS_TOKEN": "先程作成したContent Delivery API - access token" }

 ※こちらgitignoreに指定するのをお忘れなく

 

 

先程installしたcontentful用のmoduleを使うためにpluginを作成します

// ./plugins/contentful.js
const contentful = require('contentful')
const env = require('../env.js');

const config = {
space: process.env.CTF_SPACE_ID,
accessToken:process.env.CTF_CDA_ACCESS_TOKEN
}

// export `createClient` to use it in pagecomponents
module.exports = {
createClient () {
return contentful.createClient(config)
}
}

これでNuxtとcontentfulの連携の設定は完了です。

3. Contentfulのコンテンツデータ取得

連携の設定が完了したので、次はContentfulから先程書いた記事を取得します。

今回はJAM Stackにするので、buid時に全ての記事データを取得してjsonに固めます。

 

ではまずデータを取得するmoduleを作成しましょう。

 

modulesディレクトリ配下に、先程作成したcontentful連携用のpluginを使用して

データ取得する処理を書きます。

 

その後、取得したデータをjsonファイルとして指定ディレクトリに出力します。

// ./modules/createStaticJson.js

import { createClient } from '../plugins/contentful.js';
import env from '../env.js';
import fs from 'fs';

const outputPath = 'static/json/article.json';

/**
* Contentfulから取得したデータをjsonファイルとして出力します。
*/
export default async function outputStaticData() {
const client = createClient();

// contentfulからデータを取得
const articles = await client.getEntries({
'content_type': env.CTF_BLOG_POST_TYPE_ID,
order: '-sys.createdAt'
});

// jsonとして出力する
fs.writeFile(
outputPath,
JSON.stringify(articles),
err => {
if (err) {
throw err;
}
},
);
};

 

取得したjsonはstatic/json/article.jsonに配置するので、指定ディレクトリにはあらかじめ空のjsonファイルを作成しておきましょう。

// ./static/json/article.json
{}

 

これでデータの取得、jsonファイル出力処理は完了です!

 

4. ビルド時のhookと動的ルーティングの生成

データを取得する処理ができたので、その処理の呼び出し元を作っていきます。

 

今回は nuxt generateという nuxtアプリケーションを静的ファイルとして出力するコマンドを使用していきます。

そのため、このgenerateが実行されたタイミングでデータを取得するようにしましょう。

 

 nuxt.config.jsのgenerateの中に以下のように処理を追加します。

 

まず、先程作成したデータを取得してjsonにする処理を呼びます。

// ./nuxt.config.js

import Articls from './static/json/article.json';
import outputStaticData from './modules/createStaticJson';

module.exports = {
generate: {
async routes() {
// contentfulからデータを取得してjsonにexportする
await outputStaticData();

// 取得したjsonからページを動的生成する
return Articls.items.map(i => {
return `articles/${i.fields.id}`;
});
}
},

 // --- 以下省略 ----

その後に取得したデータから動的なページを生成します。

 

なぜこのような処理をする必要があるかというと

nuxt generateコマンドで静的ページとして出力した場合、

article/{id} のような動的URLのページは生成できないからです。

 

今回は

/ 記事一覧ページ

article/{記事ID} 記事詳細ページ

 

というページ構成で作成するので

contentfulから取得した記事IDをもとに記事詳細ページのroutingを追加しています。

 

5. ブログページ

 最後に、実際に表示するページ部分を作成して行きます。

 

/ 記事一覧ページ

article/{記事ID} 記事詳細ページ

 

という構成にします

 

root /

├ pages/

         index.vue

       articles/

              _id.vue

 

pages 配下の構成がそのままルーティングになるので、こんな感じでvueファイルを配置していきましょう。

 

ここではポイントだけ説明をしていきたいと思います。(vueの説明は省きます)

 

まず、取得したjsonの記事データを表示する方法ですが、jsonをimport してcomputedで参照するのが良いでしょう。

 

// ./pages/index.vue

 const Articls = require('~/static/json/article.json');

export default {
computed: {
articles(){
return Articls.items;
}
}
}

 

詳細ページに関してはurlから対象の記事のデータを抽出します。

 

 // ./pages/article/_id.vue
const Articls = require('~/static/json/article.json');

export default {
computed: {
article(){
const id = this.$router.params.id;
return Articls.items.find(i => i.fields.id == id);
}
}
// 以下省略

 

 

今回contentfulでrichテキストを使用して文章の途中に画像をいれたり、太文字にしたり

といったことを行っています。この richText を表示する部分は少し処理が必要です。

 

 // ./pages/article/_id.vue

import { BLOCKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from "@contentful/rich-text-html-renderer";

export default {
methods: {
toHtmlString(obj) {
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ASSET]: ({ data: { target: { fields }}}) =>
`<img src="${fields.file.url}"/>`,
},
}
return documentToHtmlString(obj, options);
}
},
// 以下省略

このように変換するモジュールがライブラリにあるので、こちらを使用して変換の処理を行う必要があります。

 

template内ではv-htmlで指定し、変換メソッドを指定すればOKです。

 // ./pages/article/_id.vue
<template>
<div v-html="toHtmlString(article.fields.body)"></div>
</template>
// 以下省略

 

Netlify

 アプリケーションの実装が完了したので、次は実際にデプロイします。

今回はNetlifyという静的なサイトを無料でホスティングできるサービスを利用して

githubにpushしたら自動でデプロイされるようにします。 

 

1. 事前準備

 事前準備として、先程作成したアプリケーションをgithuにpushします。

 

$ yarn generate

 

nuxt generateで静的ファイルとしてビルドしましょう。

実行後にdistというディレクトリが作成されていると思います。

 

次に先程作成されたdistディレクトリをgit.ignoreから外します。

 

最後にgit pushでgithubにpushしたら準備完了です。

 

2. アカウント作成

 次にhttps://app.netlify.com/signupからNetlifyのアカウントを作成しましょう。

f:id:frostnday:20190529224337p:plain

今回はgithubと連携したいのでgithubアカウントでsignupします。

 

アカウント作成後のTOPページからgithubリポジトリと連携していきます。

f:id:frostnday:20190529224748p:plain

New site from Gitをクリックします。

 

f:id:frostnday:20190529225120p:plain

GitHubを選択して認証します。

 

f:id:frostnday:20190529225704p:plain

Only select repositoriesを選択肢、連携するgithubリポジトリを選択します。

 

f:id:frostnday:20190529230154p:plain

先程連携したリポジトリを選択肢します。

 

f:id:frostnday:20190529231011p:plain

連携するリポジトリの設定を行います。

① pushがあった場合にhookするブランチを選択します。

 今回は masterを選択しておきます。

 

② pushがあった場合に実行するコマンドを入れます。

コマンドは何も実行しないので未指定でOKです。

 

③ 実際にホスティングする対象となるディレクトリを入力します。

NuxtGenerateを行ったときのデフォルトディレクトリはdistなので今回はdistを指定してましょう。

 

最後に Deploy site でデプロイが開始されます 。

f:id:frostnday:20190530000029p:plain

ビルドが成功するとこのようにURLが表示されます。

 

以上でデプロイ設定は完了です。

 

以降はコンテンツをcontentfulで更新したら、ローカルでnuxt generateを実行し

githubにpushすることで自動でデプロイができます。

 

これでJAMStackなブログが完成しました!!!

 

いかがだったでしょうか?

比較的お手軽に構築からデプロイまで出来たかと思います。

 

今回のブログは完全な静的サイトなので画像など最適化したりすれば阿部寛の速度も夢ではないかもしれません。(笑)

 

サンプルは以下に置いておくので参考にどうぞ

 

サンプルブログ

https://reverent-saha-5d7aec.netlify.com/

 

サンプルソースコード

 https://github.com/frostnday/contentful_nuxt_sample

 

【3分でわかる!】CSSスプライトアニメーションをvue.jsのイベントハンドリングで動かしてみよう

f:id:tomita_ak:20190425143208p:plain

こんにちは!エンジニアのとみたです。

ささやかなネタですが、CSSで実装できるスプライトアニメーションで遊んでみました。

Twitterのいいねボタンのエフェクトにも使われています。

f:id:tomita_ak:20190425101438g:plain

Twitterのいいねボタン

 

スプライトアニメーション用の画像を用意

今回は、弊社が開催しているもくもく会の非公式キャラクター(笑)「プロラボくん」に動いてもらいます

f:id:tomita_ak:20190425101703p:plain

非公式キャラクタープロラボくん

スプライトアニメーション用の画像はこちら。

7つの絵を少しずつ動かします。

f:id:tomita_ak:20190425102718p:plain

スプライトアニメーション用の画像

Illustratorで作成しました。

基準になる絵と枠を一つ作成して、横に並べます。

f:id:tomita_ak:20190425111617p:plain

枠を付けた絵を並べてみました

ここから少しずつ変化をつけていくように作成します。

形式はpngではなく、SVG形式で書き出します。

アニメーションが動いたときに、滑らかに描画されます。pngだと思った以上にギザギザに...。

 

HTMLとCSSを作っていきます!

vue-cliを使って新規プロジェクトを作成します。

今回はApp.vueをそのまま書き換えてしまいます。

まず先程のSVGデータを表示します。

 

HTMLはこちら。

 <template>
<div id="area">
<div class="wrap">
<div class="prorabokunSmile"></div>
</div>
</div>
</template>

 

cssはこちら。

.prorabokunSmile {
background: url(./assets/purorabokun_smile.svg) no-repeat;
background-size: cover; //高さをheightに合わせる
width: 100px; //1コマ目の大きさ
height: 126px; //1コマ目の大きさ
display: inline-block;
margin: 0 50px;
}

 

f:id:tomita_ak:20190425112234p:plain

最初の1コマ目が表示されました

いよいよアニメーションを追加していきます!

HTMLはこちら。smileクラスを追加します。

 <template>
<div id="area">

<div class="wrap">
<div class="prorabokunSmile smile"></div>
</div>

</div>
</template>

 

cssはこちら。

smileクラスと、@keyframesを追加しています。

.prorabokunSmile {
background: url(./assets/purorabokun_smile.svg) no-repeat;
background-size: cover;
width: 100px;
height: 126px;
display: inline-block;
margin: 0 50px;
}
.smile {
animation: animationSmile 1s steps(6) infinite;
}
@keyframes animationSmile {
to {
background-position: -600px 0;
}
}

 

画像を横方向に動かしているだけなのですが、

step関数を使い6段階に切り分けて表示させます。

 

step関数の値は、最初に表示される分を差し引いて、コマ数から1引いた値になります。

今回は7コマのアニメーションなのでsteps(6)となります。

 

アニメーションには任意の名前をつけ、@keyframesと紐づけます。

 

brackground-positionの値は、widthの値*steps関数の値をマイナスさせた値にすると、うまく動きました。100pxの6倍で-600px、といった具合に。

Image from Gyazo
動きました!
vue.jsのイベントハンドリングを使ってみます。

ボタンをクリックすると、 アニメーションが動き出すようにしたい。

 <template>
<div id="area">
<div class="wrap">
<div class="prorabokunSmile"
v-bind:class="{ smile: isActive }"
></div>
</div>
<button v-on:click="move">笑顔!</button>
</div>
</template>

 

jsの指定はこのようにしました。

<script>
export default {
name: 'app',
data () {
return {
isActive: false
}
},
methods: {
move: function () {
this.
isActive = !this.isActive
},
}
}
</script>

 

「笑顔!」ボタンをクリックするとmoveメソッドが動き、isActiveが切り替わり、アニメーションが定義されたsmileクラスが付与されてキャラクターが動いて見える...といった流れです。

Image from Gyazo
クリックするとアニメーションが動くようになりました!

お気に入り登録ボタンや画面遷移にも応用していけそうですね!

 

最後に

ITプロパートナーズでは、Laravel、vue.js、Nuxt.jsで開発に挑戦したいエンジニア・デザイナーを絶賛募集中です!

www.wantedly.com

 

採用以外でも、様々なイベントを開催予定です!ぜひオフィスに遊びに来てください!

今年の3月にオフィスが増床、広くてオシャレなイベントスペースが使えるようになりました!

月に数回開催している「プロラボ」「もくもく会」ではたくさんの方に参加いただいています!

f:id:tomita_ak:20190425131047p:plain

f:id:tomita_ak:20190425131051p:plain

f:id:tomita_ak:20190425131054p:plain

新しいイベントスペース

itpropartners.connpass.com

graspy.jp

Image from Gyazo
ありがとうございました!

PHPを使い続ける理由

柳澤です。
本日のブログを担当します。
よろしくお願いします。

 


ITプロパートナーズは現在5つの事業をやっています。

f:id:yuyayanagisawa:20181206122357p:plain

ITプロパートナーズ事業

 

上記のサービスは全てPHPを使っています。
事業立ち上げ初期の技術選択はとても大切であると考えており、なぜ弊社はPHPを使い続けているのかをお話したいと思います。

 


[ダイバーシティの環境で開発をしている]

弊社では自社サービスであっても弊社に登録いただいているITプロフェッショナルと一緒に開発する機会が多くあります。
現在開発中のGraspy(https://graspy.jp/)では社員以外は在宅で仕事をしてもらう機会も多く、リモートワークで活躍いただいています。
弊社の登録者は2018年12月時点で約2万人に登録いただいており、内訳は以下のようになっています。

 

f:id:yuyayanagisawa:20181204115549p:plain


9,115人と約半数がエンジニアとしての登録になります。
登録者のプログラミング言語別の割合が以下になります。

 

f:id:yuyayanagisawa:20181204115600p:plain


PHPJavascriptを得意とするエンジニアが全体の約1/3の割合となっています。

 

弊社の場合、登録いただいているITプロとチームを結成してプロダクト開発に臨んでいます。
上記は開発言語にPHPを使い続けている理由のひとつでもあります。

 

 

[初期開発メンバーは自分しかいなかった]


僕のエンジニアキャリアはJavaからスタートしました。
JavaC#PHPObjective-CAndroid JavaPHP と経験してきたのですが、生産性を考えたら当時PHPで開発するという選択がベストだと判断しました。
もちろんPHP以外の言語にも興味はありましたし、他のスタートアップはRubyで開発しているからうちもRubyでやりたい、という気持ちも正直ありました。
ただ会社の立ち上げ当初で人数が少ない中、自分がチームに一番貢献できることはやはり、PHPでサービスをつくるということでした。

 

 

f:id:yuyayanagisawa:20181206122101j:plain

立ち上げ当初のオフィススペース

 

 

[PHPを使っているという劣等感]


上でも書きましたが、やはりスタートアップはRubyで開発している企業が多く、弊社のITプロ紹介サービスでもRubyエンジニアを企業様に紹介する機会がすごく多いです。
GoやScalaで開発するという技術的挑戦をしている企業もよく耳にしてましたし、うちも新しい言語や技術に挑戦していくべきではないかと悩んだりもしました。
エンジニアの集まりに参加すると、未だにPHPを使っている古い企業と思われてしまうのではないかと勝手に思い込み、胸を張って「PHP使ってます」と言えませんでした。

 

この劣等感は自分達が提供するサービスに誇りを持ち、多くの人に価値を提供できるサービスに成長させることによって解消されると考えています。

どんな言語を使っても、結局誰にも使われないサービスであれば意味ないですよね。

 


[プロダクトの開発言語はどうやって選ぶか?]

以下の3つのポイントが重要だと考えています。


スピード感のある開発ができるか


スピード感ある開発を行うにはそれまでのノウハウの蓄積が重要であると考えています。
今までずっとPHPで開発してきたので、ゼロから新しい開発言語を使用して開発するよりも圧倒的に早くサービスをリリースすることが可能です。

 

すぐに方向転換できる柔軟性と自由度があるか

サービスの柔軟性、自由度があることにより、試験的にチャレンジできる機会が増えます。
PHPは自由度が高すぎるが故にスパゲッティコードになりがちだという問題がありますが、弊社ではフレームワークをちゃんと理解してつかうことにより、ある程度制約を設けています。
フレームワーク構造を理解し、適切な使い方をするためにペアプログラミング開発を行っています。

 

人材を採用することができるか


サービスがスケールすると開発エンジニアの人数も増やさなければなりません。
難易度の高い言語を開発で選択した場合、採用に苦労します。
市場にはやはりPHPエンジニアエンジニアが多いという印象があり、弊社の登録状況からもやはりPHPエンジニアが一番採用しやすいことがわかります。
人が採用できないが故にプロダクトの成長を止めたくありません。

 


[弊社プロダクトの開発例]

2018年10月に新サービスをリリースしました。

どんな技術を使っているか紹介します。

 

「未来を掴む」キャリア形成プラットフォーム Graspy

graspy.jp

 

Graspyでは以下を使用しています。 

 

サーバサイド開発言語:PHP7
フロントサイド開発言語:Nuxt.js、Vue.js
フレームワーク:Laravel5.5
webサーバ:nginx
DB:RDS(Amazon Aurora
クラウドサーバ:aws(EC2、S3、ELB、route53、cloudfront、他)
その他:docker、SPA、ADRスクラム開発、Git Flow

 

昨年のVueフェスではGoldスポンサーをさせていただきました。

先月のLaravelカンファレンスでもスポンサーとして参加させていただきました。

今後はフロントでNuxt.jsやVue.jsに積極的に取り入れ、スポンサー活動も続けて行なっていきたいと思っています。 

 

[PHPに感謝している]

現在の弊社のサービスは4年前のスタート当時に比べたら使ってもらえる機会も圧倒的に増え、従業員や弊社に関わってくれるITプロもだいぶ増えました。
まだ通過点ではありますが、現在の状況を見ると初期開発をPHPで行うという判断は間違っていなかったと思います。
僕自身は色々な経験や出会いをもたらしてくれたPHPという言語に感謝しています。
PHPを使ってプロダクトを成長させ、多くの人に使ってもらえるサービスにしていくことでPHPコミュニティに貢献できれば嬉しいです。
 


[最後に]


ITプロパートナーズでは、Laravel、vue.js、Nuxt.jsで開発に挑戦したいエンジニア・デザイナーを絶賛募集中です!

少し技術的なことに投資できるフェーズになってきました。
今回Nuxt.jsやVue.jsを取り入れたように、チャンスがあれば新しいチャレンジもしていきたいと考えています。

ちょっとでも興味を持っていただけたら、まずはお話しましょう。

お気軽にご連絡ください!

 

 

www.wantedly.com

 

www.wantedly.com

 

www.wantedly.com

エンジニアドリブンで始める新規サービス開発のススメ

f:id:kumamon_engineer:20190228085445j:plain


ITプロパートナーズのパートナーズ事業部エンジニアチームのリーダーをしている三宅(@miyakey7)です。

今回はITプロパートナーズで、初めてエンジニア主体でサービスの企画から開発までを担った話をしたいと思います。

 

開発したサービスはSNSのつながりを活用した、ソースコード共有サービス「ReviewMe」です!

review-me.tech

サービスの始め方

体制

2018年度下半期が始まる10月、事業部長直下にエンジニア2人と、19卒でエンジニアとして入社するインターン1人の、4人体制でこのプロジェクトは始まりました。

プロジェクトの目的は、本来の業務(ITプロパートナーズメインサイトの開発)とは別に、業務時間を使って新しい取り組み(サービスの開発)に挑戦しよう、ということです。

開発段階では業務委託のデザイナーさんも加わり5人体制になりました。

プロダクトオーナー

普段は事業部長がプロダクトオーナーとしてタスクやサービスの方向を決めるのに対し、今回はエンジニアがプロダクトオーナーになります。

これにより、以下のようなことも今回はエンジニアで決定しました。

  1.  サービスの各種目標数値(KPI設定)
  2.  必要な機能の選定と実装
  3.  システム以外の施策

サービス内容の決定

当然、サービス内容もエンジニアが中心で決めます。今回は以下の軸をベースに開発するサービスを決定しました。

  • エンジニアの助けになるもの
  • ソースコードを使ったもの
  • SNSの特性を活かせるもの

これらを元に「最短の期間で最小の機能」を作っていきました。

結果として

  • エンジニアのアウトプットの第一歩になる簡単な投稿
  • ソースコードが主体の投稿一覧
  • SNSにシェアすることでコードのOGP画像が表示される

という機能を中心に作成しました。

 

詳しくはもう一人のエンジニアでもある、ちゃんなか(@channaka0531)の記事にまとまっています。サービスの方向性決定に言及した内容になっています!

note.mu

サービス名の決定と商標取得

PULLREQ時代

サービス名ももちろんエンジニアが決めます!

今回は商標も取る予定でした。

最初に付けた名前は「PULLREQ(プルリク)」。エンジニアならすぐにイメージが出来る言葉であり、サービス内容を端的に表した素敵な名前でした。

しかし、皆さんご存知の通り、GitHubのPULL REQUEST機能の略称から来ているこの言葉。識別性の観点から、商標を取ることは出来ませんでした。。。(正確には取れる見込みが薄いとのこと)

 

画像も出来てました..お蔵入りがもったいないのでここに貼っておきます..。

f:id:kumamon_engineer:20190228091556p:plain

 

※ちなみに商標調査は代行でお願いすると1回で数万円程度、登録申請代行で内容にもよりますが最小で15万円以上、申請から取得までは時期によって違うらしいですが10ヶ月程かかるそうです!(結構かかりますね..)  

サービス名決定

200を超える名前案をエンジニア3人で出し尽くしました。

その結果、偶然後ろを通った今回のプロジェクトに全く関わっていないエンジニアの一声

「ReviewMe(レビューミー)」

 

f:id:kumamon_engineer:20190228134448p:plain

コレで決まりました!意外なところに答えは落ちているものです。

 

開発期間

ReviewMeはデザイン含め、その全てを「1ヶ月」で作りました。

実際にエンジニアが手を動かしたのは2週間程度です!

 

このスピード感はエンジニアだけで詳細の仕様を口頭+Slackで詰めれた事で実現できたのだと思います。もちろん上長への報告はありますが、プロダクトオーナーである自責が開発を進める上で、大きく影響を与えていたと感じます。

サービスの技術選定

 最短の期間を目指していたため、慣れ親しんだ環境を最優先に選定しました。

サーバー

AWS EC2(Amazon Linux)

RDB

Amazon Aurora(Mysql

サーバーサイド

・Laravel 5.7

フロントエンド

・Vue.js

jQuery(少しだけ)

その他ツール

git/GitHub

一度、サイトのオープンソース化も考えましたが、一旦はprivateで開発しております。

docker

ローカル環境は全てdockerでまとめました。

backlog

スクラム開発のタスク管理として利用しました。

IFTTT

IFTTTの機能によりReviewMeでシェアしたツイートなどを収集できます。更にその内容をSlackに通知することも出来ます。

Slack

コミュニケーションツールはSlackです。多くの議論の結果がSlackに残っています。

RealtimeBoard

ビジネスフレームワーク用に利用しました!詳細は次に書いております!

 

ビジネスフレームワークの利用

リーンキャンバス 

今回はサービスの強み、弱み、価値を明確にするためにリーンキャンバスを利用しました。リーンキャンパスは端的に表すこと、時間をかけすぎないことが重要で、頭の整理に役立ちます。その内容をチームで共有できるので、非常に効果的です。

以下はその時使った枠組みになります!

f:id:kumamon_engineer:20190228094917j:plain

こちら実際の進め方としてはRealtimeBoardの機能を使い、オンライン上でテキストを埋めていきました!URLで共有出来、お互いの反映がリアルタイムで反映されるので便利でした。

realtimeboard.com

ユーザーヒアリング活動

 twitter

twitter上のユーザーの意見を迅速に取得しながら開発改善を行っています!

目標時間は要望ツイートから24時間以内です!

以下はエディタの言語選択にElixirが無いという意見を頂き、対応致しました!

f:id:kumamon_engineer:20190228100238p:plain

使っていて気になる点、要望があればツイートしていただくと幸いです!

もくもく会(ProLabo)

f:id:kumamon_engineer:20190228101903p:plain

弊社イベントスペースではエンジニアが主体で運営しているもくもく会(ProLabo)が月に1回開かれています。

毎回100人を超える応募を頂き、多くのエンジニアやデザイナーが参加していただけています。

itpropartners.connpass.com


今回初期ユーザーとユーザーヒアリングの対象をProLabo参加者に限定しました。

協力してくださった皆さん本当にありがとうございます!

ProLaboは駆け出しのエンジニアや、普段は別の仕事をしながら休日はプログラミングを勉強している方達もたくさん参加しており、そういった人達に使ってもらい意見を直接聞かせてもらいました。

ユーザーFB内容の一部
  • スキルカテゴリが目立つところに欲しい
  • 検索がない

  • ポートフォリオ的に使いたい

などの貴重な意見を貰い、機能開発に役立てることが出来ました!

 

広報活動

今回はじめてPRTimesに載せるプレスリリースの内容を考えました。

普段は何気なく読んでいる記事ですが、実際に自分のサービスで書くとなると、表現一つ取ってもサービスの方向性とずれてないか気になります。

記事で表現する際に再度サービスと向き合い、コレって何のためにあるんだっけと考えるきっかけが起き、自分の作ったサービスですが理解が深まるといった経験ができました。

prtimes.jp

 

 

家族に誇れるサービスを

弊社が掲げるバリューの一つに「家族に誇れるサービスを」というものがあります。これは、提供するサービスに誇りを持ち続けられるように、お客様の声に耳を傾けサービスを改善し続けるべきだということ、どんなに規模が拡大しても、一人一人がお客様への提供価値を考え続けるチームでいること、そして「自分の家族に心から薦められるサービスである」 ということをクオリティの基準にする、というバリューです。

 

私達は全てのサービス開発において、このバリューを大切にしながらを作ることを心掛けています。もちろん今回も同じで、サービスを作る側として立ち返る際の大事な指標になりますし、個人的にとても共感の強いバリューの1つです。

 

サービスの終わり方

もちろん、今は考えていませんがサービスが終わる時を考えることも時には必要かもしれません。サービスを生み出したなら、エンジニアはその最後まで見届けたいというのが私の本音です。(もちろん色んな理由でこれが難しい事は理解しています。)

 

意思決定の方法は以下の点で考えています。

・サービスに誇りを持って、お客様に価値を提供出来ているか

・サービスの成長性/継続性

・コスト面

上から順に重要な指標として置いています。

 

最後が来ないに越した事はありませんが、もし終わらせるなら自分で決断したいと思っています。それがサービスを生むということであり、使ってもらってる人達への責任だと考えます。

 

そしてReviewMeは絶対終わらせないように頑張ります!!

 

最後に

今回エンジニア主体でサービスの企画から開発までを行なったことで、これまで以上にビジネス的視点を持って開発に取り組めるようになりました。

その点において、本来やらない開発以外の実務の経験(広報、サービス名検討、商標取得、ビジネスフレームワーク、KPI設定)は非常に有意義なもので、そこから得た学びをサービスに役立てることが出来たと感じています!

また新規でミニマムなサービス開発においては、エンジニアドリブンはエンジニアにとってもサービスにとっても良い開発手段だと思いました!

 

少人数でまだまだ未熟な開発体制ですが、これからサービスと共に最高のプロダクトチームへと成長できるよう頑張ります。

今後はサービスをグロースさせていくことに注力していくことになります。

エンジニアとしてサービスを開発するだけでなく、サービスをグロースするための視点を養えるチャンスだと思います。そういった経験や視点の話もこれから書いていけたらいいなと考えています!

 

弊社ではサービスにコミットする経験やフェーズに興味のあるエンジニアを絶賛募集中です!僕たちと一緒にReviewMeを作りませんか?

興味ある方は是非フラットにお話し出来ればと思います!

 

www.wantedly.com

 

www.wantedly.com

 

【Nuxt.js/Vue.js】スタートアップ導入事例 LTイベントに参加しました!

f:id:marron-web-engineer:20190202124120p:plain

こんにちは! ITプロパートナーズ(https://itpropartners.jp/)インターンの栗岡です!

普段は、Laravelで自社サービスの開発をしたり、新卒採用関係の業務をやっています。

今回は、1月30日に弊社渋谷オフィスで行われたNuxt.js/Vue.jsで開発しているスタートアップ企業によるLTイベントのレポートを行います!

弊社のエンジニアの米川も登壇しました!

re-build.connpass.com

続きを読む

Vue.jsの開発コードネームが〇〇オタ仕様だという話と、次のコードネームを予想してみる

  • Vue 2.6 が2/4に正式リリース
  • そもそも開発コードネームとは
  • ここでVue.jsの過去のコードネームを見てみましょう
  • となれば予想したくなりますよね
  • 次バージョン(2.7.0)は「N」始まりです。
  • おわりに

 

 

intee 担当エンジニアの五藤です。

弊社では、フロントエンドの処理ではVue.jsを採用することが多いです。

 

そんなVue.jsですが、最近新バージョンがリリースされました。

 

Vue 2.6 が2/4に正式リリース

 

medium.com

 

今回注目すべきはここです。

 

— today we are excited to announce the release of Vue 2.6 “Macross”!

 

開発コードネームが Macross ??

 

しかもリリース記事には何やらそれっぽい戦闘機の画像が。ちゃんと可変ギミックもありそう

 

そもそも開発コードネームとは

ソフトウェアやライブラリの開発で、いわゆる正式名称やバージョン番号とは別に、愛称のような物を付けるケースがあります。

有名どころでは、Android OSの「Lolipop」「KitKat」のようなお菓子縛りや、MacOS では「Mavericks」「Sierra」など、カリフォルニアの地名が付けられています。

 開発コードをつける背景としては

  • 正式名称が決まるまでの仮の通称
  • 開発時、バージョン数字で呼ぶよりも識別しやすい(OSSの場合は、たいてい複数のバージョンを平行して開発するため、var2.0ではこの機能があってvar2.1ではこうする〜みたいな話が入り乱れます)
  • ユーザー側に愛着を持ってもらう

などなどです。

ここでVue.jsの過去のコードネームを見てみましょう

version 開発コードネーム 日本語名称 アニメ初出年 制作会社
v2.6 Macross 超時空要塞マクロス 1982年 タツノコプロ
v2.5 Level E レベルE 2011年 Studioピエロ✕david production
v2.4 Kill la Kill キルラキル 2013年 TRIGGER
v2.3 JoJo's Bizarre Adventure ジョジョの奇妙な冒険 1993年 A.P.P.P
v2.2 Initial D 頭文字D 1998年 スタジオコメットぎゃろっぷ
v2.1 Hunter X Hunter HUNTER✕HUNTER 1999年 スタジオディーン日本アニメーション
v2.0 Ghost in the Shell GHOST IN THE SHELL / 攻殻機動隊 1995年 Production I.G
v1.0 Evangelion 新世紀エヴァンゲリオン 1995年 タツノコプロGAINAX
v0.12.0 Dragon Ball ドラゴンボール 1986年 東映動画
v0.11.0 Cowboy Bebop カウボーイビバップ 1998年 サンライズ
v0.12.0 Blade Runner - 1982年 -
v0.12.0 Animatrix アニマトリックス 2003年 スクウェアUSA、STUDIO 4℃マッドハウス

 ・・・予想以上にアニオタだぞこれ!?   

海外アニメファンの評価が高い「攻殻機動隊」「カウボーイビバップ」「ドラゴンボール」辺りを押さえつつ、2010年台の「キルラキル(2013-2014)」「レベルE(2011)」あたりを混ぜてみたりと、結構なこだわりようです。

そして命名にはルールがあり、Animatrix から Macross まで、綺麗に先頭の頭文字がアルファベット順に並んでいます。 (頭文字Dのイニシャルが「D」ではなくて「I」扱いなのは若干納得がいかない)

ちなみに最初期は
Animatrix(超有名SF映画マトリックス」のアニメスピンオフ作品)
Blade Runner(カルト的な人気を誇る古典SF映画)」

と、どちらかといえばSF路線の名前をつけていたけど、少しずつ吹っ切れてきた模様。

 

また、Vue.jsの作者である Evan Youの個人サイトのプロフィールには

evanyou.me

 

Outside of programming and helping my wife take care of our two kids, I enjoy video games, karaoke, sushi and collecting watches.

プログラミングと育児以外では 、ビデオゲームやカラオケ、寿司、時計の収集が趣味です。

とあります。ものすごくアニメが好き!というのを全面に押し出しているわけではないですが、コードネームの並びを見る限りは、結構なアニメ好きなのが見て取れます。

(なお、後述の予想サイトには、Kazuponさんを始めとしたContributorも次Verの予想を書き込んでいるため、コードネームはEvan氏が一人で決めている可能性が高いです。)

 

となれば予想したくなりますよね

アルファベット順、というルールがある以上、予想したくなるのが人の常、ということで、次バージョンのコードネームの予想を議論するサイトもすでに出来ていたりします。

 

github.com

 

最新の2.6に対するissueでは「Macross」と「Monster」が2大予想になっていたので、見事的中していた模様。

 

次バージョン(2.7.0)は「N」始まりです。

折角なので本ブログでも次バージョンを予想してみます。

大本命:NARUTO

大本命は、忍者をフューチャーした世界観と、圧倒的なアクション作画で海外から圧倒的な支持を得ているこの作品。海外においては、アニメ好き=NARUTO好き、と言っても過言ではありません。
過去のコードネームで「DRAGON BALL」「攻殻機動隊」などの超有名作品をしっかりと押さえていることを考えると非常に可能性は高いです。
という雰囲気すらします。むしろ、この先Vue.jsのシェアが伸びてきた場合、Vue.jsのコードネームに採用される=超有名アニメとして認められる 、というコンセンサスが社会的に形成されることも十分考えられるので、むしろ、
「この流れでNARUTOを外していいのか?」
という雰囲気すら感じられます。

微妙に何を言っているのかわかりませんが、2.7.0はかなりの可能性で「NARUTO」が採用されると言って間違いがないと思います。

次点:機動戦艦ナデシコ(Mobile Buttleship Nadeshiko)

エヴァンゲリオンで一般層を巻き込んだ空前のアニメブームが起きていた90年代後半時代に、重厚なSF設定と軽妙なシナリオで人気を博した名作です。唯一対抗馬になりそうなのはこれくらいでしょうか。

有力な要素

  • 直近で「レベルE」「キルラキル」「マクロス」など、アニメファン以外も知っているような超有名作品ではない作品を出してきており、「私はこんな作品も知ってるよ!」という路線で考えた場合は非常に有力

懸念点

  • 前バージョンがマクロスだったので、同じロボット系SFアニメを連載することを避けるのではないか
  • 海外での知名度がそれほど高くない

 個人的には好きなんですけどね、ナデシコ

大穴:風の谷のナウシカ(Nausicaa of the Valley of The Wind)

言わずとしれたジブリアニメの雄ですね。

 

有力な要素

  • コードネームを考える中で「ジブリアニメから1回は採用したい」と考えている場合はかなり有力。(他のタイトルは、「千と千尋の神隠し(Spirited Away)」など作品名に修飾語が多く、イニシャルを意識しづらいものが多い)

懸念点

  • 海外での評価はそれほど高くない(いわゆる海外アニメ人気の文脈において、日本のそれほど王道的な立ち位置ではない)

ジブリアニメ自体は非常に有力なのですが、
NARUTO」か「ナウシカ」の2択だと、NARUTOを選ぶような気がするんですよね・・・。
これが「NARUTO」と「ナデシコ」の2択だと、ナデシコを選ぶ可能性がありそうに感じてしまうのは、なんとなくアニメファンの業みたいなものを感じます。

 

 

以上、Vue.jsのコードネーム界隈の話でした!
フロントエンド界隈では確固たる地位を得たVue.jsですが、本筋とは別に、こんな楽しみ方も提供していることを知ってもらえれば幸いです!

 

続きを読む

毎月恒例!#ProLabo(プロラボ)渋谷もくもく会@渋谷1月12日(土)に開催しました! 

こんにちは! ITプロパートナーズ(https://itpropartners.jp/)インターン栗岡です!

普段は、Laravelで自社サービスの開発をしたり、新卒採用関係の業務をやっています。

今回は、1月12日に弊社渋谷オフィスで開催されたもくもく会をレポートします!

続きを読む