selmertsxの素振り日記

ひたすら日々の素振り内容を書き続けるだけの日記

TypeScript & Jest & VSCode環境でDebuggerを動かす

モチベーション

  • TypeScript & Jest & VSCode環境でDebuggerを動かしたい。
  • ちゃんと設定ファイルを見れていなかったので、これを期に一通り確認したい

動作内容

test以外のコードでも、debuggerは効きます。

f:id:selmertsx:20180118213748p:plain f:id:selmertsx:20180118213806p:plain

設定ファイル一覧

vscodeの設定

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Jest",
      "preLaunchTask": "build", 
      "program": "${workspaceRoot}/node_modules/jest/bin/jest.js",
      "args": [
        "${file}",
        // 現在のプロセスで逐次テストを実行していく設定.
        // この設定をしないと複数のchildプロセスでテストを実行するらしい
        // cliのpackage の性質上、子プロセスがテスト画像を変更してしまうリスクがあるし、
        // debuggingのために有用とのことだったので、この設定を有効にした
        // https://facebook.github.io/jest/docs/en/cli.html#runinband
        "--runInBand", 
        // debugの際はcacheを無効にした。
        // cacheを無効にすると、2倍くらい遅くなるらしい。
        "--no-cache"
      ],
      "cwd": "${workspaceRoot}",
      "console": "integratedTerminal"
    }
  ]
}

tasks.json

https://vscode-doc-jp.github.io/docs/userguide/tasks.html

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "type": "shell",
      "command": "yarn build"
    }
  ]
}

とりあえず、テスト前にbuildすれば良いだけの設定。 typeのところには、npm, shell, gulpが使えるようだ。下記資料参照。 https://github.com/Microsoft/vscode/blob/master/.vscode/tasks.json typeのところにyarnが無かったので、shellとおいて commandの部分に yarn buildと書いた。

jest.config.json

https://facebook.github.io/jest/docs/en/configuration.html

module.exports = {
  rootDir: "./",
  transform: {
    "^.+\\.tsx?$": "ts-jest"
  },
  testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
  modulePathIgnorePatterns: [
    "<rootDir>/build/"
  ],
  moduleFileExtensions: [
    "ts",
    "js",
    "json"
  ]
}

transform はソースコードを変換する必要があるものを正規表現で記載するもの。 typescriptなど利用している場合は、ここに記載する必要がある。 typescriptを使う場合、jest本家は下記のようにコンパイルしている。 https://github.com/facebook/jest/blob/master/examples/typescript/package.json#L18

今回は ts-jestを利用しているため、ts-jestのドキュメントが指定する通りにした。 https://github.com/kulshekhar/ts-jest#usage

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "alwaysStrict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": false,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "noUnusedParameters": false,
    "noUnusedLocals": false,
    "outDir": "../build/",
    "removeComments": true,
    "strictNullChecks": false,
    "target": "es5",
    "traceResolution": false
  },
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "**/*.spec.ts"
  ]
}

debugのための設定としては、exclude の部分だけである。 testコードはcompileする必要がないので、excludeに含めた。

Serverless Architecture を翻訳しようとしてFAQを読んだ

Frequently Asked Questions

モチベーション

serverlessに関して、体系的な知識を身につけたかったので、下記ページの読んで、自分のブログに理解した内容を掲載したかった。

martinfowler.com

FAQの内容

Frequently Asked Questions

Can I translate one of your web articles?

In general I'm happy for people to do translations. However in recent months I've learned that many translations that are done are of poor quality. So if you do a translation I will try to check that it's of decent quality by finding a colleague to take a look it. As long as they tell me it's ok, I'm happy for it to be posted. I do need you to put a link to the original article and the date of the translation in the translation. (The date helps people spot if I've changed the article since the translation.) Once you've done that please let me know and I will link to it in my paper, (but that may take a while if I'm busy traveling). The only exception to this is material that I'm working into a book. I have to be careful with these since they will be published commercially.

I'm afraid I don't host translations on martinfowler.com as I'm not comfortable serving up text that I can't comprehend.

I haven't checked the older translations to see if they are of decent quality, if you see one that is of poor quality, please email me and I'll at least remove the link.

翻訳したものを公開するときは、その文章が正しいかどうかチェックしたいから、必ず fowler氏のチェックを通してねとのこと。

結論

martinfowler.com の文章を翻訳するときは、必ずfowlerさんにemailで送ってチェックして貰うこと。チェックしてもらってない文章は、ブログに掲載しないこと。

TypeScriptで書いたcliのnpm packageをリリースする方法

背景

人生初のnpm packageをリリースしました。

