selmertsxの素振り日記

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

継承先のclassのプロパティはオブジェクトの生成時には利用できない

概要

表題のとおり。継承先のプロパティは、オブジェクトの生成時には利用できなかった。 このあたりの仕組みが気になる。やり方があれば、ご紹介頂けると幸いです!

確認のコード

class A {
  protected hoge = 3;
  constructor () {
    console.log(this.hoge);
    this.hoge;
  }

  hage() {
    return this.hoge;
  }
}

class B extends A {
  protected hoge = 4;
}
console.log("-------construct-----");
const a = new A();
const b = new B();
console.log("-------call function-----");
console.log(a.hage());
console.log(b.hage());
➜  typescript ts-node override.ts
-------construct-----
3
3
-------call function-----
3
4

ES6において strict modeになる条件

モチベーション

code reviewをして貰ったときに、「ES Modulesを使うと、暗黙的に 'use strict' 付きますよ」というコメントを頂いた。'use strict' になる条件を全然把握していないので、ちょっと資料を読んでみた。

読んだ資料

ECMAScript® 2015 Language Specification

http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code

分かったこと

  • Global codeが、Strict Directive ( 'use strict' のこと )を含むDirective Prologueで始まるなら、strict mode codeである。
  • Module codeはいつでも strict mode codeである。
  • ClassDeclaration、またはClassExpressionの全ての部分は、strict mode codeである。
  • strict directive を含む場合、evalの中身も strict modeになる。
  • 関連する FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, MethodDefinition, ArrowFunctionがstrict mode codeを含んでいるならば、functionのcodeも strict modeなcodeになる。
  • 引数にcode strictされているfunctionがある場合、それを受け取るfunctionもcode strictになる

TypeScriptをVSCodeでデバックする

概要

  • TypeScriptのデバック効率を上げたい
  • フロントエンドのコードでは無いのでchromeデバッグツールが使えない
  • VSCodeのデバックツールを試してみた
  • 5分くらいで設定できた

VSCodeでのデバック画面

f:id:selmertsx:20171130165908p:plain

こんな感じの画面でデバックができます。

設定方法

VSCodeにおけるTypeScriptデバックの流れとしては、下記の通りです

  1. launch.jsonを読み込む
  2. launch.jsonのpreLaunchTaskにて、実行するタスクを指定する
  3. 指定されたタスクを tasks.jsonから探して実行する
  4. デバッガが動く
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debugging TypeScript",
      "program": "${file}", 
      // tasks.json のlabelで指定
      "preLaunchTask": "Compile TypeScript", 
      "cwd": "${workspaceFolder}", 
      "outFiles": [
        "${workspaceFolder}/build/**/*.js"
      ]
    }
  ]
}
// ${file}: 今開いているコード
// ${workspaceFolder} : VS Codeを開いたフォルダ
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Compile TypeScript",
      "type": "shell",
      "command": "yarn build",
      "problemMatcher": []
    }
  ]
}

デバックの実行

fn + F5で、デバックが開始されます。

f:id:selmertsx:20171130165922p:plain

node.js version could not be determined というログが出ている原因は、これから見ていきます :pray:

参考資料

https://code.visualstudio.com/docs/editor/debugging https://code.visualstudio.com/docs/editor/tasks#vscode

TypeScriptで書かれた AWS Lambdaのコードで AWS SAM Localを使う (第一弾)

やりたいこと

  • TypeScript で書かれている AWS Lambda のコードを AWS SAM Local で動かしたい
  • TypeScriptのコードとbuild後のコードは別ディレクトリで保持したい
  • AWS SAM LocalのREADMEではそこの説明が無いので、自分でなんとか動く方法を模索する必要がある

結論

CodeUri プロパティはcloudformation.ymlからの相対パスを指定する必要がある

※ Lambdaと AWS SAM の初心者です。間違ったことを言ってる。もしくはもっと良い方法を見つけられていない可能性があります。なにかありましたら、コメント頂けますと幸いです!

AWS SAM Localとは

https://github.com/awslabs/aws-sam-local#advanced

AWS Lambda関数をローカルで実行しテストができるようになるツール。 S3, DynamoDB, Kinesis 等のリソースからのイベントをエミュレートすることもできる。 API Gatewayをlocalで動かし、Lambdaコードの変更をhot reloadすることもできる。

AWS SAM のinstall

npm install -g aws-sam-local
sam --version # installできているか確認する

上記コマンドだけで installが可能。Dockerも必要なので気をつけること。

設定内容

AWS SAMの説明とcloudformation.yml の書き方についてはここに書いてあるので、ここを見ながら設定を行う。 https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction

yamlの設定内容

# cloudformation.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Simple Lambda functions

Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: build/src
      Handler: index.post
      Runtime: nodejs6.10
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /chat-bot
            Method: post

