Posted on

Nuxt.js v2.9のリリース情報とDiff

2019年8月20日にNuxt.jsのバージョンが2.8.1から2.9へがリリースされました。2019年9月19日時点ではバージョン2.9.2まであがっています。本投稿ではリリース内容と変更点が見れるように2.8.1から2.9.1のソースのDiffと変更されたファイル一覧を載せておきます。変更ファイル数は、examplestestを除くと約142ファイルでした。またバージョンが上がっただけ、関数にスペースが追加されただけのファイルも多く、それを除くともっと少なくなります。
本リリースでの大きな変更はImportant Notesの中でもTypescript関連の変更が個人的には大きいと思います。Nuxt Typescriptの導入やMigrationはリリースノートにあるページの SetupMigration from Nuxt 2.8 を見れば簡単に行えます。(本記事の一番下でも試しにやってみました。)

リリースノート

nuxtjs.org

Due to a known problem (webpack/webpack#8656, #4869, #4839) users of npm should either remove package-lock.json and reinstall before upgrade or use npm update acorn –depth 20 && npm dedupe after upgrading to 2.4.0. users should have no problems but removing yarn.lock still recommended before the upgrade process.

Diff

v2.8.1からv2.9.2のDiffをつくってみました。

v2.9.2 diff by taisa831 · Pull Request #1 · taisa831/nuxt.js

Types of changes Bug fix (a non-breaking change which fixes an issue) New feature (a non-breaking change which adds functionality) Breaking change (fix or feature that would cause existing functionality to change) Description Checklist: My change requires a change to the documentation. I have updated the documentation accordingly.

変更ファイル

nuxt.js v2.8.1 -> v2.9.2

examples examples,examples/async-component-injection/pages/_slug.vue examples,examples/async-data/pages/posts/_id.vue examples,examples/async-data/pages/posts/index.vue …

examplestestを除いた変更ファイル一覧

  • .circleci/config.yml
  • .eslintignore
  • .eslintrc.js
  • README.md
  • babel.config.js
  • distributions/nuxt-start/package.js
  • distributions/nuxt-start/package.json
  • distributions/nuxt-ts/README.md
  • distributions/nuxt-ts/bin/nuxt-ts.js
  • distributions/nuxt-ts/package.js
  • distributions/nuxt-ts/package.json
  • distributions/nuxt/README.md
  • distributions/nuxt/package.js
  • distributions/nuxt/package.json
  • jest.config.js
  • lerna.json
  • package.json
  • packages/babel-preset-app/README.md
  • packages/babel-preset-app/package.json
  • packages/babel-preset-app/src/index.js
  • packages/babel-preset-app/src/polyfills-plugin.js
  • packages/builder/package.json
  • packages/builder/src/builder.js
  • packages/builder/src/context/build.js
  • packages/builder/src/context/template.js
  • packages/builder/src/ignore.js
  • packages/cli/package.json
  • packages/cli/src/command.js
  • packages/cli/src/commands/build.js
  • packages/cli/src/commands/dev.js
  • packages/cli/src/commands/generate.js
  • packages/cli/src/commands/help.js
  • packages/cli/src/commands/index.js
  • packages/cli/src/commands/start.js
  • packages/cli/src/imports.js
  • packages/cli/src/index.js
  • packages/cli/src/list.js
  • packages/cli/src/options/common.js
  • packages/cli/src/options/index.js
  • packages/cli/src/options/server.js
  • packages/cli/src/run.js
  • packages/cli/src/setup.js
  • packages/cli/src/utils/banner.js
  • packages/cli/src/utils/config.js
  • packages/cli/src/utils/formatting.js
  • packages/cli/src/utils/index.js
  • packages/cli/src/utils/memory.js
  • packages/cli/src/utils/typescript.js
  • packages/config/index.d.ts
  • packages/config/package.json
  • packages/config/src/config/_app.js
  • packages/config/src/config/_common.js
  • packages/config/src/config/build.js
  • packages/config/src/config/index.js
  • packages/config/src/options.js
  • packages/config/types/build.d.ts
  • packages/config/types/env.d.ts
  • packages/config/types/fetch.d.ts
  • packages/config/types/generate.d.ts
  • packages/config/types/globals.d.ts
  • packages/config/types/head.d.ts
  • packages/config/types/hooks.d.ts
  • packages/config/types/index.d.ts
  • packages/config/types/loading.d.ts
  • packages/config/types/module.d.ts
  • packages/config/types/plugin.d.ts
  • packages/config/types/render.d.ts
  • packages/config/types/router.d.ts
  • packages/config/types/server-middleware.d.ts
  • packages/config/types/server.d.ts
  • packages/config/types/vue-configuration.d.ts
  • packages/config/types/watchers.d.ts
  • packages/core/package.json
  • packages/core/src/hookable.js
  • packages/core/src/module.js
  • packages/core/src/nuxt.js
  • packages/core/src/resolver.js
  • packages/generator/package.json
  • packages/generator/src/generator.js
  • packages/server/package.json
  • packages/server/src/context.js
  • packages/server/src/jsdom.js
  • packages/server/src/listener.js
  • packages/server/src/middleware/error.js
  • packages/server/src/middleware/nuxt.js
  • packages/server/src/middleware/timing.js
  • packages/server/src/server.js
  • packages/typescript/package.js
  • packages/typescript/package.json
  • packages/typescript/src/index.js
  • packages/utils/package.json
  • packages/utils/src/cjs.js
  • packages/utils/src/context.js
  • packages/utils/src/lang.js
  • packages/utils/src/locking.js
  • packages/utils/src/modern.js
  • packages/utils/src/resolve.js
  • packages/utils/src/route.js
  • packages/utils/src/serialize.js
  • packages/utils/src/task.js
  • packages/utils/src/timer.js
  • packages/vue-app/index.d.ts
  • packages/vue-app/package.json
  • packages/vue-app/src/index.js
  • packages/vue-app/template/App.js
  • packages/vue-app/template/client.js
  • packages/vue-app/template/components/no-ssr.js
  • packages/vue-app/template/components/nuxt-build-indicator.vue
  • packages/vue-app/template/components/nuxt-child.js
  • packages/vue-app/template/index.js
  • packages/vue-app/template/router.js
  • packages/vue-app/template/router.scrollBehavior.js
  • packages/vue-app/template/utils.js
  • packages/vue-app/types/index.d.ts
  • packages/vue-app/types/process.d.ts
  • packages/vue-app/types/vue.d.ts
  • packages/server/src/middleware/nuxt.js
  • packages/server/src/middleware/timing.js
  • packages/server/src/server.js
  • packages/typescript/package.js
  • packages/typescript/package.json
  • packages/typescript/src/index.js
  • packages/utils/package.json
  • packages/utils/src/cjs.js
  • packages/utils/src/context.js
  • packages/utils/src/lang.js
  • packages/utils/src/locking.js
  • packages/utils/src/modern.js
  • packages/utils/src/resolve.js
  • packages/utils/src/route.js
  • packages/utils/src/serialize.js
  • packages/utils/src/task.js
  • packages/utils/src/timer.js
  • packages/vue-app/index.d.ts
  • packages/vue-app/package.json
  • packages/vue-app/src/index.js
  • packages/vue-app/template/App.js
  • packages/vue-app/template/client.js
  • packages/vue-app/template/components/no-ssr.js
  • packages/vue-app/template/components/nuxt-build-indicator.vue
  • packages/vue-app/template/components/nuxt-child.js
  • packages/vue-app/template/index.js
  • packages/vue-app/template/router.js
  • packages/vue-app/template/router.scrollBehavior.js
  • packages/vue-app/template/utils.js
  • packages/vue-app/types/index.d.ts
  • packages/vue-app/types/process.d.ts
  • packages/vue-app/types/vue.d.ts
  • packages/vue-renderer/package.json
  • packages/vue-renderer/src/renderer.js
  • packages/vue-renderer/src/renderers/base.js
  • packages/vue-renderer/src/renderers/modern.js
  • packages/vue-renderer/src/renderers/spa.js
  • packages/vue-renderer/src/renderers/ssr.js
  • packages/webpack/package.json
  • packages/webpack/src/builder.js
  • packages/webpack/src/config/base.js
  • packages/webpack/src/config/client.js
  • packages/webpack/src/config/modern.js
  • packages/webpack/src/config/server.js
  • packages/webpack/src/plugins/vue/client.js
  • packages/webpack/src/plugins/vue/cors.js
  • packages/webpack/src/plugins/vue/modern.js
  • packages/webpack/src/plugins/vue/server.js
  • packages/webpack/src/plugins/warning-ignore.js
  • packages/webpack/src/utils/perf-loader.js
  • packages/webpack/src/utils/postcss.js
  • packages/webpack/src/utils/style-loader.js
  • renovate.json
  • scripts/changelog.js
  • scripts/dev.js
  • scripts/link.js
  • scripts/package.js
  • scripts/rollup.config.js

Nuxt Typescriptプロジェクトを新規作成する

npx create-nuxt-appNuxtプロジェクトを新規作成する
※ この時点ではTypescriptのソースがある場合は起動できませんがなにもしなければ起動します。

npx create-nuxt-app 
cd 

分離されて新しくなったnuxt/typescript-buildをインストールする

yarn add --dev @nuxt/typescript-build
# OR
npm install --save-dev @nuxt/typescript-build

nuxt.config.jsbuildModules@nuxt/typescript-buildを追記する

// nuxt.config.js
buildModules: ['@nuxt/typescript-build']

tsconfig.jsonを新規作成する

// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/types"
    ]
  },
  "exclude": [
    "node_modules"
  ]
}