画像を所定のフォーマットで圧縮してくれるCLIです。現在はシンプルに画像を圧縮するだけですが、おいおい未圧縮の画像を検知する機能であったり、gitのpre-commitにhookして自動で圧縮する機能などを追加していこうと考えています。なお、このpackageはTypeScriptで書かれています。

本日のブログでは、npm packageをリリースする方法、TypeScript(altJS 全般で使えそう)でnpm packageを作る際の方法、npm packageでcliを作る際の注意点について記載していきます。

なお、今回の npm package が僕の初めてのリリースですので、間違った部分や至らない部分があるかもしれません。そこを意識して見て頂ければ幸いです。誤りなどありましたら、コメントを頂けると喜びます!

npm packageをリリースする

シンプルな npm packageであれば、下記の手順を踏めば簡単に npm packageをpublishすることが可能です。

  • npmjs にユーザー登録する
  • npm config にnpmjsに登録したユーザー情報を設定する
  • npm の2要素認証設定をする
  • npm packageをpublishする

以降、図を使いながらより詳細に説明していきます。

npmjsにユーザー登録する

https://www.npmjs.com/signup

上記URLにアクセスして npmjs.com に自分のユーザーを作ります。説明どおりにやれば大丈夫です。

f:id:selmertsx:20180111192236p:plain

npm configにユーザー情報を設定する

terminal から npm login と叩いて、npmjs に登録したユーザー情報を入力します。 問題なく設定できてたら、npm whoami と叩くと自分のユーザー名が返されます。

$ npm login
Username: ${yourName}
Password:
Email: (this IS public) ${yourEmail}
Logged in as shuhei.morioka on https://registry.npmjs.org/.
$ npm whoami
${yourName}

参考URL: Redirecting…

2要素認証をする

自分のpackageに悪さされないように、2要素認証も入れておきましょう。

Requires npm version 5.5.1 or greater

2要素認証は、 バージョンが5.5.1以上のnpmから対応されているため、必要であればnpmのバージョンを上げましょう。

$ npm -v
3.10.10
$ npm update -g npm
/nodepath/node/v6.10.3/lib
└── npm@5.6.0
$ npm -v
5.6.0
$ npm profile enable-2fa

するとバーコードがterminal上で表示されるので、表示されたバーコードを使って2要素認証の設定ができるようになります。

参考URL: Redirecting…

npm packageをpublishする

$ npm publish --access public (--otp xxxx)

上記コマンドで作成したpackageをリリースすることができます。ただし2要素認証の設定をしていた場合、--otpのあとにotpcodeを入力することを忘れないで下さい。

TypeScriptでnpm packageを作る

nodejsのシンプルなコードであれば、上記の手順でnpm packageをpublishすることができます。ただしTypeScriptなどのaltJSを使って開発をしている場合、build後のコードはGitでは管理しないけれども、packageには含めたくなります。

gitでは管理していないコードをpackagesに含めるための方法は2つあって、.npmignoreを使う方法と、packages.jsonのfiles fieldを利用する方法です。ざっくり書くと .npmignoreはブラックリストであって、packages.jsonのfiles fieldはホワイトリストになります。確認が容易なものではないので、何を入れるのか明示的に指定したほうが事故がないと判断し、今回は packages.json の files fieldを採用しました。

packages.json の files field

ioptにおける files field の設定内容は下記のように、たった2行になります。

# packages.json
  "files": [
    "build",
    "bin"
  ],

iiopt/package.json at master · speee/iiopt · GitHub

files fieldはデフォルトで、package.json、README、CHANGES、LICENSE、NOTICE 等のファイルを含めます。なので、ここに記載するコードは少なくてすみます。

https://docs.npmjs.com/files/package.json#files

altJSを使った npm packageをリリースする上で、必要だった作業は僕がやった限りこれだけでした。

npm packageでCLIを作る上での注意点

CLIツールのコマンドは、参考資料に示すように bin fieldに実行コードへのパスを指定し、yarn linkすることによって使えるようになります。

# packages.json
  "bin": {
    "iiopt": "./bin/cli"
  },
$ yarn link
yarn link v1.3.2
success Registered "@speee/iiopt".
info You can now run `yarn link "@speee/iiopt"` in the projects where you want to use this module and it will be used instead.
✨  Done in 0.14s.

yarn linkを実行した際に、/usr/local/bin/iiopt に対して、bin fieldsで指定したコードのパスへのリンクを貼ることで、コマンドが使えるようになります。

$ ls -l /usr/local/bin/iiopt
/usr/local/bin/iiopt -> /path_to_iiopt/iiopt/bin/cli

その他

packages.jsonの整理や抜け漏れチェックには fixpackが便利だった

nodejsで開発をしていると、packages.jsonの要素の順番がごちゃごちゃしてきたりします。 また初めてのnpm package開発だと、packages.jsonに何を記載すれば良いのか分からないと思います。 fixpackは、その問題に対する解決方法になります。