上記の設定ファイルが SAM Localを使う上で、自分が設定した CloudFormationのymlである。CloudFormationに Transform: AWS::Serverless-2016-10-31 という値を追加することで、SAMの定義をCloudFormationで行うことが可能となる。

In order to include objects defined by AWS SAM within a CloudFormation template, the template must include a Transform section in the document root with a value of AWS::Serverless-2016-10-31.

ここで重要なのは HelloWorldリソースのCodeUri プロパティで、こいつはjsファイルのディレクトリを指す。気をつけなければならないのは、指定するディレクトリパスは絶対パスか、cloudformation.ymlからの相対パスを指定しなければならないということ。よって、このときのディレクトリ構成は下記のようになる。

➜  speee_pf_checker git:(aws_saml) ✗ tree -I node_modules
.
├── build
│   └── src
│       ├── index.js
 |          ...
│       └── index.js.map
├── cloudformation.yml
├── package.json
├── src
│   ├── application.ts
│   ├── index.ts
 |      ...
│   └── pc_environment.ts
├── cloudformation.yml
├── tsconfig.json
├── tslint.json
└── yarn.lock

ちなみにドキュメントでは下記のように記載されている。

For example, if your AWS Lambda function source code is in the /home/user/code/lambdafunction/ folder, specify CodeUri: /home/user/code/lambdafunction for the AWS::Serverless::Function resource. The command returns a template and replaces the local path with the S3 location: CodeUri: s3://mybucket/lambdafunction.zip.

ということで、絶対パスじゃないといけないかと思ったら、絶対パス指定して実行したら下記のエラーとなった。

➜  speee_pf_checker git:(aws_saml) ✗ echo '{"body": "chiba"}' |  sam local invoke HelloWorld --template cloudformation.yml
2017/11/27 19:22:28 Successfully parsed cloudformation.yml
2017/11/27 19:22:28 Connected to Docker 1.34
2017/11/27 19:22:28 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
Digest: sha256:0721cee9614fe0c995c2eb0f52b9803a23d1c2da3007d46cb54b745d970850a0
Status: Image is up to date for lambci/lambda:nodejs6.10
2017/11/27 19:22:31 Reading invoke payload from stdin (you can also pass it from file with --event)
2017/11/27 19:22:31 Invoking index.post (nodejs6.10)
START RequestId: 08f01507-747c-1789-1312-b3368c5a26ad Version: $LATEST
Unable to import module 'index': Error
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
END RequestId: 08f01507-747c-1789-1312-b3368c5a26ad
REPORT RequestId: 08f01507-747c-1789-1312-b3368c5a26ad  Duration: 13.31 ms  Billed Duration: 0 ms   Memory Size: 0 MB   Max Memory Used: 29 MB

{"errorMessage":"Cannot find module '/var/task/index'","errorType":"Error","stackTrace":["Function.Module._load (module.js:417:25)","Module.require (module.js:497:17)","require (internal/module.js:20:19)"]}

JavaScriptのコード

// build/src/index.js
'use strict';
console.log('Loading function');

exports.post = (event, context, callback) => {
    callback(null, {
        statusCode: 200,
        headers: { "x-custom-header" : "my custom header value" },
        body: "Hello " + event.body
    });
};

確認用のシンプルなJSコード。

動作確認

➜  speee_pf_checker git:(aws_saml) yarn build
yarn run v1.3.2
$ tsc
✨  Done in 3.25s.
➜  lambda git:(aws_saml) ✗ echo '{"body": "chiba"}' |  sam local invoke HelloWorld --template cloudformation.yml
2017/11/27 18:04:54 Successfully parsed cloudformation.yml
...
{"statusCode":200,"headers":{"x-custom-header":"my custom header value"},"body":"Hello chiba"}

上記コマンドで確認した結果、aws sam localが動いていることが確認できた。

後程確認すること

  • node_modulesを AWS SAM Localで読み込む
  • API GatewayをLocalで使う

slackからAWS Lambdaを起動するために、Outgoing WebHooksではなくて Slash commandを使った理由

後で勉強会等で発表するための、自分用メモ。

TL;DR

  • Outgoing WebHooks は private channelでは使うことが出来ない
  • slash commandは private channel でも利用可能
  • private channel でも利用されることを考慮して slackからAPI Gatewayへの連携に slash command を採用した

やりたいこと

  • slack上でURLを入力したら botが起動する
  • botは入力されたURLについて、パフォーマンス観点で修正できるところを教えてくれる
  • botは誰でも利用することが出来る

やったこと

https://dev.classmethod.jp/cloud/aws/slack-integration-blueprint-for-aws-lambda/ 基本的に、class method さんのこのブログを見ながら手を動かした。 ここで、Outgoing WebHooksではなくて、Slash commandを使っている理由を諸々考えたので、その内容をメモった。

構成

SlashCommand(slack) => API Gateway => lambda => slack

