2019年6月29日土曜日

firebase-tools v6.11.0 release note 和訳

※翻訳勉強中のため、間違っている可能性があります。


https://github.com/firebase/firebase-tools/releases/tag/v6.11.0

  • Fixed bug in Firestore emulator where some FieldTransforms were sending back incorrect results.
  • Fixed bug where read-only transactions would cause errors in the Firestore emulator.
  • Fixed bug where collection group query listeners would cause errors in the Firestore emulator.
  • Fixed bug where query parameters were not sent to HTTP functions.
  • Fixed bug where some HTTP methods (like DELETE) were not allowed.
  • Fixed bug where CORS headers were too restrictive.
  • Fixed bug where CSV exporting users with commas in displayName causes columns to no longer align.
  • Fixed bug where environment variables are unset for script in emulators:exec.
  • emulators:exec script now inherits stdout and stderr.
  • Improved reliability and performance of project listing for firebase use command.
  • Fixed bug where firestore:delete skips legacy documents with numeric IDs.
  • Fixed bug in Firestore emulator where it ignored x-forwarded-host header.
  • Improved Scheduled Functions deployment to keep and not recreate schedules that are already correct.

  • いくつかの FieldTransforms が誤った結果を送り返していたFirestoreエミュレータのバグを修正しました。
  • 読み取り専用トランザクションがFirestoreエミュレータでエラーを引き起こすというバグを修正しました。
  • Collection Group Query リスナーがFirestoreエミュレータでエラーを引き起こすというバグを修正しました。
  • クエリパラメータがHTTP関数に送信されなかったバグを修正しました。
  • いくつかのHTTPメソッド(DELETEなど)が許可されていなかったバグを修正しました。
  • CORSヘッダの制限が厳しすぎるというバグを修正。
  • displayName にカンマを使用してCSVをエクスポートすると、列が整列されなくなるというバグが修正されました。
  • 環境変数が emulators:exec のスクリプトに設定されていないバグを修正しました。
  • emulators:exec スクリプトは現在 stdoutstderr を継承しています。
  • firebase use コマンドのプロジェクト一覧の信頼性とパフォーマンスが向上しました。
  • firestore:delete が数値IDを持つレガシードキュメントをスキップするバグを修正しました。
  • Firestoreエミュレータが x-forwarded-host ヘッダを無視していたバグを修正しました。
  • Scheduled Functions のデプロイを改善し、すでに正しいスケジュールを保持し、再作成しないようにしました。

Written with StackEdit.

Nuxt.js v2.7.1 release note 和訳

※翻訳勉強中のため、間違っている可能性があります。


https://github.com/nuxt/nuxt.js/releases/tag/v2.7.1

Fixes