$ fixpack
missing main
package.json already clean!

上が、fixpackの実行結果になります。packages.jsonの中に記載されていない情報があれば、通知してくれます。また、中の要素もfixpack指定の順番に並べてくれます。

最後

以上、npm packageをリリースする方法を記載しました。

参考URL

公式ドキュメント以外で参照したページです。お世話になりました。

2018年の抱負 (4月まで)

2017年は、ふわっと目標を定めたので、ふわっと終わってしまいました。2018年は、もう少し具体的に目標を定めて、言語化し、達成してきたいと思っています。

目標のざっくり全体像

2018年は、一言で言うとエンジニアとしての基礎力を上げるということをテーマとしてやっていこうと思います。より具体的に言うと、下記の内容です。

  • 自らがサービスで利用しているコアな技術に関して、選定理由を明確に語ることができる
    • どの条件が変われば、他の技術の方に軍配が上がるのかも説明できる
  • サーバーサイドエンジニアの領域に関して、現在のトレンドを幅広く把握している
  • 英語での読み書きが開発に支障無い範囲内で行える

具体例で言うと、ゆううきさんみたいに、深い技術的な理解に基づいた文章が書けるエンジニアにあこがれています。

もうちょっと具体的な目標

  • 継続してキャッチアップするもの
  • ちゃんとやってみるもの
    • serverless
    • nodejs
  • 一通り触ってみるもの
    • docker & k8s
    • react
  • その他

4月までの詳細な目標

とりあえず、4月までの目標をざざっと書いてみます。 細ければ細かいほど良いと思うので、思いつく限り書きまくります。 OKRの考え方にもとづいて、全体の70%くらい実現できたらいいなと。 業務のことはとりあえず、置いといてます。

  • serverlessについて語れるようになる
    • https://martinfowler.com/articles/serverless.html これ読んでブログにまとめる
    • micro service について把握する
      • serverlessはmicro serviceからの流れを組むものだと思っているので、その流れなどを語れるようになる
    • https://github.com/selmertsx/serverless-prpolice これを作り切る
      • PR policeを AWS SAM Localを使ってリプレイスしたもの
    • serverless-prpoliceに関して、エラー監視をできるようにする
    • serverless-prpoliceに関して、トラフィック監視をできるようにする
    • serverless-prpoliceに関して、適切なデプロイ戦略を考えることができる
    • これらの知識をまとめて技術書展で本を出す
  • 英語頑張る
    • 1日1時間は勉強する
    • 1日1時間半勉強する
    • TOEIC 受ける
    • TOEIC 700点
    • TOEIC 800点
  • その他
    • ふつうのLINUXプログラミングを読了する
    • ふつうのLINUXプログラミングをブログにまとめる
    • 週2~3本はブログ書く
    • 週1本は、ちゃんと頭を使い切ったブログを書く

どうして serverlessを選んだのか

個人的には serverlessは将来、webサービス開発における選択肢として、十分に挙がってくるものになると考えています。

今のserverlessでは、コードをコンテナにデプロイし、使い終わったら破棄するという仕組みのため、大きなコードを用意してしまったらデプロイに時間が掛かってしまい早いレスポンスが返せない。サービスが拡大したとき、functionの関連性を管理することが難しい。などなどデメリットも多くあります。

しかしながら、AWSを見ていると大きなメモリやコードを許容できるようにする動きもありますし、awslabにて expressフレームワークで作った webサービスをlambdaで動かす実験的なコードも生まれてきました。 GitHub - awslabs/aws-serverless-express: Run serverless applications and REST APIs using your existing Node.js application framework, on top of AWS Lambda and Amazon API Gateway

今ある serverlessの欠点の多くは、仕組み以上に、エコシステムに起因する部分が大きいのではないかと感じていて、AWSはそこの解決に力を入れているように見えています。そこをやりきった後には、今とは違う形の serverlessの世界が見えてくるのでは無いかと思ってちゃんとキャッチアップしてみることにしました。

今のところまだまだ感覚で話してはいますが、3ヶ月後はこれについて自信を持って話せるようになりたいですな。 それでもって、良い所感を持てたら、この分野でOSS等にコミットしていきたいと思ったり思わなかったり。

後半力尽きましたが、2018年前半の抱負はこんな感じでいこうと思います!

2017年棚卸し

今の会社のエンジニアの人と、2017年の棚卸しをしようじゃないかという話しになりまして、この記事にまとめました。

2017年の目標