このまま起動すると以下のように怒られる場合があるのでtsconfig.jsoncompilerOptions"experimentalDecorators"を追記する

ERROR in /Users/tt-dev/src/taisa831/nuxt-typescript/components/TodoList.vue(47,22):                                                                                                                                                           nuxt:typescript 11:06:14
47:22 Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.
// tsconfig.json
  "compilerOptions": {
    "experimentalDecorators": true
  }

起動するとTypescriptのコードが入っていても問題なく表示されます🎉

npm run dev

※ 既存プロジェクトからのMigration方法は以下です。
https://typescript.nuxtjs.org/migration.html

参考

https://typescript.nuxtjs.org/guide/setup.html#configuration

Posted on

Vue.js+TypeScriptで外部APIを使ったTODOリストを作ってみた

Vue.jsで外部APIを使ったTODOリストを作ってみた に続き、それのTypeScript版を作ってみました。TODOリスト用のAPIは以前書いたこちらのAPI「Go言語 GORM+GinでTODOリストのAPIを作ってみた」を利用します。CORSを全て許可しているのでどこからでも叩けるようになっています。TypeScriptを書くのは今回が初めてなので、誤っている箇所やもっとよい書き方などがあれば指摘して頂ければと思います。

できたもの

できたものはこちらです。
http://vuejs-ts.taisablog.com/todo

APIのエンドポイント

APIのエンドポイントは以下としました。

URL    http://gin.taisablog.com/api/v1/
GET    /todo       // 一覧表示
POST   /todo       // 新規作成
GET    /todo/:id   // 編集画面表示
PUT    /todo/:id   // 編集(今回未使用)
DELETE /todo/:id   // 削除

プロジェクト作成

vue-cliを使ってプロジェクト作成をしました。プロジェクト作成のコマンドを打つと、色々と聞かれますが、TypeScriptを利用する為にManually select featuresを選択し、TypeScriptをONにします。ここではRouterもONにしました。

% npm install -g @vue/cli
% vue create my-project
  default (babel, eslint)
❯ Manually select features

vue-cliでできたプロジェクトのsrc配下の構成は以下となっています。今回はそこにTodo.vueTodoList.vueを追加して実装しました。views配下で実装するだけでも大丈夫ですが、今回はあえてviews/Todo.vueからTodoList.vueコンポーネントを呼び出す形としました。

.
├── App.vue
├── assets
│   └── logo.png
├── components
│   ├── HelloWorld.vue
│   └── TodoList.vue ← 新規追加
├── main.ts
├── router.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
└── views
    ├── About.vue
    ├── Home.vue
    └── Todo.vue ← 新規追加

views/Todo.vue

TodoList.vueコンポーネントを呼び出します。


  
Vue logo
import { Component, Vue } from 'vue-property-decorator' import TodoList from '@/components/TodoList.vue' @Component({ components: { TodoList, }, }) export default class Todo extends Vue {}

components/TodoList : importとクラス定義

axiosを利用するのでインストールします。

% npm i axios
import { Component, Vue } from 'vue-property-decorator'
import axios from 'axios'
const NOT_STARTED = 1
const FINISHED = 3
@Component
export default class TodoList extends Vue {
   ここに実装
}

インスタンス変数定義

private todoList: string[] = []
private inputField: string = ''
private baseUrl: string = 'http://gin.taisablog.com/api/v1/'

createdフック

createdフックでロード時に一覧を取得します。

public created() {
  this.getTodo()
}

一覧を取得する