修正

  • builder: use warn only for mismatched dependencies (#5723)
  • webpack: correctly resolve consola for the client bundle (#5729)

  • builder: 依存関係が一致しない場合にのみ警告を使用する (#5723)
  • webpack: クライアントバンドル時にconsolaを正しく解決する (#5729)

Dependency Upgrades

依存関係のアップグレード



Written with StackEdit.

2019年6月20日木曜日

Nuxt.js v2.7.0 release note 和訳

※翻訳勉強中のため、間違っている可能性があります。


https://github.com/nuxt/nuxt.js/releases/tag/v2.7.0

DX Improvements 💅

SSR logs in your browser 🖥️

SSRのログをブラウザへ出力


We all know the console.log debugging method, but when working with universal applications, you have to remember that sometimes, your logs are in your terminal and not in your browser console.

console.logというデバッグ方法がありますが、ユニバーサルアプリケーションを作成している場合、ログはブラウザコンソールではなくターミナルに出力されることがあるのを覚えておかなければなりません。


This can be really annoying when developing a Nuxt.js application, starting with this version and running nuxt dev, the ssr logs are now reported to your browser console:

このバージョンから始めて nuxt devを実行して、Nuxt.jsアプリケーションを開発するとき、これは本当に厄介なことになるかもしれません、SSRのログはブラウザのコンソールに表示されるようになりました。


Detecting store/ creation 👀

store/ ディレクトリの作成を検出


Nuxt.js now detects when you created a store/ directory and will reload himself auto-magically so you don’t have to restart it anymore.

Nuxt.jsは、あなたが store/ディレクトリを作成したことを検出し、自動的に自分自身を再ロードするので、もう再起動する必要はありません。


PS: We also improved the serverMiddleware watch to restart Nuxt.js and clean their cache

PS:Nuxt.jsを再起動してキャッシュを消去するために serverMiddlewareの監視を改良しました。

Fixes ✔️

修正

  • builder: corretly detect mode of hashed plugins (#5695)
  • builder: call watch:restart after watch:fileChanged hook (#5620)
  • utils: node v8 not support dotAll in regex (#5608)
  • vue-app: properly catch component loading error (#5687) (#5688) (#5690)
  • vue-app: consider watchQuery option in routerViewKey (#5516)
  • vue-renderer: await on spa:templateParams hook (#5619)
  • webpack: set log level to warn for HardSourcePlugin (#5653)
  • vue-app: properly catch loading error in component prefetching (#5688) (#5690)
  • vue-app: avoid using aliases in templates (#5656)
  • builder: watch store dir and serverMiddleware paths (#5681)

  • builder: ハッシュプラグインのモードを正しく検出する (#5695)
  • builder: watch:fileChangedフックの後にwatch:restartを呼び出す (#5620)
  • utils: ノードv8は正規表現でdotAllをサポートしていません (#5608)
  • vue-app: コンポーネントの読み込みエラーを正しく検出 (#5687) (#5688) (#5690)
  • vue-app: routerViewKeywatchQueryオプションを検討してください(#5516)
  • vue-renderer: spa:templateParamsフックを待ってください (#5619)
  • webpack: ログレベルを HardSourcePluginに警告するように設定します (#5653)
  • vue-app: コンポーネントのプリフェッチでロードエラーを適切に検出する (#5688) (#5690)
  • vue-app: テンプレートでエイリアスを使用しない (#5656)
  • builder: storeディレクトリと serverMiddlewareパスを監視する (#5681)

Features 🚀

特徴

  • vue-app: rename transition to pageTransition and deprecate it (#5558)
  • vue-renderer/vue-app: report SSR console logs to the browser with consola (#5673)
  • webpack: suppress not found typescript warnings (#5635)
  • webpack: extendable babel.presets and babel envName (#5637)
  • configurable aliases (#5655)

  • vue-app: transitionpageTransitionに改名して非推奨になりました (#5558)
  • vue-renderer/vue-app: SSRコンソールログをconsolaでブラウザに報告する (#5673)
  • webpack: 見つからないタイプスクリプトの警告を抑制 (#5635)
  • webpack: 拡張可能なbabel.presetsとバベルenvName(#5637)
  • 設定可能なエイリアス (#5655)

Refactors 🧹

リファクタリング

  • server: exclude dist files request from browser detection (#5571)
  • vue-renderer: remove chalk in renderer (#5609)
  • vue-renderer: split renderer into ssr, spa and modern (#5559)
  • move modern detection from server to utils (#5584)

  • server: ブラウザ検出からdistファイル要求を除外する(#5571)
  • vue-renderer: レンダラーのchalkの警告を削除 (#5609)
  • vue-renderer: レンダラーをssr、spa、modernに分割 (#5559)
  • 最新ブラウザの検出をサーバーからutilsに移動 (#5584)

Examples 📚

  • auth-routes: fix typo (#5651)
  • babel-preset-app: add core-js@3 example in the readme (#5633)
  • docker: fix Dockerfile casing (#5705)

  • auth-routes: typoを修正 (#5651)
  • babel-preset-app: readmeにcore-js@3の例を追加 (#5633)
  • docker: Dockerfileのスペルを修正 (#5705)

Typescript 👷

Only for typescript users, Nuxt.js v2.7 dropped support for node < 8.6 relate to ts-loader v6

TypeScriptユーザのみ、Nuxt.js v2.7ではts-loader v6に関連してNode v8.6未満のサポートを終了しました

  • add babel config types (#5666)
  • upgrade ts-loader to v6 (#5691)
  • fix context.app type (#5701)
  • fix extendRoutes method type (#5700)
  • prevent ts-node to register twice (#5699)

  • config typesbabelを追加 (#5666)
  • ts-loaderをv6にアップグレード (#5691)
  • context.appタイプを修正 (#5701)
  • extendRoutesメソッドの型を修正 (#5700)
  • ts-nodeが2回登録されるのを防ぎます (#5699)

Written with StackEdit.

2019年6月13日木曜日

JestでVuex.Storeのテストを行う

NuxtでTypeScriptを使うときのVeux.storeの設定方法で作成したプロジェクトに Jest でのユニットテストをつけていきます。

できあがったものは以下のリポジトリになります。
https://github.com/TAC/nuxt-vuex-typescript-jest-example

Jestの追加

Nuxt を新規作成時のオプションでテストフレームワークに Jest を選択すると自動で追加されますが、それらを手動で追加してみます。

yarn add -D jest vue-jest babel-jest ts-jest eslint-plugin-jest @vue/test-utils babel-core@^7.0.0-bridge.0

Babelのバージョンが7になっているのでbabel-core@^7.0.0-bridge.0 が必要になります。
Vuex.StoreTypeScriptなのでts-jestも追加します。

Jestの設定

jest.config.js.babelrc を以下の内容で追加します。

app/jest.config.ts

module.exports = {
  moduleNameMapper: {
    '^vue$': 'vue/dist/vue.common.js',
    '^@/(.*)$': '<rootDir>/$1',
    '^~/(.*)$': '<rootDir>/$1'
  },
  moduleFileExtensions: ['js', 'ts', 'vue'],
  transform: {
    '^.+\\.js$': 'babel-jest',
    '^.+\\.ts$': 'ts-jest',
    '^.+\\.vue$': 'vue-jest'
  },
  collectCoverage: false,
  collectCoverageFrom: [
    '<rootDir>/components/**/*.vue',
    '<rootDir>/pages/**/*.vue',
    '<rootDir>/store/**/*.ts'
  ]
}

.babelrc

{
  "env": {
    "test": {
      "presets": [
        [
          "@babel/preset-env",
          {
            "targets": {
              "node": "current"
            }
          }
        ]
      ]
    }
  }
}

テストの作成

コンポーネントのテスト

まずはコンポーネントのテストから。

import Vuex from 'vuex'
import { cloneDeep } from 'lodash'
import { createLocalVue, mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'
import counter from '@/store/modules/counter.ts'

const localVue = createLocalVue()
localVue.use(Vuex)

describe('components/Counter.vue', () => {
  let wrapper
  const initValue = 10
  beforeEach(() => {
    // create store
    const store = new Vuex.Store({
      'modules': {
        'modules/counter': cloneDeep(counter)
      }
    })

    // initialize store
    store.commit('modules/counter/SET_VALUE', initValue)

    // mount Vue Component
    wrapper = mount(Counter, {
      store: store,
      localVue
    })
  })

  describe('template', () => {
    test('snapshot correctly', () => {
      expect(wrapper.element).toMatchSnapshot()
    })
  })

  describe('script', () => {
    test('get counter value correctly', () => {
      expect(wrapper.vm.counter).toBe(initValue)
    })
    test('increment button correctly', () => {
      wrapper.find('[name="increment"]').trigger('click')
      expect(wrapper.vm.counter).toBe(initValue + 1)
    })
    test('decrement button correctly', () => {
      wrapper.find('[name="decrement"]').trigger('click')
      expect(wrapper.vm.counter).toBe(initValue - 1)
    })
  })
})

@vue/test-utilscreateLocalVueを使ってローカルコピーを作成しておきます。
Vuex.Storeには使用するstoreの定義をmodulesの該当パスにcloneDeepでコピーしてあげます。
そうすることで他のテスト時に値が汚染されなくなります。
あとは好きなテストを記述していきます。
wrapper.find()にはCSSセレクターを指定できるので、テスト対象のエレメントなどが一意になるようにnameclassを設定しておくと探しやすくなります。

Veux.Storeのテスト

次はstoreのテストです。

import Vuex from 'vuex'
import { cloneDeep } from 'lodash'
import { createLocalVue } from '@vue/test-utils'
import counter from '@/store/modules/counter.ts'

const localVue = createLocalVue()
localVue.use(Vuex)

describe('store/modules/counter.ts', () => {
  let store
  const initValue = 10
  beforeEach(() => {
    // create store
    store = new Vuex.Store({
      'modules': {
        'modules/counter': cloneDeep(counter)
      }
    })

    // initialize store
    store.commit('modules/counter/SET_VALUE', initValue)
  })

  describe('getters', () => {
    test('get value correctly', () => {
      expect(store.getters['modules/counter/value']).toBe(initValue)
    })
  })

  describe('actions', () => {
    test('increment correctly', () => {
      const addValue = 1
      store.dispatch('modules/counter/increment', addValue)
      expect(store.getters['modules/counter/value']).toBe(initValue + addValue)
    })
    test('decrement correctly', () => {
      const subValue = 1
      store.dispatch('modules/counter/decrement', subValue)
      expect(store.getters['modules/counter/value']).toBe(initValue - subValue)
    })
  })
})

ほぼコンポーネントと同じですが、作成したstoreを使用してテストしたいactionsなどを実行していく形になります。

package.jsonに以下のスクリプトを追加します。

    "test": "jest",
    "test:coverage": "jest --coverage",

これで準備が整ったので、yarn testを実行すると以下のような結果が得られると思います。

PS C:\work\repos\nuxt\jest\app> yarn test
yarn run v1.15.2
$ jest
$ C:\work\repos\nuxt\jest\app\node_modules\.bin\jest
 PASS  tests/store/modules/counter.test.js
 PASS  tests/components/Counter.test.js

Test Suites: 2 passed, 2 total
Tests:       7 passed, 7 total
Snapshots:   1 passed, 1 total
Time:        3.831s
Ran all test suites.
Done in 5.54s.

テストカバレッジも見たい時はtest:coverageを実行します。

PS C:\work\repos\nuxt\jest\app> yarn test:coverage
yarn run v1.15.2
$ jest --coverage
$ C:\work\repos\nuxt\jest\app\node_modules\.bin\jest --coverage
 PASS  tests/store/modules/counter.test.js
 PASS  tests/components/Counter.test.js
---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |    65.38 |      100 |     87.5 |    65.22 |                   |
 components    |    71.43 |      100 |      100 |    71.43 |                   |
  Counter.vue  |      100 |      100 |      100 |      100 |                   |
  Logo.vue     |        0 |      100 |      100 |        0 |             10,13 |
 pages         |        0 |      100 |      100 |        0 |                   |
  index.vue    |        0 |      100 |      100 |        0 |         8,9,10,18 |
 store         |        0 |      100 |        0 |        0 |                   |
  index.ts     |        0 |      100 |        0 |        0 |               1,3 |
 store/modules |      100 |      100 |      100 |      100 |                   |
  counter.ts   |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

Test Suites: 2 passed, 2 total
Tests:       7 passed, 7 total
Snapshots:   1 passed, 1 total
Time:        10.346s
Ran all test suites.
Done in 11.68s.

Written with StackEdit.

2019年6月4日火曜日

NuxtでTypeScriptを使うときのVeux.storeの設定方法

NuxtTypeScript で構築した時に Vuex.store の構成をどうしたらいいかを考えてみました。

結論としては vuex-class-component を使用してモジュールモードで構成する、という感じになりました。

完成したプロジェクトは以下のリポジトリになります。
https://github.com/TAC/nuxt-vuex-typescript-example

簡単なカウンターを作成しました。

環境

- version
OS Windows10
Node.js v8.15.0
Nuxt.js v2.7.1

どのモジュールがいいのか?

Vuex.store を簡潔にかけるようにするモジュールはいくつかあって、以下の2つが主に使われてるようでした。

vuex-class-component
https://github.com/michaelolof/vuex-class-component

vuex-module-decorators
https://github.com/championswimmer/vuex-module-decorators

Nuxt では store ディレクトリ以下にファイルを配置すれば自動で Vuex のモジュールモードで構築してくれます。

ただし、 store/index.ts が関数を返すとクラシックモードになり、その恩恵を受けることができません。
また、各モジュールのファイルも関数ではなくオブジェクトを返す必要があり、それができるのが vuex-class-component でした。
また、Nuxt.jsv3.0.0 ではクラシックモードが非対応になるようなので、それを考慮に入れての選択になります。

ディレクトリ構成

以下のような構成を考えてみました。

src/store/index.ts
  +- modules/
      +- counter.ts

modules に機能毎に分けたモジュールを作成していく感じです。
models とか作ってDBのテーブル毎などに分けたモジュールを作成してもいいかもしれない。

counter.ts

デコレータを使って以下のように記述します。

import {
  VuexModule,
  Module,
  action,
  getter,
  mutation
} from 'vuex-class-component'

interface Counter {
  value: number
}

@Module({ namespacedPath: 'modules/counter/', target: 'nuxt' })
export class CounterStore extends VuexModule implements Counter {
  @getter value = 0

  @mutation
  public SET_VALUE(value: number) {
    this.value = value
  }

  @action()
  public increment(value: number) {
    this.SET_VALUE(this.value + value)
  }

  @action()
  public decrement(value: number) {
    this.SET_VALUE(this.value - value)
  }
}

export default CounterStore.ExtractVuexModule(CounterStore)

ポイントは2つあって、1つは @Module のオプションに namespacedPathtarget:'nuxt' を指定するところです。
もう1つは、最後の行で ExtractVuexModule を使ってオブジェクト形式で export してあげるところです。
これで Vuex.store のモジュールモードに対応できました。

index.ts

index.ts もデコレータを使って記述しようとしたのですが、 nuxtServerInit の定義がどうしてもできなかったので、デコレータを使わずに記述します。

export const actions = {
  nuxtServerInit: ({ commit }) => {
    commit('modules/counter/SET_VALUE', 20)
  }
}

ここでは modules/counter の初期化を行ってみました。

呼び出すComponent

components/Counter.vue を作成します。

<template lang="pug">
  div [counter]
    div {{ counter }}
    div
      button(@click="increment") +
      button(@click="decrement") -
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'

@Component
export default class Counter extends Vue {
  get counter() {
    return this.$store.getters['modules/counter/value']
  }

  public increment() {
    this.$store.dispatch('modules/counter/increment', 1)
  }
  public decrement() {
    this.$store.dispatch('modules/counter/decrement', 1)
  }
}
</script>

呼び出す箇所は通常の使い方と同じです。

これでごちゃごちゃしがちな store 周りをスッキリとかけるようになったかと思います。

Written with StackEdit.