2017年は、下記3点の目標を持って仕事していました。

  • Ruby以外の言語でもサービスを作れるようにする
    • 2016年当時は、Ruby以外は正直なところちょいちょい摘む程度だった
  • AWSのインフラを使って、サービスを自分1人で作れるようにする
    • 2016年当時、ほとんど触ったことが無かった
  • OSSに関して、ちょっとばかり参加する
    • 2016年時点では、gemを3つ作ったくらい

Ruby以外の言語に関してはnodejsでサービスを1つ作りましたし、AWSについてもちょいちょい勉強会でお話しさせて頂くことができました。また、OSSについては、自作のOSSを一つ作ったのと、ドキュメント修正をちょいちょいやったりしました。

※ 自作OSS

※ ドキュメント修正 (一部抜粋)

読んだ技術書

他にも10冊くらい読んだ気がするのですが、読んでる最中に飽きてしまって読みきれませんでした。 上にあるのは、ちゃんと読み切ったやつです。上からおすすめ順になってます。

ビジネス書

サービスとして何を作るべきか悩んでいた時期に、このあたりの本を読んだりしていました。 上2つについては、まだ手元に置いてます。

発表

AWS Startup tech meetup

speakerdeck.com

【開催報告】第10回 AWS Startup Tech Meetup | Amazon Web Services ブログ

Rails Developers Meetup

speakerdeck.com

Rails Developers Meetup #3 (東京会場) - connpass

JAWS UG night

speakerdeck.com

ASCII.jp:JAWS-UG NightはパネルやLT、クイズまで欲張らナイト!|JAWS-UG広報ユカリンの部屋

備考

2017年おすすめ本です。よかったらポチってください :pray:

JestにおけるbeforeAllの実行タイミングについて

TL:DR

Jestにおいて、describe内外にbeforeAllを複数用意した場合の評価タイミングを確認した。その結果、beforeAllは上から順番に実行されていることが分かった。

モチベーション

beforeAllを上書き指定できれば、綺麗に書けるテストを書いていた。 そのため、beforeAllの優先順位や実行順序などが気になって検証した。

実行内容

コード

beforeAll(()=>{
  console.log("out of describe");
});

describe('sample describe 1', () => {
  beforeAll(()=>{
    console.log("inside of describe 1");
  });

  describe("sample describe 2", () => {
    beforeAll(() => {
      console.log('inside of describe 2');
    });

    test('sample test', () => {
      expect('hoge').toEqual('hoge');
    });
  })
});

ターミナル

$ yarn test __tests__/test.spec.ts
yarn run v1.3.2
$ yarn build && yarn jest __tests__/test.spec.ts
$ yarn tsc
$ /path_to_dir/node_modules/.bin/tsc
$ /path_to_dir/node_modules/.bin/jest __tests__/test.spec.ts
 PASS  __tests__/test.spec.ts
  sample describe 1
    sample describe 2
      ✓ sample test (5ms)

  console.log __tests__/test.spec.ts:2
    out of describe

  console.log __tests__/test.spec.ts:6
    inside of describe 1

  console.log __tests__/test.spec.ts:10
    inside of describe 2

というように、上から順番に実行されていることが分かった。

parameter storeで環境変数管理したら便利だった

モチベーション

GitHubで管理できないパラメータの管理。めんどうですよね。昔は.envrc.localで管理していたんですけれども、チームで開発するときは、ちょっといじると周りに共有しなければならなくて手間でした。そうしなくて済む方法をawsparameter storeで作ってみました。

Parameter Storeってなんだ

AWS のサービスの一つで、パスワード、データベース文字列、ライセンスコードなどのデータをセキュアに扱うためのものです。

Systems Manager パラメータストア - Amazon EC2 Systems Manager

Parameter Storeへのデータ設定方法

下記のコマンドを叩いて、parameter storeにデータを突っ込んでいきます。

aws ssm put-parameter --name SlackToken --type String --value xxxxx 
aws ssm put-parameter --name IAMRole --type String --value xxxxx 

put-parameter — AWS CLI 1.14.16 Command Reference

コード

#!/bin/sh
SlackToken=(`aws ssm get-parameters --names SlackToken --query "Parameters[*].{Value: Value}"  --output text`)
IAMRole=(`aws ssm get-parameters --names IAMRole --query "Parameters[*].{Value: Value}"  --output text`)

echo "export SlackToken=${SlackToken}" >> .envrc.local
echo "export IAMRole=${IAMRole}" >> .envrc.local

ホントなら一回のリクエストで済ませたいのですが、複数パラメータを扱おうとすると、jsonを扱ったりする必要があって、ちょい手間なのでこんな感じですませちゃいました。

あと、.envrc.local を .gitignoreに追加しておきましょう。

実行

bin/setup.sh

を実行すると、下記のように .envrc.local が生成されます。

export SlackToken=xxxx
export IAMRole=xxxxx

という感じで、簡単にパスワード管理ができるようになりました。