public async getTodo() {
  try {
    const response = await axios.get(this.baseUrl + 'todo')
    this.todoList = response.data
    return this.todoList
  } catch (e) {
    return e
  }
}

タスクを追加する

public async addTodo() {
  if (!this.inputField) {
    return
  }
  try {
    const params = {
      text: this.inputField,
      status: 1,
    }
    await axios.post(this.baseUrl + 'todo', JSON.stringify(params))
    this.getTodo()
    this.inputField = ''
  } catch (e) {
    return e
  }
}

タスクを削除する

public async deleteTodo(todo: any) {
  try {
    await axios.delete(this.baseUrl + 'todo/' + todo.ID)
    this.getTodo()
  } catch (e) {
    return e
  }
}

タスクを完了にする

public async toggle(todo: any) {
  try {
    let status = 0
    if (todo.Status === NOT_STARTED) {
      status = FINISHED
    } else {
      status = NOT_STARTED
    }
    const params = {
      '{status}': status,
    }
    await axios.put(this.baseUrl + 'todo/' + todo.ID, JSON.stringify(params))
    todo.Status = status
  } catch (e) {
    return e
  }
}

HTML

HTMLとCSSはもう少し書き直したいです。


    

Vue.js TODO List

  • {{ todo.Text }}
    {{ todo.Text }}
    X

TodoList.vue全部


    

Vue.js TODO List

  • {{ todo.Text }}
    {{ todo.Text }}
    X
