TypeScriptとWebpackとReactを使って簡単なTODOリストを作ってみた
最近フロントエンドの勉強をはじめました。フロントエンド界隈(JavaScript界隈)は変化が激しいようで今最新だーと思っていた技術も数ヶ月後には古いみたいなのがざらにあるようですが、最近私が興味を持っているTypeScriptとFacebookが作っているReact.jsをもとにWebpackを組み合わせて使ってみたというものです。
環境構築
nodeやnpmは既に入っているという前提にしておく。
$ npm init
で出てくる質問に片っ端から答える。yesをするとpackage.jsonが生み出される。
次にTypeScriptをインストールし、トランスコンパイル設定ファイルを生成する。
$ npm install typescript $ (npm bin)/tsc --init
すると配下にtsconfig.jsonが生成されているはず。 また、tsconfig.jsonはとりあえず以下のように書き直しておく。
{ "compilerOptions": { "module": "commonjs", "target": "es5", "jsx": "react", "noImplicitAny": false, "sourceMap": false } }
次にWebpackをインストールする。WebpackはJavaScriptやCSSなどのモジュール依存関係を解決しながら変換してくれるものらしい。
$ npm install webpack ts-loader -D
次にWebpackの設定をJavaScriptでかく。webpack.config.js
という名前で保存しておく。
const path = require('path'); module.exports = { entry: { app: "./index.ts", }, output: { path: path.resolve(__dirname, "./dist"), filename: "[name].bundle.js", }, resolve: { extensions: ["*", ".ts", ".tsx", ".js", ".jsx"], }, module: { rules: [ { test: /.tsx?$/, use: [{ loader: "ts-loader" }], }, ], }, };
次に, Reactをインストールする。
$ npm install react react-dom @types/react @types/react-dom -S
後ろの @types
から始まる部分のものは、すべてTypeScriptを使う際に必要でこれらは型定義となっている。
Hello, World
ここまで来たら、Hello Worldと出力させる部分だけをやってみる。
まず、index.htmlを以下のように作成する。
<!DOCTYPE html> <html> <head> <title>Tiny TODO app</title> </head> <body> <div id="app"></div> <script src="./dist/app.bundle.js"></script> </body> </html>
次に、index.tsを作成する。
import * as React from "react"; import * as ReactDom from "react-dom"; import TodoApp from "./todoapp"; ReactDom.render( React.createElement(TodoApp), document.getElementById("app") );
最後にTODOリストを定義するファイルとして、todoapp.tsxを作成する。
import * as React from "react"; export default class TodoApp extends React.Component<any, any> { render() { return ( <div>Hello, World</div> ); } }
これで、webpack
を使ってコンパイルしてみる。
$ $(npm bin)/webpack -p
こうしてから普通にindex.htmlへブラウザからアクセスしてみる。
こんな感じ。
TODOリストを作成してみる
まず入力フォームを作っておく。入力フォームは以下のような感じ。
import * as React from "react"; export default class TodoApp extends React.Component<any, any> { render() { return ( <div> <h3>TODO</h3> <TodoList items={this.state.items} /> <form onSubmit={this.handleSubmit}> <input onChange={this.handleChange} value={this.state.text} /> <button>{'Add #' + (this.state.items.length + 1)}</button> </form> </div> ); } }
一応できたけど、またstateの値やhandleSubmit, handleChangeと言った部分が実装されていない。
まず、コンストラクタを実装する。
constructor(props: any) { super(props); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.state = {items: [], text: ''}; }
こんな感じ。次にhandleSubmitとhandleChangeをそれぞれ書く。
handleChange(e: any) { this.setState({text: e.target.value}); } handleSubmit(e: any) { e.preventDefault(); let newItem = { text: this.state.text, id: Date.now() }; this.setState((prevState) => ({ items: prevState.items.concat(newItem), text: '' })); }
最後に今まで入力した値をきちんと出力するためのクラスとして TodoList
を定義する。
class TodoList extends React.Component<any, any> { render() { return ( <ul> {this.props.items.map(item => ( <li key={item.id}>{item.text}</li> ))} </ul> ); } }
これでおしまい。実際に実行してみる。Webpackでコンパイルした後、ブラウザで普通にindex.htmlを開いてみるとこんな感じになっているはず。
ちなみに書いたコードとかはこれ。
まとめ
環境構築あたりがものすごくしんどいという印象。フロントエンドが正しく動いているというようなテストを書くにはどうするのかまだよくわからないので調べていきたいと思っております。はい。
まだTypeScript自体も写経と言うような感じで使いこなせているわけではないので精進していきたいところです。
GitHubのプロジェクトをCircleCI 2.0でテストできるように移行してみる
前回書いたマストドンの記事が地味にバズっていてびっくりしているたんごです。
今日はマストドンとは全く関係ないですが、自分のGitHubのリポジトリでCircleCIでテストをしているプロジェクトをCircleCI 2.0でテストするようにしたので、簡単にそのメモ書きを残しておきます。
CircleCI 2.0ってなんぞ
を読め、という気持ちなんですが簡単に言うと以下のような違いがあります。
- 基本的にDockerコンテナがそのままCircleCIで動かせるよ。
- ローカルでビルドできるようになるよ。
- キャッシュがめっちゃ効かせられるよ
はい。意味がわかりませんね。一番でかいのはやっとNativeのDockerをサポートしたということではないでしょうか。今までだと、例えば docker -v
でマウントしたり、docker exec
でコンテナ内のコマンドが実行できなかった気がしますが、2.0を使えばそれも簡単にできます。
どうやって始めるの
CircleCI 2.0はまだベータ版なので使いたい人は自分で使いたいよ〜という申請をする必要があります。先程のリンクの下の方にあるAccess CircleCI 2.0’s Beta Nowという部分に行って入力すると、数分後か数日後にメールが届き使えるようになります。
とはいっても、すぐに自分のリポジトリがすべて2.0でビルドされるわけではありません。
まず、今までだとプロジェクトルートに circle.yml
というファイルを作っていました。2.0を適用させるには、.circleci/config.yml
というディレクトリに設定を書く必要があります。
今回私が移行したプロジェクトはこちらです。
基本的にはPythonのみのコードで構成されておりテストも簡単にユニットテストを動かすだけでした。
machine: python: version: 3.6.0 dependencies: cache_directories: - "~/.cache/pip" test: override: - python setup.py test
さてこれを2.0用のYAMLファイルに書き直していきます。 ドキュメントとしては以下の2つを読めば事足ります。
はじめにDockerのイメージを指定します。今回は公式イメージから最新のイメージを利用することにしました。
ここまでの設定を書くと次のようになります。
jobs: build: docker: - image: python:3
次にテストの前の依存関係のインストールやPythonなら requrements.txt
の読み込み、RubyならGemfileからのインストールなどをすると思いますが、そのステップも各必要があるみたいです。
version: 2 jobs: build: docker: - image: python:3 steps: - checkout - run: apt-get update && apt-get install -y libgmp3-dev - run: name: Install dependencies command: pip install -r requirements.txt
stepsのはじめの行である checkout
によりGitHubからコードを取得してくることができます。
また、runはnameとcommandというキーを持つことができ、これらはWeb UI上で次のように表示されるようになります。
お好みで書けばよいでしょう。
最後にテストの部分を追加します。
version: 2 jobs: build: docker: - image: python:3 steps: - checkout - run: apt-get update && apt-get install -y libgmp3-dev - run: name: Install dependencies command: pip install -r requirements.txt - run: name: Run tests command: python setup.py test
ローカルでCircleCIのビルドをテストしてみる
さて、今までのCircleCIであればこのあと実際にこれが正しく動くかどうかに関してはコミットしプッシュしてみないとわからないという状況でした。なので初歩的にはYAMLの構文が間違っていたとか、設定に誤りがあった場合その修正コミットを作成してプッシュするという屈辱的な状況に追い込まれていました。
そこでCircleCIコマンドの出番です。
インストールは簡単で1行で済みます。
curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci
ちなみにDockerが必要なのでよしなにインストールしておいてください。
あとはおもむろにプロジェクトルートで
circleci config validate config file is valid
でコンフィグの検証も行え、 circleci build
で一貫したテストを行うことができます。
circleci build ====>> Spin up Environment Build-agent version 0.0.3052-5be8345 (2017-04-15T11:24:20+0000) Starting container python:3 using image python@sha256:0a979dbff79f466aad8d92a89980ebe19cbd481b135d8cc9c0d843d8cf802ef9 Using build environment variables: CI=true CIRCLECI=true CIRCLE_BRANCH=master CIRCLE_BUILD_NUM= CIRCLE_BUILD_TOKEN=**REDACTED** CIRCLE_JOB=build CIRCLE_NODE_INDEX=0 CIRCLE_NODE_TOTAL=1 CIRCLE_REPOSITORY_URL=git@github.com:ryosan-470/cocoa.git CIRCLE_SHA1=f8cdb852ca92b53ae61768852ad23a9871e3ea8b ====>> Checkout code Warning: skipping this step: running locally ====>> apt-get update && apt-get install -y libgmp3-dev #!/bin/bash -eo pipefail apt-get update && apt-get install -y libgmp3-dev Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB] ... ... writing manifest file 'cocoa.egg-info/SOURCES.txt' running build_ext ============================= test session starts ============================== platform linux -- Python 3.6.1, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- /usr/local/bin/python cachedir: .cache rootdir: /home/ubuntu/cocoa, inifile: setup.cfg collected 5 items tests/test_factorize.py::TestFactorizeTestCase::test_fermat_success PASSED tests/test_factorize.py::TestFactorizeTestCase::test_fermat_timeout PASSED tests/test_factorize.py::TestFactorizeTestCase::test_pollard_rho PASSED tests/test_factorize.py::TestFactorizeTestCase::test_small_prime PASSED tests/test_factorize.py::TestFactorizeTestCase::test_trial_division PASSED =========================== 5 passed in 3.73 seconds =========================== Success!
こんな感じです。あとはコミットしてプッシュすればおしまいです。
あとはWeb UIにアクセスしてみると表示が2.0 になっています。
参考
今何かと話題のマストドン(mastodon)鯖を自分用に無料で立てる方法
こんにちは。社会人2週間が経過して日々辛い思いを背負っているたんごです。
水曜日頃TLで賑わっていたポストTwitterとか色々呼ばれているマストドン(mastodon)が流行っていますね。ただ日本鯖であるmstdn.jpが1人の大学院生の自宅鯖で動いていてめっちゃアクセスが有ってしんどいみたいな感じだったようですね。そんな中私は仕事を終え帰宅後に1時間程度でAWSにこれをデプロイして自分用として遊んでいます。 基本的には公式ドキュメントをそのまま読めば大抵何とか成るのですが、自分用に鯖を立てて良い感じに公開する方法を記述しておきます。
必要なものと前提知識など
- LinuxサーバーにSSHしたことがある
- AWSのアカウント または適当なクラウド事業者を使うことのできるアカウント
- クレジットカード (無料枠だけなら必要ないかも?)
- 独自ドメイン
- エンジニアなら自分の独自ドメインくらい持ってるよなぁ?
- 1年目ならかなり格安で取れるので興味があればとってしまうのはありだと思います
インスタンスを建てよう
今回のお話ではAWSにインスタンスを建てました。AWSはアカウント作成から1年の間であれば t2.micro
というインスタンスに限り無料で利用することができます。仮に全額支払っても月$20行かない程度なので他の用途で遊ぶのもありですね。AWSへのインスタンスの建て方に関しては割愛します。
もちろんさくらのクラウドやVPS, GCP, Azureなど自分が好きな場所に好きなように建ててもらってかまいません。
ちなみに今回のOSはUbuntu 16.04 LTSを利用しています。
必要なものをインストールする
次にインスタンスへSSHで接続します。接続したら今後必要になるであろうものをインストールしておきましょう。
$ sudo apt-get update $ sudo apt-get install -y git
マストドンは公式ドキュメントではDockerコンテナを利用して構成されています。実は普通にインストールする方法もあるのですが面倒なのでDockerコンテナをそのまま利用してしまいましょう。
はじめにDockerと docker-compose
をインストールします。次のドキュメントを参照すればOKです。
つまり、まず、
$ sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
をして次にDockerのGPG鍵を追加します。
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
最後に公式のリポジトリを追加します。
$ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
現在DockerにはCEとEEがありますがエンタープライズ向け(EE)を入れても仕方がないのでCEを入れましょう。
$ sudo apt-get update $ sudo apt-get install docker-ce
これでインストールは終了です。一応自分自身が root
権限がなくても docker
コマンドを使えるようにしておきましょう。
$ sudo usermod -aG docker $USER
一度ログアウトし再度ログインします。
次に docker-compose
をインストールします。できるだけ最新版のリリースを入れましょう。
$ sudo su # curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose # chmod +x /usr/local/bin/docker-compose
マストドンを立てる
GitHubのマストドンのREADMEにあるとおりに進めていきます。 ちなみに平易な英文ですので基本的にはREADMEを読んでくださいね。
$ git clone https://github.com/tootsuite/mastodon $ cd mastodon
追記 (4/16分)
non_117 さんがはてぶでコメントしてくださっていますが、たしかに永続化設定していることを書くの忘れていました。コメントありがとうございます。
今何かと話題のマストドン(mastodon)鯖を自分用に無料で立てる方法 - jtwp470’s blogb.hatena.ne.jpdocker-compose.ymlでpostgresqlの永続化設定コメントアウトするの忘れてませんか? 忘れてたら絶対にdocker-compose downせずにpsqlでDBをdumpしましょう。 / この記事鵜呑みにして永続化忘れる人がでると悲劇なので書いておいてほしい
2017/04/16 13:22
Dockerではコンテナ内の変更は永続化されないため、別途ディスクにボリュームとしてマウントしてあげないと、インスタンスの再起動やコンテナの再生成時にDBやRedisが全て吹き飛びます。💣 やばいので、永続化されるよう、docker-compose.yml
の中身のコメントアウトを消してあげます。
db: restart: always image: postgres:alpine volumes: - ./postgres:/var/lib/postgresql/data redis: restart: always image: redis:alpine volumes: - ./redis:/data
こうすると、カレントディレクトリの ./postgres
と, ./redis
にコンテナ内のデータが置かれ、失われずにすみます。
(追記終わり)
さてはじめに、環境変数を準備します。
cp .env.production.sample .env.production
ドキュメントに書いてあるとおり最低限以下の環境変数をセットする必要があります。
LOCAL_DOMAINは自分でもっているドメイン、(もしサブドメインで運用するならその値を)、LOCAL_HTTPSはtrue
にしておきましょう。
また、
- PAPERCLIP_SECRET
- SECRET_KEY_BASE
- OTP_SECRET
は、次にコマンドで出力される値を書いておけば良いみたいです。
$ docker-compose build $ docker-compose run --rm web rake secret
私の鯖では最終的に .env.production
を次のような感じにしました。(一部検閲済み)
# Service dependencies REDIS_HOST=redis REDIS_PORT=6379 DB_HOST=db DB_USER=postgres DB_NAME=postgres DB_PASS= DB_PORT=5432 # Federation LOCAL_DOMAIN=mastodon.jtwp470.net LOCAL_HTTPS=true # Application secrets # Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) PAPERCLIP_SECRET=xxx SECRET_KEY_BASE=xxx OTP_SECRET=xxx # Optionally change default language DEFAULT_LOCALE=ja # E-mail configuration # Note: Mailgun and SparkPost (https://sparkpo.st/smtp) each have good free tiers SMTP_SERVER=email-smtp.us-west-2.amazonaws.com SMTP_PORT=587 SMTP_LOGIN=<censored> SMTP_PASSWORD=<censored> SMTP_FROM_ADDRESS=noreply@mastodon.jtwp470.net
これらが終わったらデータベースのマイグレーションとフロントエンドのプリコンパイルを行います。
$ docker-compose run --rm web rails db:migrate $ docker-compose run --rm web rails assets:precompile
これらが終わったら立ち上げてみましょう。
$ docker-compose up -d
これで立ち上がりました。次にNginxをインストールし、証明書をLet’s Encryptで生成します。
SSLを有効化する
↑を参考に続けていきます。
$ sudo add-apt-repository ppa:certbot/certbot $ sudo apt-get update $ sudo apt-get install certbot nginx
あとは証明書を取得します。
$ certbot certonly --webroot -w /var/www/example -d example.com
さてNginxの設定はドキュメントをそのままパクります。
注意点としては、
こんな感じです。ここまで来てDNSをきちんと設定しておけば、https://example.com
などに自分だけのマストドンインスタンスが生み出されます。
初期登録と管理画面をだす方法
はじめに自分のインスタンスにサインアップしようとしてもメールが送られてこないと思います。というのも、メールサーバーの設定をしていないためです。 ただ、仮に自分だけ、または知り合いからのみしか登録を受け付けないという設定の場合はメールを送る必要はないと思いますのでその設定をしたくないと思います。こんなときは手動で登録ユーザーの承認を行いましょう。
$ docker-compose exec web bundle exec rails mastodon:confirm_email USER_EMAIL=alice@alice.com
これで上の例では alice@alice.com
で登録したユーザーが承認されログインできるようになります。
管理画面の出し方
管理画面を出すにはどうするねんという話ですが公式ドキュメントのAdministration Guideにその答えはありました。
次のコマンドを打ちます。
$ docker-compose exec web bundle exec rails mastodon:make_admin USERNAME=alice
これでユーザー alice
が管理者としていろんなことができるようになりました。
メールを送って不特定多数のユーザーを招待したい
さて、もしメールを不特定多数のユーザーに送れるようにして自分のインスタンスにメールを送りたいという場合どうしましょうか。わざわざEC2インスタンスの中にメールサーバーを自前で構えてメール送受信申請を出すのも面倒ですし…という方の解決策としてAWS SESを使うという方法がありました。
AWS SESはAmazon Simple Email Service のことで簡単にEメールを送受信できるサービスです。無料利用枠として月1000件のメッセージの受信と62000件のメッセージの送信が無料だそうです。仮に有料でも1000つうあたり0.10 USDなのでそこまで高いというわけでもないと思います。
ちなみにSESは東京リージョンでは利用できません。そこで私は米国西部(オレゴン, us-west2)を利用しています。
まずDomainsへ行き自分のドメインを証明してもらいます。DKIMも生成しておきましょう。
こんな画面が出てくるのでDNSサーバー側でよしなに設定をします。設定終了後少し待っているとStatusがVerifiedになると思います。 次にEmail Addressesの画面を開き自分の受信できるメールアドレスを入れておきます。初めての状態ではこのメールアドレスに対して1000件のみしかメールが送れないという状態になっています。次にSMTP Settingsを開き、Create My SMTP Credentialsで認証情報を作成します。
これらの情報を .env.production に追加します。
- SMTP_SERVER:
email-smtp.us-west-2.amazonaws.com
- SMTP_PORT:
587
- SMTP_LOGIN: 生成された値
- SMTP_PASSWORD: 生成されたパスワード
再度ビルドし、起動すればメールの送受信が可能になっていると思います。
$ docker-compose build $ docker-compose up -d
最後に
マストドン日本鯖が落ちたり、自宅鯖から移行してさくらのクラウドに移行したり、pixivがマストドンの運営を始めたりといろいろカオスな状況ですが、そこで大変な思いをするより自分で自分用に囲ってしまい遊んでいるほうがらくじゃないですか?
ものすごく isidaiさんの考え方に共感したのでその記事を貼っておきますね。
ドメインで名前空間が完全に分離されたお一人様インスタンスですので、自分の好きなようにTOOT(投稿)していいし、自分でアップロードしたファイルを自分のAmazon S3バケットに保存しておけます。
ドメインでアイデンティティを確立する という言葉ものすごくパワーワードを感じますね。
ちなみに1 core 1GBのインスタンスでマストドンを運営するとメモリが6 - 7割食われてしまい、RedisのログではOOM Killerが多発しているようですがガン無視して運営しています。もし余裕がある方ならメモリ量を増やすことをおすすめします.
以下は金曜日の深夜から初めて2日間たったあとのDatadogのログ。
みて分かる通りCPUはほとんど使いませんがメモリが..
これは直近のメモリ使用量です。マストドンを落としたところが急激に落ち込んでいるのがわかりますw
マスト丼
本当に最後になりますが、細々と自分のドメインでmastodonを運営しています。もし興味があって参加してみたければぜひ来てください。
また、マストドンのアカウントも作っていますのでフォローしてくれれば喜びます。
後日談
ElixirConfに参加してきた
表題の通り,ElixirConfが秋葉原で昨日(4/1)にありました.これは参加記と自分のメモを載せておくための記事です.
Opening Keynote
Elixirの作者であるJosé Valimさんのセッションでした.全編英語でしたがものすごく聞き取りやすい英語で5割程度は理解できました. 2011年にElixirという言語を設計したときの悩みや開発の進みなど言語開発者でしか味わうことのないようなお話で非常に興味深いものでした. 後半で述べていましたがこれからElixirにどんな機能を追加していくかというものでUTF-8 Atomが導入されたようです.例でも挙げていたように次のようにテストなどを書くことができるようになります.
test "こんにちは世界" do assert :こんにちは世界 end
個人的にはあんまりこのように書きたくはありませんがやはり非英語ネイティブからすると英語ベースではないというのも1つの強みなのでしょうか.
また,質問コーナーで盛り上がった型チェックの導入の検討.よいですね.静的型チェックがデフォルトで入ってくれればIDE等も対応してきてやりやすくなるのではないでしょうか.Pythonでも3.5からType Hintingなどがはいってきたように言語に型情報をつけるの流行ってますね.
Phoenixで作るスケーラブルゲームサーバ
www.slideshare.net
モンストを手がけるmixi社において一部サーバーをElixirで書いているようです.Erlang VMの安定性と軽量プロセスは突発的なアクセスに非常に強く作られているようです.
また,Erlangと違い文法がRubyライクなのが新たなエンジニアの参入障壁を下げているようです.確かにそれは一理ありそうです.関数型言語でもいきなりHaskellやLispに手を出すと途中で詰む人が多いですしね.(諸説あると思いますが) やはり大人数の開発ではなるべくみんなが理解しやすい文法で書けるという言語はよいのでしょう.だからこそRubyやPythonといったライトな言語が流行っているのですし.
最後にHot Code Loadingとかいうワード.はじめて知りましたがErlang VMはデータはそのままにコードだけを最新に置き換えるという機能があるみたいです.ただ,謎バグを踏んだりと大変みたいですが.
Functional Programming with Elixir
関数型言語についてElixirで入門しようという話.対象ははじめて関数型の知識を勉強しようという人向け.確かにElixirで学んだほうが文法が辛いとか考えなくてよくわかりやすいかもしれない.あと発表で言っていたとおりElixirの=
演算子は一般的なプログラミング言語の代入という意味ではなく,「パターンマッチング」ということに気をつけておかないといけないし,案外そのことで突っかかるかもしれないなぁと思いました.
Rediscovery of OTP
ブラウザゲームの時代から現在のゲーム開発まで色んなお話が面白かったです.Elixirは安定と信頼**のErlang VMで動いているという話と「Erlang VMは安定しているけど乗ってるサーバー(AWS)が安定しない」という話は名言な気がする.
あとgumiのPython 2コードは3へは移行せずにElixirに書き直すというお話だったのでぜひ今年か来年のPyConで話してほしいなぁと思った.
これ以降はMacのバッテリがなくなりスマホで頑張ってメモを取りながら聞いていましたがとりあえずElixirを勉強するには以下を理解する必要があるということがわかりました.
- Elixirの文法 (当たり前)
- OTPについて理解
- Erlangを少し書ける読めるようになること.