slash commandを採用した理由

 slackから lambdaを起動するには、Outgoing WebHooksと、slash commandの2つの方法がある。Outgoing Webhookは、特定のchannelでの発言内容に、特定の語句が含まれていたときに、任意のURLにPOSTリクエストを飛ばすことが出来る。slash commandは、/remind などの、slack上で実行できる slash のコマンドを追加できる機能だ。指定した slash commandが実行されたときに、任意のURLにGET/POSTリクエストを実行することが出来る。slash コマンドでの実行は、他のユーザーにはコマンドが見えない。それは実行することが共有・教育につながるという chatopsの考え方からすると、少しばかりデメリットである。

 しかしながら、今回は slash commandを slack から Lambdaを起動するための interfaceとして利用した。その理由は、Outgoing Webhookは privateなchannelでは起動できないためである。実行コマンドを見えるようにするのは、botからslackに通知する内容で担保することにする。

参考資料

Outgoing Webhooks | Slack

The outgoing webhook integration is only available in public channels. If you would like to get data out of private groups and DMs in real-time, try a slash command.

Slash Commands | Slack

CircleCI 2.0 をlocalで動かす

概要

自分がいるプロダクトでCircleCI 2.0 の導入をすることになった。 恥ずかしいことにCircleCIの設定を自分でしたことが無かったので、設定を簡単にする方法を探した。 公式ドキュメントを読んでいたら、circleci をlocalで動かす方法が見つかったのでやってみた。 その結果、10minくらいで簡単に動かせることが分かった。

このドキュメントには、circleciをlocalで動かす方法と、localで動かす際の注意点を記載する。 基本的には、このドキュメントからの抜粋なので、疑問に思ったらそっちを見て頂けると :pray:

手順

  • circleciコマンドのインストール
  • circleci 2.0用の設定ファイルを書く
  • local環境でcircleciを動かす

circleciコマンドのインストール

curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci
circleci update

これだけで完了

circleci 2.0用の設定ファイル

今回利用した circleci設定ファイルはこちら。

#.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:8.9
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "package.json" }}
          - v1-dependencies-
      - run: yarn install
      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}
      - run:
          name: Running tests
          command: yarn jest
      - run:
          name: tslint
          command: yarn tslint -c tslint.json 'src/**/*.ts'

ここでは、この設定の説明はしない。下記のページにconfigの書き方が記載されているので、確認して欲しい。

Configuration Reference - CircleCI

local環境でcircleciを動かす

# 設定した config.ymlが正しいか確認する
$ circleci config validate -c .circleci/config.yml 
config file is valid
# circleciをlocalで動かす
$ circleci build .circleci/config.yml

====>> Spin up Environment
Build-agent version 0.0.4536-a668371 (2017-11-15T20:13:56+0000)
Starting container circleci/node:8.9
  using image circleci/node@sha256:80714f293dfc6fc72c815a5bc1dc35bf33b3b8e0ebfaec0b4a64c567bbd1e766
....
$ /home/circleci/repo/node_modules/.bin/jest
 PASS  __tests__/parse.spec.ts
 PASS  __tests__/checker.spec.ts

Test Suites: 2 passed, 2 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        3.074s
Ran all test suites.
Done in 3.73s.
Success!
...

これで circleciをlocalで動かすことができた。 続いて、circleciをlocalで動かすときの注意点を記載していく。

注意点

  • 環境変数を指定するときは -e オプションを使うこと
    • circleci build .circleci/config.yml -e VAR=VAL みたいに書く必要がある
  • circleci CLIは Workflowsに対応していない
  • restore_cache, save_cache が使えない
# restore_cacheのエラーログ
====>> Restoring Cache
Error: Skipping cache - error checking storage: not supported

Step failed

最後に

circleciの設定をlocalで確認できるようになると、ちょっと書き換えるときにも色々と捗るので便利そう!

lighthouseの資料を読み込む【Offscreen Images】

TL;DR

  • 画像は必要になったタイミングで読み込もう
  • そのためには、IntersectionObserverが便利だよ

Why the audit is important

Offscreen imageは、フォールドの下に現れる画像である。 usersはoffscreenの画像は見れないので、offscreenの画像を最初のページ読み込み時において、DLする理由はない。言い換えると、offscreenの画像読み込みを延期することは、pageのload timeと操作可能になる時間を短縮できることを表している。

How to pass the audit

この監査を通すためには、最初のリクエストにおいては、トップページの表示されている部分のみDLすること。この戦略を適用することによって、あなたのJS、HTML、CSSは速度を上げることができる。 Critical Rendering Pathを読んでください

offscreen imagesのlazy-loadするタイミングを賢く決定するために、IntersectionObserverの利用を検討してください。

例えば、とても長いページの下の方に、いくつか画像があると仮定する。IntersectionObserverを使うと、あなたはスクロールして必要になった画像のみを読み込むことができる。

読みたい追加資料