import { Component, Vue } from 'vue-property-decorator' import axios from 'axios' const NOT_STARTED = 1 const FINISHED = 3 @Component export default class TodoList extends Vue { private todoList: string[] = [] private inputField: string = '' private baseUrl: string = 'http://gin.taisablog.com/api/v1/' public created() { this.getTodo() } public async getTodo() { try { const response = await axios.get(this.baseUrl + 'todo') this.todoList = response.data return this.todoList } catch (e) { return e } } public async addTodo() { if (!this.inputField) { return } try { const params = { text: this.inputField, status: 1, } await axios.post(this.baseUrl + 'todo', JSON.stringify(params)) this.getTodo() this.inputField = '' } catch (e) { return e } } public async deleteTodo(todo: any) { try { await axios.delete(this.baseUrl + 'todo/' + todo.ID) this.getTodo() } catch (e) { return e } } public async toggle(todo: any) { try { let status = 0 if (todo.Status === NOT_STARTED) { status = FINISHED } else { status = NOT_STARTED } const params = { '{status}': status, } await axios.put(this.baseUrl + 'todo/' + todo.ID, JSON.stringify(params)) todo.Status = status } catch (e) { return e } } } .todoList { width: 100%; } .clearfix::after { content: ''; display: block; clear: both; } .inputWrapper { position: relative; width: 380px; margin: auto; display: block; } .inputWrapper input[type='text'] { font: 15px/24px sans-serif; box-sizing: border-box; width: 100%; padding: 0.3em; transition: 0.3s; letter-spacing: 1px; border: 1px solid #1b2538; border-radius: 4px; } .ef input[type='text']:focus { border: 1px solid #da3c41; outline: none; box-shadow: 0 0 5px 1px rgba(218, 60, 65, .5); } .txtBoxWrapper { float: left; width: 270px; } .addBtnWrapper { float: right; } .addBtn { position: relative; display: block; text-decoration: none; color: #FFF; background: #007bff; border: solid 1px #007bff; border-radius: 4px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); width: 100px; height: 35px; font-size: 16px; } ul { list-style: none; } li { border: 1px solid #dee2e6; border-top-left-radius: .25rem; border-top-right-radius: .25rem; margin: 10px auto; width: 50%; height: 80px; } .todo { display: flex; justify-content: space-between; align-items: center; width: 100%; height: 100%; } .chkboxLabel { width: 20px; display: inline-block; text-align: left; margin-right: 10px; } .chkbox { transform: scale(1.3); margin-left: 10px; } .todoTxt { font-size: 20px; width: 100%; text-align: center; vertical-align: middle; display: inline-block; } .todoTxt.NotStarted { text-decoration: none; } .todoTxt.Finished { text-decoration: line-through; } .deleteBtn { color: pink; text-align: right; margin-right: 20px; margin-left: 10px; width: 20px; display: block; font-size: 20px; cursor: pointer; } @media screen and (max-width: 520px) { ul { list-style: none; padding: 0; margin: 0; } li { border: 1px solid #dee2e6; border-top-left-radius: .25rem; border-top-right-radius: .25rem; margin: 10px 0; width: 100%; height: 80px; padding: 0; } .inputWrapper { margin: 0px auto } }

ソース

https://github.com/taisa831/sandbox-vuejs-ts

まとめ

TypeScriptを書くのが初めてだったので(書籍自体あまりなかったですが)事前に2冊購入して読みました。学習コストが大変かと思っていましたが、評判通りJavaやC#のようなサーバサイドのように書けるので書きやすくてよいです。


Posted on

Vue.jsで外部APIを使ったTODOリストを作ってみた

APIを使ったTODOリストをVue.jsで作ってみました。TODOリスト用のAPIは以前書いたこちらのAPI「Go言語 GORM+GinでTODOリストのAPIを作ってみた」を利用します。CORSを全て許可しているのでどこからでも叩けるようになっています。

できたもの

できたものはこちらです。http://vuejs.taisablog.com/todo

APIのエンドポイント

APIのエンドポイントは以下としました。

URL    http://gin.taisablog.com/api/v1/
GET    /todo       // 一覧表示
POST   /todo       // 新規作成
GET    /todo/:id   // 編集画面表示
PUT    /todo/:id   // 編集(今回未使用)
DELETE /todo/:id   // 削除

TODOリストの処理

プロジェクトはvue-cliで作成し、APIはaxiosを利用しました。componentsTodo.vueファイルを作成しそこにすべての処理を書いています。

インポート

import axios from 'axios'
const NOT_STARTED = 1 // 未対応
const STARTED = 2 // 対応中
const FINISHED = 3 // 完了

data function

name: "Todo",
data() {
  return {
    todoList: [],
    inputField: '',
    isActive: false,
    baseUrl: 'http://gin.taisablog.com/api/v1/'
  }
},

created function

created() {
  this.getTodo()
},

methods : 一覧を取得する

async getTodo() {
  try {
    let response = await axios.get(this.baseUrl + 'todo')
    this.todoList = response.data
  } catch (e) {
    console.log(e)
  }
},

methods : タスクを追加する

async addTodo() {
  // inputFieldの空チェック
  if (!this.inputField) {
    return
  }
  try {
    let params = {
      'text': this.inputField,
      'status': 1
    }
    await axios.post(this.baseUrl + 'todo', JSON.stringify(params))
    // 一覧取得
    this.getTodo()
    // inputFieldを空にする
    this.inputField = ''
  } catch (error) {
    console.log(error)
  }
},

methods : タスクを削除する

async deleteTodo(todo) {
  try {
    await axios.delete(this.baseUrl + 'todo/' + todo.ID)
    // 一覧を取得する
    this.getTodo()
  } catch (e) {
    console.log(e)
  }
},

methods : タスクを完了にする

async toggle(todo) {
  try {
    let status = 0
    if (todo.Status === NOT_STARTED) {
      status = FINISHED
    } else {
      status = NOT_STARTED
    }
    let params = {
      'status': status
    }
    await axios.put(this.baseUrl + 'todo/' + todo.ID, JSON.stringify(params))
    todo.Status = status
  } catch (e) {
    console.log(e)
  }
}

HTML


    

Vue.js TODO List

  • {{ todo.Text }}
    {{ todo.Text }}
    X

Todo.vue全部

HTMLとスタイルはあえてフレームワークを使わず自力で作成したのでボロボロです。


    

Vue.js TODO List

  • {{ todo.Text }}
    {{ todo.Text }}
    X
import axios from 'axios' const NOT_STARTED = 1 // 未対応 const STARTED = 2 // 対応中 const FINISHED = 3 // 完了 export default { name: "Todo", data() { return { todoList: [], inputField: '', isActive: false, baseUrl: 'http://gin.taisablog.com/api/v1/' } }, created() { this.getTodo() }, methods: { async getTodo() { try { let response = await axios.get(this.baseUrl + 'todo') this.todoList = response.data } catch (e) { console.log(e) } }, async addTodo() { if (!this.inputField) { return } try { let params = { 'text': this.inputField, 'status': 1 } await axios.post(this.baseUrl + 'todo', JSON.stringify(params)) this.getTodo() this.inputField = '' } catch (error) { console.log(error) } }, async deleteTodo(todo) { try { await axios.delete(this.baseUrl + 'todo/' + todo.ID) this.getTodo() } catch (e) { console.log(e) } }, async toggle(todo) { try { let status = 0 if (todo.Status === NOT_STARTED) { status = FINISHED } else { status = NOT_STARTED } let params = { 'status': status } await axios.put(this.baseUrl + 'todo/' + todo.ID, JSON.stringify(params)) todo.Status = status } catch (e) { console.log(e) } } }, } .todoList { width: 100%; } .clearfix::after { content: ''; display: block; clear: both; } .inputWrapper { position: relative; width: 380px; margin: auto; display: block; } .inputWrapper input[type='text'] { font: 15px/24px sans-serif; box-sizing: border-box; width: 100%; padding: 0.3em; transition: 0.3s; letter-spacing: 1px; border: 1px solid #1b2538; border-radius: 4px; } .ef input[type='text']:focus { border: 1px solid #da3c41; outline: none; box-shadow: 0 0 5px 1px rgba(218, 60, 65, .5); } .txtBoxWrapper { float: left; width: 270px; } .addBtnWrapper { float: right; } .addBtn { position: relative; display: block; text-decoration: none; color: #FFF; background: #007bff; border: solid 1px #007bff; border-radius: 4px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); width: 100px; height: 35px; font-size: 16px; } ul { list-style: none; } li { border: 1px solid #dee2e6; border-top-left-radius: .25rem; border-top-right-radius: .25rem; margin: 10px auto; width: 50%; height: 80px; } .todo { display: flex; justify-content: space-between; align-items: center; width: 100%; height: 100%; } .chkboxLabel { width: 20px; display: inline-block; text-align: left; margin-right: 10px; } .chkbox { transform: scale(1.3); margin-left: 10px; } .todoTxt { font-size: 20px; width: 100%; text-align: center; vertical-align: middle; display: inline-block; } .todoTxt.NotStarted { text-decoration: none; } .todoTxt.Finished { text-decoration: line-through; } .deleteBtn { color: pink; text-align: right; margin-right: 20px; margin-left: 10px; width: 20px; display: block; font-size: 20px; cursor: pointer; } @media screen and (max-width: 520px) { ul { list-style: none; padding: 0; margin: 0; } li { border: 1px solid #dee2e6; border-top-left-radius: .25rem; border-top-right-radius: .25rem; margin: 10px 0; width: 100%; height: 80px; padding: 0; } .inputWrapper { margin: 0px auto } }

ソース

ソースはこちらにあがっています。
https://github.com/taisa831/sandbox-vuejs

まとめ

もっとスマートな書き方があるかしれませんが、これで一通り動作するようになりました。次はこれをTypeScriptに書き換えたものを作成する予定です。HTMLとCSSに一番時間がかかったのでもっとスマートにさらっと書けるようになりたいです。

Posted on

Firebase Cloud Firestore 使い方の勘ドコロ

FirebaseのCloud Firestoreを扱う際、本家ドキュメントが充実していて検索すればすぐに出てくるのでそれほど困ることはありません。ただ、最初の入りとしてFiresotreのDocumentって何? となったり、docdocRefcityRefcityDocRefsnapShotdocs など、本家ドキュメントの中でも若干変数名の書き方が異なっていたりします。その為、慣れてくれば大丈夫ですが、慣れるまで毎回どう書くんだっけ?と検索することが多かったので、自分なりに解釈して整理してみました。Firestoreを扱える言語は様々用意されていますが、ここでは、JavaScript(Nuxt.js)を例に進めていきます。(セットアップは省きます)

参照元:https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja

Firestoreの基本的な考え方

基本的な考え方は、正にこの図にあるように「フォルダ(collection)」「ドキュメント(document)」「データ」という構成になっています。

参照元:https://firebase.google.com/docs/firestore/data-model
これをFirestoreの管理画面でみるとこのようになります。

これを「フォルダ(collection)」「ドキュメント(document)」「データ」に当てはめてみるとこのようになります。イメージとしては、本棚にフォルダが並んでいてフォルダを選択するとフォルダの中のファイル一覧がみることができ、あるファイルを選択するとそのファイルに書かれている内容をみることができるという感じです。

◯◯Refとは

本家ドキュメントをみると、◯◯Refという変数がよく出てきます。これはその名の通り「参照」です。つまり本棚にあるフォルダ(collection)やフォルダ内のドキュメントを選択した状態です。この時点ではまだ参照なので取得はしていません。usersコレクションを選択した状態であればuserRefusersコレクションのドキュメントを選択した状態であればuserDocRefといった変数をつけると分かりやすいと思います。(本家ドキュメントではそのようなルール決めはありません。)

userRef = db.collection('users')
userDocRef = db.collection('users').doc('YLu7bG7PcRNYhAg3F6MY')

これらを踏まえて、実際にデータの取得、追加、更新、削除のコードを書いてみます。ここではあえて◯◯Refのように変数を使っています。

コレクション配下のドキュメントデータをすべて取得する

usersコレクションを参照した状態で、get().then()を呼び出すとその時点のドキュメント一覧(snapShot)が取得できます。ドキュメントは1つしか存在しない可能性もありますが、ドキュメント一覧なのでforEachでループすることで全データを取得することができます。ユーザIDはデフォルトでドキュメントに振られるIDです。

const db = firebase.firestore();
let userRef = db.collection('users')
userRef.get().then((snapShot) => {
  snapShot.forEach((doc) => {
    this.users.push({
      user: doc.data(),
      user_id: doc.id
    })
  })
})
ユーザID ユーザ名 ユーザメールアドレス
{{user.user_id}} {{user.user.name}} {{user.user.email}}

参考:https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja

コレクション配下のドキュメントデータをフィルタして取得する

フィルタするのにwhereを利用することができます。whereで対象を絞った後、同様にget().then()を呼び出すとフィルタしたドキュメント一覧が取得できます。

const db = firebase.firestore();
let userRef = db.collection('users')
userRef.where('name', '==', '山田太郎1').get().then((snapShot) => {
  snapShot.forEach((doc) => {
    this.filteredUsers.push({
      user: doc.data(),
      user_id: doc.id
    })
  })
})
ユーザID ユーザ名 ユーザメールアドレス
{{user.user_id}} {{user.user.name}} {{user.user.email}}

参考:https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja

単一のドキュメントデータを取得する

単一のドキュメントデータを取得するには、doc()IDを渡し、get().then()を呼び出すと指定したドキュメントのデータが取得できます。この場合、doc()で単一のドキュメントを指定しているので、取得できるのは一覧ではなく指定したドキュメントの値となります。

const db = firebase.firestore();
let userRef = db.collection('users')
userRef.doc('YLu7bG7PcRNYhAg3F6MY').get().then((doc) => {
  this.user = doc.data()
  this.user.user_id = doc.id
})

これは以下のようにも書くことができます。

const db = firebase.firestore();
let userDocRef = db.collection('users').doc('YLu7bG7PcRNYhAg3F6MY')
userDocRef.get().then((doc) => {
  this.user = doc.data()
  this.user.user_id = doc.id
})
ユーザID ユーザ名 ユーザメールアドレス
{{user.user_id}} {{user.name}} {{user.email}}

参考:https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja

ドキュメントを新規追加する

ドキュメントを新規追加するには、add()またはset()を使います。ドキュメントIDをランダムに完全に新規で作成する場合はadd()を利用します。ドキュメントIDを任意の値に指定したい場合はset()を指定します。set()は、既存のドキュメントIDを指定するとドキュメント全体を更新する処理となります。

const db = firebase.firestore();
let userRef = db.collection('users')
// 完全新規で追加する場合
userRef.add({
  name: '山田花子1',
  email: 'sample1@sample.com'
})
// ドキュメントIDを指定して新規追加する場合
userRef.doc('new-user-id').set({
  name: '山田花子2',
  email: 'sample2@sample.com'
})
// 既存のIDを指定してドキュメントの値を更新する場合
userRef.doc('YLu7bG7PcRNYhAg3F6MY').set({
  name: '山田花子3',
  email: 'sample3@sample.com'
})

参考:https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja

ドキュメントを更新する

ドキュメント全体を上書きせずにドキュメントの一部のフィールドを更新するには、update()を使います。

const db = firebase.firestore();
let userRef = db.collection('users')
userRef.doc('YLu7bG7PcRNYhAg3F6MY').update({
  name: '山田花子1'
})

参考:https://firebase.google.com/docs/firestore/manage-data/add-data?hl=ja

ドキュメントを削除する

ドキュメントを削除するには、特定のドキュメントIDをしていしてdelete()を呼び出します。

const db = firebase.firestore();
let userRef = db.collection('users')
userRef.doc('2YkjKlEoEQtH0tBJnByr').delete()

参考:https://firebase.google.com/docs/firestore/manage-data/delete-data?hl=ja

まとめ

ある程度がっつり書いていけばすぐに慣れますが、ちょこちょこ書いていたので書くたびにドキュメントを参照するというのを何回もやっていたのでまとめてみました。自分なりにまとめたものなので誤っている解釈などがあれば指摘して頂ければ幸いです。

Posted on

Rust+WebAssembly で Hello, World!

以前 Rust をはじめてみよう!という記事を書いた。今回は Rust + WebAssembly を使って Hello, World!の出力をやってみた。

WebAssembly について

まず WebAssembly とは何か。本家サイトの Overview をみてみる。ここにある通り、WebAssembly(WASM)は C/C++/Rust などの高級言語を使って開発をしバイナリ形式で動かすことができる。その為 Web 上で高速に動かすことができる。とりわけゲームなどの実行速度が求められるような分野で有効になる。Chrome、Firefox、Safari、Edgeで利用が可能。

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
https://webassembly.org/

よくデモに出てくる Unity を使った動画
https://webassembly.org/demo/Tanks/

Youtube動画

再生回数が一番多い動画をあげておく。2018年2月の動画ですごく分かりやすく説明されている。

Rust+WebAssembly のドキュメント

ここからは以下の記事を実際にやってみる。実際にほぼそのまま実行しているだけなので以下についてはリンクをチェックするだけでも良いです。
https://rustwasm.github.io/book/game-of-life/hello-world.html

事前準備

参考URL:https://rustwasm.github.io/book/game-of-life/setup.html

rustup を使って rust をインストールする

curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env

source $HOME/.cargo/envは .zshrc などに記述しておくとよい

wasm-pack インストール

wasm-pack を使うとビルド・テスト・公開などが簡単にできる

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

cargo-generate インストール

cargo-generate を入れるとcargo generateコマンドが使えるようになり、この後の Git リポジトリからのソース取得ができる

cargo install cargo-generate

npm インストール

最新の npm を入れておく

npm install npm@latest -g

サンプルプロジェクトのテンプレート

Hello, World!のサンプルプロジェクトを取得する

cargo generate --git https://github.com/rustwasm/wasm-pack-template
// プロジェクト名を聞かれるのでここはドキュメントの通り`wasm-game-of-life`とする

ドキュメントツリーは以下のようになる。ドキュメントにはないtestsが追加されていた。ここでsrc/lib.rsgreet関数の文字列が、Hello, wasm-game-of-life!となっているので一応Hello, World!と変えておく。

wasm-game-of-life
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
├── src
│   ├── lib.rs
│   └── utils.rs
└── tests
    └── web.rs

wasm-packコマンドでビルドしてみる。rustcのバージョンが1.30以上でないとエラーが発生するけどrustup updateコマンドでアップデートすれば問題なく進められる。

wasm-pack build
| [1/9]   Checking `rustc` version...
Your version of Rust, '1.29', is not supported. Please install Rust version 1.30.0 or higher.

rustupを使ってrustcをアップデートする

rustup update

ビルドが完了するとpkgディレクトリができる

wasm-pack build
pkg
├── README.md
├── package.json
├── wasm_game_of_life.d.ts
├── wasm_game_of_life.js
└── wasm_game_of_life_bg.wasm

Webページを作成する為に以下のコマンドを実行する。するとあらたにwwwディレクトリができる。

npm init wasm-app www
npx: 1個のパッケージを3.137秒でインストールしました。
 Rust +  Wasm = ❤

wwwのドキュメントツリー

www
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── bootstrap.js
├── index.html
├── index.js
├── package-lock.json
├── package.json
└── webpack.config.js

wwwディレクトリへ移動し依存関係をインストールする

npm install

pkgディレクトリへ移動し以下のコマンドを実行する

npm link
/usr/local/lib/node_modules/wasm-game-of-life -> /Users/satomasaki/Dev/taisa/wasm-game-of-life/pkg

更にwwwディレクトリへ移動して以下のコマンドを実行する

npm link wasm-game-of-life
/Users/satomasaki/Dev/taisa/wasm-game-of-life/www/node_modules/wasm-game-of-life -> /usr/local/lib/node_modules/wasm-game-of-life -> /Users/satomasaki/Dev/taisa/wasm-game-of-life/pkg

index.jsimport箇所のhello-wasm-packwasm-game-of-lifeに更新する

import * as wasm from "wasm-game-of-life";
wasm.greet();

実行しページを開いてみるとHello, World!が表示される。

npm run start

ソースを少し変更してみる

wasm-game-of-life/src/lib.rsgreet関数を以下のように少し変更しwasm-game-of-life/www/index.jsgreet関数の引数に文字列を入れてみると渡した文字列が出力される

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
wasm.greet("wasm!");

Webサーバを立ち上げたままでもwasm-pack buildと実行するだけでソースが更新され動作確認をすることができる。

まとめ

本当に少し触っただけながら、便利なツールがちゃんとあって、ある程度形ができて慣れてくればそれほどストレスなく開発が進められそう。

Posted on

node-nightlyを使ってwebpackをデバッグする

webpackに限らずだけどnode-nightlyを使うと簡単にデバッグすることができる

Debugging

When contributing to the core repo, writing a loader/plugin, or even just working on complex project, debugging tools can be central to your workflow. Whether the problem is slow performance on a large project or an unhelpful traceback, the following utilities can make figuring it out less painful.

node-nightlyをインストールする

インストール後一度初期化を行う

npm i -g node-nightly
// 初期化
node-nightly

webpackの実行環境をつくる

デバッグする為にwebpackの実行環境をつくる
npm initしてwebpackをディレクトリ配下にインストールする

npm init
npm i -D webpack
//バージョンは4.12.1
npx webpack --version
4.12.1

webpack-cliをインストールする。ここではグローバルインストールとしている。

npm i -g webpack-cli
//バージョンは3.0.8
webpack-cli --version
3.0.8

webpack.[prod].jsをコマンドラインから作成する

webpack-cli init

以下のように聞かれるので好みの設定をする(今回はデフォルトを利用)

ℹ INFO For more information and a detailed description of each question, have a look at https://github.com/webpack/webpack-cli/blob/master/INIT.md
ℹ INFO Alternatively, run `webpack(-cli) --help` for usage info.
? Will your application have multiple bundles? No
? Which module will be the first to enter the application? [default: ./src/index]
? Which folder will your generated bundles be in? [default: dist]:
true
? Will you be using ES2015? Yes
? Will you use one of the below CSS solutions? PostCSS
? If you want to bundle your CSS files, what will you name the bundle? (press enter to skip)
npm WARN nightly@1.0.0 No description
npm WARN nightly@1.0.0 No repository field.

webpack-cliで設定したディレクトリとファイルを作成する

mkdir dist
mkdir src

ここではindex.jsからhello.jsを呼び出す形にした
index.js

vi src/index.js
import hello from './hello.js'

hello.js

vi src/hello.js
export default function () {
console.log('Hello webpack')
}

ちゃんとビルドできるかチェック

npx webpack --mode development

正常にビルドできた

Hash: b4135b9c0e10130dfeb5
Version: webpack 4.12.1
Time: 309ms
Built at: 2018-06-26 19:55:01
Asset Size Chunks Chunk Names
main.js 980 bytes 0 [emitted] main
[0] ./src/index.js + 1 modules 102 bytes {0} [built]
| ./src/index.js 38 bytes [built]
| ./src/hello.js 64 bytes [built]

node-nightlyを使ってデバッグする

node-nightly--inspect-brkオプションを使うと1行目で止まってくれる
webpackのデバッグを実行

node-nightly --inspect-brk ./node_modules/webpack/bin/webpack.js --mode development

コマンドを実行したらchromeで以下のURLにアクセスする

chrome://inspect/

すると下記のようにinspectリンクが出てくるのでクリックする

クリックするとデバッガが立ち上がり、1行目で止まるのでステップ実行していくことができる。オプションを変えれば1行目で止まらないことも可能。

node-nightlyを使えばwebpackに限らずnpmモジュールのデバッグが簡単にできる

Posted on

「はじめてのフロントエンド開発」という共著本を出版しました

『React,Angular,Vue.js,React Nativeを使って学ぶ はじめてのフロントエンド開発』という共著本を2018年5月9日に出版しました。

React、Angular、Vue.js、React Nativeを使って学ぶ はじめてのフロントエンド開発 Amazonより
自分はこの中の第3章の環境構築を担当しています。お陰様で現在まで売れ行きは好調ですが、一方で誤植もいくつか見つかっていますので誤植情報についてもこの投稿でお知らせします。また、表紙をパッと見ただけでは分からない本書の内容についてや去年最新JavaScriptフロントエンドをキャッチアップした経緯などを書いていきます。

どんな本か

「どんな本か」については共著者である新井正貴の投稿にまとめられているので確認してみてください。

「はじめてのフロントエンド開発」という本を書きました – massa142’s blog

共著者として参加していた書籍『React,Angular,Vue.js,React Nativeを使って学ぶ はじめてのフロントエンド開発』が、2018/5/9に 技術評論社 さまより発売となりました。 React、Angular、Vue.js、React Nativeそれぞれが、同じサーバの APIを参照し、同様の機能を持ったアプリケーションとして作成します。

  • どんな本か
  • こんな方におすすめ
  • 書いたきっかけ
  • パンダの由来
  • サポートリポジトリ

本書の内容について

書籍タイトルは『React,Angular,Vue.js,React Nativeを使って学ぶ はじめてのフロントエンド開発』ですが、タイトルに出てくるワードの他にも『フロントエンドの最新動向』『環境構築』『ES2015』『TypeScript』『Firebase』についても書かれています。
表紙をパット見ただけでは内容が分からないところもあると思うので、本書がどのような内容かを簡単にまとめてみます。

アウトライン

  • Part1:JavaScriptフロントエンドフレームワーク最新動向
    • 第1章:JavaScriptフロントフレームワークの興隆
    • 第2章:SPA、PWA – フロントエンド実装技術の最新トピック
  • Part2:フロントエンドJavaScript開発のための基礎知識と環境構築
    • 第3章:フロントエンドJavaScript開発のための環境構築
    • 第4章:フロントエンドJavaScript開発のための基礎知識
    • 第5章:フロントエンドJavaScript開発のためのサーバ構築
  • Part3:Slackライクなサンプルで比べて学ぶ React/Angular/Vue.js
    • 第6章:React入門 & 徹底活用
    • 第7章:Angular入門 & 徹底活用
    • 第8章:Vue.js入門 & 徹底活用
  • Part4:Slackライクなサンプルで学ぶ React Native
    • 第9章:React Native 入門 & 徹底活用

大きな流れ

まずPart1で「JavaScriptフロントエンドの最新動向」を解説し、Part2で「環境構築」「ES2015」「TypeScript」「FirebaseによるAPIサーバの構築」などフロントエンド開発の事前準備をします。
Part3、4では「React」「Angular」「Vue.js」「React Native」それぞれの章の最初の入門で基礎知識を解説した後、同一のAPIを利用しSlackライクなサンプルアプリを作ります。それぞれが同一APIを使って同じアプリケーションをつくることでそれぞれの特徴を掴めるような構成になっています。

各Partについて

Part 1:JavaScriptフロントエンドフレームワーク最新動向

第1章では「React」「Angular」「Vue.js」「React Native」に関する解説や比較をしています。また本書で扱うフレームワーク/ライブラリ以外(Polymer、Ember.js、Riot.js、Vanilla.js、Native Script、Weex、A-Frame、React VR)についてもそれぞれジャンル分けしながら取り上げて解説しています。
第2章では「SPA」「PWA」に関連する技術的な内容(クライアントサイドルーティング、CSS in JS、コンポーネント指向、SSRとプリレンダリング、バーチャルDOM、MVCとMVPとMVVM、Flux、PWA、Electron など)を取り上げて解説しています。
Part1を読むことで最新のJavaScriptフレームワークの動向を掴みつつ、フロントエンドに関する技術的な面を把握することができると思います。

Part 2:フロントエンドJavaScript開発のための基礎知識と環境構築

第3章では「node.jsのインストール」から「npm」「package.json」「webpack」「IDE(VS Code)」まで、開発に必要な環境構築について取り上げて解説しています。既に環境がある人にとっては飛ばしても良い内容ですが、一方で環境構築周りで躓く人も一定数いると思うので、その場合はこの章を進めていけば開発環境を構築することができます。
第4章では「ES2015」「TypeScript」について解説しています。第5章では「Firebase」を使って以降の章で利用するAPIサーバの立ち上げについて解説しています。

Part 3:Slackライクなサンプルで比べて学ぶ React/Angular/Vue.js、Part 4:Slackライクなサンプルで学ぶ React Native

第6、7、8、9章では、それぞれの章において各フレームワーク/ライブラリへの入門をした後サンプルアプリを作るという流れになります。
本書は(特にPart 3とPart 4)は、ただ読み進めるよりも実際にコードを書いて動かしてみてほしいというのが思いとしてあります。
中には「はじめての」というタイトルの割には敷居が高いと感じる人もいるかもしれませんが、とにかく書いて動かしてみて比較してみてほしいです。

誤植情報

誤植情報については以下のページにまとめていて、随時更新していますので何かあったらTweetしたりissuesにあげたりしてもらえると助かります。

okachijs/jsframeworkbook

Contribute to jsframeworkbook development by creating an account on GitHub.

おわりに

自分は去年のはじめにJavaScriptの最新動向のキャッチアップをしてプロダクトに適用しようと決めて活動していました。それでまずはじめに「ES5」「ES2015」「TypeScript」「webpack」を触りつつ、どのフレームワーク/ライブラリを使うかを選定することからはじめました。
選定ではまず対象を「React」「Angular」「Vue.js」に絞りました。他フレームワークについては本書にも少しでてきますがOkachi.jsという勉強会で比較発表会をした結果や現状のトレンドを考慮し対象から外しました。
対象を絞った上で、チームメンバーで分担して「React」「Angular」「Vue.js」の担当者を決め、各自が調べた結果の発表会をした上で最終的に使うフレームワークを検討し決定しました。
最終的には、メンバーのスキルセット、プロダクトとの相性、スケジュール、導入のラーニングコスト、知り合いに知見のある人がいるか、など総合的に判断しVue.jsを採用しました。結果的にはVue.jsを採用してよかったと思いますが、これらの条件が違えば他のフレームワーク/ライブラリを採用していたかもしれません。
このように振り返ってみると、去年行ったキャッチアップ活動の多くは本書に詰め込まれてるように思います。なのでこれからやろうという方は是非本書を参考にしてみてください。また参考までに、去年「slideship Tech Dive」という勉強会でLTした時の投稿とスライドを貼っておきますので合わせて見てみてください。

「slideship Tech Dive vol.1 フロントエンド特集」でLTしてきた

connpassリンク slideship Tech Dive v1.0 #React / ReactVR / #VueJs Webフロントエンド特集 「slideship Tech Dive v1.0 #React / ReactVR / #VueJs Webフロントエンド特集」でLTしてきた。タイムテーブルは、メインセッションがVue、ReactVR、React SPAになっていてその後LT4本で親睦会という構成。自分は「フロントエンド速習コース」というタイトルでLTをさせてもらった。

Posted on

おれ的フロントエンド速習コース

3ヶ月でフロントエンド向上させるにあたって取り組んだことを書く。

フロントエンドって?

どこからどこまで?何を指してる?と引っかかる人がいるかもしれないけどそこら辺はなんとなくお察しください。

3ヶ月前まで

  • JSとjQueryのみ
  • 毎回ノリで書いていた(もちろんカオスにならないように最大限工夫はしてるけど)
  • 流れが早いからモダン情報のキャッチアップはタイミングを見計らっている
  • けど2017年中にはなんとかしたい
  • やるなら一気にやりたい

始める前まではこんな感じだったけど、そろそろいってもいいかな?ということでやり始めた。

速習後

もともとは既存プロダクトをどうにかするつもりで始めていたけど、タイミングよく新規プロダクトを立ち上げることになったので採用した。何もしてなかったらかなり勇気が必要だったと思う。

  • ES6
  • React
  • VueJS
  • Webpack
  • Babel
  • PostCSS
  • Go
  • PHP(継続)

3ヶ月でやった事

  • JavaScript(ES5)を速習する
  • ES6を速習する
  • React(でSPAを)速習する
  • マークアップを速習する
  • Podcastで速習する
  • 勉強会で速習する
  • チームメンバーと速習する

JavaScript(ES5)を速習する

オライリー本で速習

JavaScriptパターン ―優れたアプリケーションのための作法 Amazonより
JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス」や他の本もいいけど個人的にはこの本がお薦め(発売時期がよい)。
※デザインパターンの章は他に「JavaScriptデザインパターン」という書籍があるしここでは読み飛ばしてもよいと思う。

ES6を速習する

WEB+DB PRESS Vol.87で速習

WEB+DB PRESS Vol.87 Amazonより
非常に分かりやすく端的に説明されていてとてもよい。
(こんなツイートも↓)

React(でSPA)を速習する


WEB+DB PRESS Vol.97 Amazonより
React+Flux、クライアントサイドルーティング、サーバサイドレンダリング、webpackについて丁寧に説明されている。他にもマネジメントやPythonに関する内容があってとても読みごたえがある。

すぐに「理解できた」という訳にはいかない

Reactはそれなりに初期学習コストがあるので以下のことを繰り返しながらじっくり理解を進めていった。

マークアップを速習する

マークアップも一人でできるようになりたいというメンバーが多かったのもあり、社内のUI/UXデザイナーにハンズオンをしてもらった。このハンズオンの目的としては何から手をつけていいか分からないという状況から脱却して自分でもなんとか勉強できる状態にすることでこれだけでなんとかしようというものではない。

関連リンク
初心者向けざっくりHTML/CSSコーディングハンズオン資料
社内エンジニア向けにマークアップハンズオンを開催しました

その他の方法

Podcastで速習する

勉強会で速習する

コミュニケーションしながら疑問点を解決してもらえたのでとても助かった。他にもReact、VueJS、Angular以外も含めたフレームワーク発表会をやったりした。またそれをうけてあたらめてReact、VueJS、Angularはいいなと実感した。

チームメンバーと速習する

  • 今QはJSをやろうと全員で決めた(※この間業務でJS触る機会は0だった)
  • 情報共有しやすい
  • ここでもチームメンバーで分担してReact、VueJS、Angularを調べて発表会をした
  • チームメンバーのJSに対する意識が全体的に変わって導入障壁が低くなった

まとめ

  • 業務でJS触る機会が0だったとしても3ヶ月あれば結構イケる
  • 他にやりたいことができてもなるべく我慢してJSやるの大事
  • あとは実践あるのみ(※無謀な挑戦にならなくて済んだ)

結果

JSが好きになった🤗
※ この内容は「slideship Tech Dive vol.1 フロントエンド特集」でLTしてきた」で発表した内容をベースにしています。

Posted on

「slideship Tech Dive vol.1 フロントエンド特集」でLTしてきた

connpassリンク
slideship Tech Dive v1.0 #React / ReactVR / #VueJs Webフロントエンド特集
「slideship Tech Dive v1.0 #React / ReactVR / #VueJs Webフロントエンド特集」でLTしてきた。タイムテーブルは、メインセッションがVue、ReactVR、React SPAになっていてその後LT4本で親睦会という構成。自分は「フロントエンド速習コース」というタイトルでLTをさせてもらった。

slideshipって何?

markdownで手軽にスライドがつくれちゃうサービスでコードシンタックスハイライトを自動でやってくれたりPDFに変換してくれたりする。今回LTするにあたって前日までラフなマークダウン文章しかなかったけど早くスライド作らなきゃっていう焦りがなかったので気分的に非常に楽だった。
slideship.com
slideship

トークスライド (すべてslideshipでできてる)

Vue.js 効果的だった事例から見る利点と特徴

橋本 安司さん
@yellow844
Vue.js 効果的だったじれいから見る利点と特徴
これが大事↓
「単一ファイルコンポーネントで『テンプレート、ロジック、スタイル』の関心を分離させる記述になっており、ファイル分割してより疎な状態に出来る。更にテンプレートやスタイルのテンプレート言語・CSSプリプロセッサを選択できる。」

ReactVR でつくるサーバ連動型インタラクティブ VR

原 一浩さん
@kara_d
ReactVR でつくるサーバ連動型インタラクティブ VR
「s7は爆発の危険がある」に笑った。

React SPA における OGP への挑戦

池内 孝啓
@iktakahiro
React SPA における OGP への挑戦
サーバサイドレンダリングはしないぞ!っていうこだわりが感じられた

LT

PATENTS問題とfast-asyncについて

石井 直矢さん
@kaidempa
PATENTS問題とfast-asyncについて
OSSのライセンスのお話

フロントエンド速習コース

@taisa831
フロントエンド速習コース
3ヶ月でフロントエンドを一気にキャッチアップした時にやったことを紹介した。

書籍プレゼント企画

書籍プレゼント企画


こちらの書籍の監訳者の吉田 真吾さん
@yoshidashingo
じゃんけん大会で書籍はゲットできなかったけどこの書籍はオライリーの電子版で購入した。タイトル見て発売したら速攻買おうと思ってたけどReal World Httpに先に手出してたので買えてなかった。

RxJSコトハジメ

@massa142
RxJSコトハジメ
RxJS良さそう。マーブルテスト楽しそう。

勉強会風景




まとめ

ちょうどフロントエンドのキャッチアップをしていたのでとても良い機会になった。トーク内容もいろいろあってとても楽しめ。次回も楽しみ。