vimでNERDTreeを使いつつもmksしたい
最近nvimを使っているんですが、NERDTreeを起動したまま
:mks
して
nvim -S
するとNERDTreeが復元できなくてエラーになります。
ちょっと調べたんですがあまり良い方法が見つからず・・・。
せっかく ~/.config/git/ignore
に Session.vim
を書いてglobalでgit ignoreできて他の人がvim使ってないプロジェクトでも優勝!と思ったのに。
しょうがないのでvim終了時に :mks!
するようにしてその直前にNERDTreeは閉じることにしました。
autocmd VimLeave * NERDTreeClose autocmd VimLeave * mks!
復元できるのが一番ですが、あまり設定周りを複雑にしたくない気持ちもあり。
何かいい方法あれば教えていただきたいです。
お試しIonic React
IonicFrameworkについて、最近よく耳にするので、自分も試したかったためプロジェクト作成→PWA→iOSビルドまでやってみました。
やったことは完全に ドキュメント (Installing Ionic - Ionic Documentation) の流れなので、内容については細かくは書きませんが、ざっくり説明すると
- npmでPCに
@ionic/cli
を入れる - ionicコマンドでプロジェクトを作る
- npmで
@ionic/react
and@ionic/react-router
を入れる ionic serve
してweb開発する(まんまreact scriptsですね)- githubにpushし、netlifyにデプロイしてPWAを実機(iPhone)で試す
- ionicコマンドで
capacitor add ios
する capacitor.config.json
の appId(Bundle ID)をセットする(store公開しないので適当に)- macOS最新化
- Xcode最新版インストール
- cocoapods最新版インストール
- Xcodeでプロジェクト開く
- エミュレータ&実機ビルド確認
をしました。 ただ、実際には8をやる前に実機ビルドしようとして、pod installがコケたり、ダークモードのコードがうまく動作しなかったりといったことで軽くハマっているので前後関係がちょっと違います。全部最新化されていればハマりポイントは少なくサクッといけそうだなぁという印象です。ネイティブのAPIなどはまだ触っていないので、その辺触り出したらどの程度ハマるか・・・。
リポジトリは下記です。
所感(触って10h程度です。前述の通りネイティブのAPIはまだ触っていません。)
- ドキュメントしっかりしていたのでwebでの開発に入るまではサクッといけたので、単なるWebアプリでも採用して良いのではないかという印象です。(ただパッケージの依存性などの制約がどの程度あるかなどはわかりませんが、そこはもう使う以上はIonic Wayに乗っかるべきですね。最悪Ionicだけを剥がすこともできそうなのは👍)
- ネイティブにビルドするためにどの程度コードの書き方への制約があるのかまだよくわかっていませんが、表面的な部分では普通にReact書いてそのままiOSアプリ作れる感覚がとてもGoodでした。
- Xcode周りはSwift開発ほどの知識は不要とはいえ、CocoaPodsなどを全く知らない状態からやるとハマって抜け出せなくなる場合もありえるのかな?と思いましたが、逆にIonicからネイティブビルド環境に触れる足掛かりにするのもありかなと。この手の「ハイブリッドアプリやクロスプラットフォームのフレームワークはそのネイティブアプリビルド環境の知識がないとキツイ問題」はどこでも同じだとは思いますので。
というわけで技術選定時に問題がなければプロダクションでも積極的に使っていきたいなーという気持ちは今のところ結構強いです。
@vue/composition-apiで縦と横のwindowサイズの変更検知する
最近 @vue/composition-api
を触っていて、ウィンドウサイズを検知して値を取得する処理を書いたので備忘録として残します。
以下そのまま書いてもたぶん動きますが確認してないです。
import { defineComponent, reactive, onMounted, onBeforeUnmount, } from '@vue/composition-api' export default defineComponent({ setup() { const state = reactive({ width: window.innerWidth, height: window.innerHeight, }) const resizeWidth = () => { state.width = window.innerWidth } const resizeHeight = () => { state.height = window.innerHeight } onMounted(() => { window.addEventListener('resize', resizeWidth) window.addEventListener('resize', resizeHeight) }) onBeforeUnmount(() => { window.removeEventListener('resize', resizeWidth) window.removeEventListener('resize', resizeHeight) }) return { state, } }, })
template内では以下のようにして検知して値を取れます。これで横幅によって分岐ができて嬉しいかも。
<template> <div> {{state.width}} {{state.height}} </div> </template>
もっと良い書き方あればぜひコメントください。
Nuxt.jsから始めるPWA生活
gunma.webでLTしてきました。
テーマフリーということで、PWAへの取っ掛かりの内容で話してきました。
LT内容
- スライド
- DEMOページ
elated-knuth-617fed.netlify.com
以下、LTの補足内容です。知っている人には大した情報ではないので、最後( PWA iOSつらい問題について
)だけ読んで、解決策知ってる方いたら教えていただけると嬉しいです。
デモの環境について
スマホでホーム画面に追加するとPWAアプリ化します。オフラインでも一度読み込むとページ遷移するので、読み込んだあと機内モードにしてみてください。
私が初めてPWAを実装を触った時(一年半くらい前?)にはもうNuxt.jsにpwaのモジュールがあり、ちらほらと記事をあげている人がいて、とっつきやすかったので、今回題材としてもNuxt.jsを使用しました。
静的ファイルをgenerateできるのも良いところで、以下コマンドでビルドしてnetlifyでホスティングしてサクッと見せられるのも良いところです。
$ yarn generate // ディレクトリ・dist内にgenereteされるのでそれをホスティング
PWAの '実装' について
LT冒頭で、PWAは特定の実装を指すものではない、ということを少し強調して話したのですが、googleの指針があったり、lighthouseでPWA実装状況が表示されるようになってたりで、何に対応していたらPWAか、ということが具体的にわかるものがあります。
例えばMicrosoftの PWABuilder を使用すればWebサイトのPWA実装状況を見ることができます。
ちなみに、デモサイトの結果は以下のような感じ。
pushManagerが実装されてない旨が表示されています。
サービスワーカーの利用について
さらに踏み込んだキャッシュ戦略を行う場合、今回紹介した範囲だけでなく、直接cache APIを利用する処理やServiceWorkerとやりとりする処理を書く必要が出てくる場合あるかもしれません。
その時はworkboxも利用できる状態なので、ドキュメント見ながら頑張るって感じになると思います。
自分もチョットやったことはありますが教えられるほど詳しくない&いろいろ見てても泥臭い処理書いてる場合が多くてベストプラクティス、綺麗な書き方がわかっていない状態なので、むしろこの辺は細かく教わりたいですね......。
WebPushについて
今回のLTではあえてweb pushについてはあまり触れませんでしたが、OneSignal使うと比較的容易に実装できた気がします。お手伝いでやったけどうろ覚えです。
Nuxt.js pwaのドキュメントにも載ってるのでその通りにやるだけですが、iOSはまだ対応してないのでandroidとブラウザ/デスクトップPWAでしか通知はきません。
PWA iOSつらい問題について
言及している2つのポイント
- バージョンID情報アップデートしてもアプリが更新されない
- web pushがない
以外は個人的にはPWAとしてそこそこ使えるレベルにはなっていると思っています。
ただ、1の状況が直近なぜ起こっているのかわからず、androidでは正常に更新されるので、これが実装の問題じゃないのであればかなり致命的だなと。(業務アプリやる分にはOAuth情報保持されなくても画面reloadされる方がまだマシだった)
これ、だれかわかる人とか同じ状況起きたって人いたら教えてほしいです。
あとはスプラッシュが出ないとか細かいところはありますが、上記ができれば個人的にはより普及するんじゃないかと思っています。
最後に
深夜3時から4時頃にスライドの冒頭とデモ作ったので若干寒いネタが入ってるんですが、話す時はいかに寒いと思っても臆しないかが重要だということが勉強になったLTでした。(いったい何の勉強会なのか)
他の方の面白いLTも結構あったので、そのうちconnpass上に資料があがると思うので是非見てみてください。
Gunma.web #34 スキーマ駆動開発に参加しました/LTしました
Web + DB pressで執筆された中野さんに講演をしていただき、OpenAPI Generatorめちゃめちゃ使いたいな!?となりました。
https://github.com/OpenAPITools/openapi-generator
スキーマ駆動開発、言葉としては新しいですが、思想としては今までみなさんやりたい/やっているものだと思うので、今後APIの実装は定義して、コード生成するという流れが加速していくのではないかなと感じています。
今回、前日の夜に「LTせよ」という天の声を受け取ったため、5分LTしてきました。
ネタとしてはAWSの標準機能であるAPI Gateway Swagger インポートをしてみたという話です。
Open APIの3に対応していて、初めてインポートしてみたのでどんな感じなのか手探りでやってみたけどインポートだけなら簡単だったという話です。
実務で使っていくにはどこまでできるかの調査と、いろいろ仕組み作りは必要だなと思いましたが、可能性は感じました。
スライド内でREST Clientから実行してみている箇所がありますが、もちろんswagger-uiからの実行もうまくいきました。(なぜか最初はswagger-uiの存在が頭から抜け落ちていた)
APIはドキュメントとの乖離をなくしていく、単純なものはコードを書かずに生成するという方向で実務でも使っていけたら幸せになれるのではないかと感じた会でした。
gunma.web #34 全LT資料はこちらにアップロードされています。
中野さんのスライド
平静を保ち、コードを生成せよ 〜 OpenAPI Generator誕生の背景と軌跡 〜 / gunmaweb34 - Speaker Deck
中野さんの講演の中で話題に出てきたと思われるスキーマの参考記事
JAWS-UG 群馬 #2 でLTしました->AWSサーバーレスアーキテクチャでWebサイトを構築してみた
2018/12/18にJAWS-UG 群馬支部のLT会が開かれました。
テーマは「今年AWSでこれやったよ!」
JAWS-UG 群馬は10月に発足したばかりなので現在手探りでいろいろやっている状況です。(私は運営メンバーではありませんが。)
発表内容
今回LTということでサーバレス関係でLTをしました。
私の個人サイト(https://www.poriweb.com/)はnetlifyでホスティングしているのですが、別件でWebサイトを構築する件がありまして、S3でのホスティングを選びました。
この構成です↓ aws.amazon.com
この構成、比較的容易ではあるんですが、デプロイなどの環境を整えなくてはならないので、個人的にはAmplify consoleに期待しています。
あと、サーバーレス関係ないですが、EKS Tokyoはよ・・・! (追記: はよって言ってる時点でもう来てました笑)
他の方の発表内容
AWS re:Invent 2018参加報告
現地に行かれたそうです!
現地ならではの雰囲気もあると思うので一回行ってみたいですね〜。5分でS3にサイトをアップする方法をやろうと思ったら90分ハマり倒した話
WebコンソールのUIが変わったり機能が変わったり、っていうの結構あるので本を参考にやっていてもハマることがあるんですよね。 公式のドキュメントが取っつき辛いというのもあります。今年AWSでこれやったよ!
特に気になったのが、Alexaスキルについて。
元々興味はあってecho dot持っているんですが、なかなか重い腰が上がらなかったので、実際にやってる人の話を聞いてやりたくなりました。
最後に
発表内容にあるサーバサイドのLambdaの詳しい内容については前回の記事(AWS Lambda(python) / API Gateway / DynamoDB / SES でWebサイトのお問い合わせAPIを作る(DB保存,メール,slack連携) - poriweb)に載せています。
AWS Lambda(python) / API Gateway / DynamoDB / SES でWebサイトのお問い合わせAPIを作る(DB保存,メール,slack連携)
サーバーレスでwebサイトを構築をすることがあったので、Lambdaネタです。
ググればすぐ出てくるような話が主ですが、ユースケースが合う人の参考になれば。
作成部分は簡単にしか書いていませんので詳しくはドキュメントを参照願います。
また、pythonで書いているので他言語は読み替えていただければと思います。
LambdaとAPI Gatewayを作成する
Lambda関数を作成する
AWS WebコンソールよりLambda関数を作成します。
ロールに権限が必要になるのでDynamoDBとSESにアクセスできるようにしておきます。API Gatewayを作成する
コンソールよりAPI Gatewayに行き新しいAPIの作成を押下し、API名とエンドポイントタイプ(リージョン)を入力/選択して作成します。
空のAPIにリソースを設定します。アクションからメソッドの作成を選択し、POSTを作ります。Lambda関数の欄に先ほど作成したLambda関数を入力して保存。
また、CORSは有効化しておきます。POSTメソッドを選択し、アクションからCORSの有効化を行います。
あとはAPIをデプロイすればAPI Gateway側の基本設定は終了で、APIを実行できるようになります。
- 最終的にLambda側のDesinerはこんな感じ(CloudWatchとS3にも権限を与えています)
前提:お問い合わせのPOST内容
下記のようなjsonが送られてくるとします。関数のテストイベントの中身をこれにしておきます。
{ "item": { "company_name": "テスト株式会社", "name": "テスト名前", "tel": "000-0000-0000", "email": "hogehoge@test", "content": "内容" } }
1. Lambdaで入力されたものをDynamoDBに保存する
まず、DaynamoDBに contacts
というテーブルを作成しておきます。
lambdaのコードは元々はこんな感じ
import json def lambda_handler(event, context): # TODO implement return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }
event
で入力を受け取ります。APIの場合POSTされてきた中身がここに入ってきます。
POSTされてきたデータをlambdaに登録する処理を入れたコードはこんな感じ。
import json from datetime import datetime import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') def lambda_handler(event, context): item = event['item'] # 対象テーブル table = dynamodb.Table('contacts') # 実行時間を登録しておく item['received_at'] = datetime.now().strftime("%Y/%m/%d %H:%M:%S") # テーブル登録 table.put_item( Item=item ) # 成功 return { 'statusCode': 200, 'body': json.dumps('success!') }
登録された時間をテーブル内のデータとして持っておきたかったので datetime.now
を使用しています。注意点としては日本時間にする場合はLambda関数の環境変数にタイムゾーンを設定しておく必要がある点です。
2. Lambdaでお問い合わせ内容をメールで管理者に知らせる
先にSESでドメインから送信できるように設定しておく必要があります。
仮に test.com
というドメインを持っていて送信できる状態とします。
メール送信用に以下のような関数を用意します。
import boto3 MAIL_REGION = "us-east-1" def send_email(source, to, subject, body): client = boto3.client('ses', region_name=MAIL_REGION) response = client.send_email( Source=source, Destination={ 'ToAddresses': [ to, ] }, Message={ 'Subject': { 'Data': subject, }, 'Body': { 'Text': { 'Data': body, } } } ) return response
呼び出しは send_email("no-reply@test.com", "admin@test.com", "タイトル", ”本文”)
といった感じです。
これを踏まえて先ほどのDB登録を行うコードに付け加えてみます。
import json from datetime import datetime import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') MAIL_REGION = "us-east-1" def send_email(source, to, subject, body): client = boto3.client('ses', region_name=MAIL_REGION) response = client.send_email( Source=source, Destination={ 'ToAddresses': [ to, ] }, Message={ 'Subject': { 'Data': subject, }, 'Body': { 'Text': { 'Data': body, } } } ) return response def lambda_handler(event, context): item = event['item'] # 対象テーブル table = dynamodb.Table('contacts') # 実行時間を登録しておく item['received_at'] = datetime.now().strftime("%Y/%m/%d %H:%M:%S") # テーブル登録 table.put_item( Item=item ) # メール送信 title = "お問い合わせが来ました" message = "会社: " + item['company_name']\ + "\n名前: " + item['name']\ + "\nメールアドレス: " + item['email']\ + "\n電話番号: " + item['tel']\ + "\n内容:" + item['content']\ src = "no-reply@test.com" dst = "admin@test.com" rsponse = send_email(src, dst, title, message) # 成功 return { 'statusCode': 200, 'body': json.dumps('success!') }
3. Lambdaでお問い合わせ内容をslackにも連携する
slack連携はwebhookを使用してPOSTすれば良いので urllib.request
でなげちゃいます。これだけのためにRequestsを入れるのは面倒そうだったのでurllibを使用しています。
先ほどのコードにさらに追記しちゃいます。
import json from datetime import datetime import boto3 from boto3.dynamodb.conditions import Key, Attr import urllib.request dynamodb = boto3.resource('dynamodb') MAIL_REGION = "us-east-1" def send_email(source, to, subject, body): client = boto3.client('ses', region_name=MAIL_REGION) response = client.send_email( Source=source, Destination={ 'ToAddresses': [ to, ] }, Message={ 'Subject': { 'Data': subject, }, 'Body': { 'Text': { 'Data': body, } } } ) return response def lambda_handler(event, context): item = event['item'] # 対象テーブル table = dynamodb.Table('contacts') # 実行時間を登録しておく item['received_at'] = datetime.now().strftime("%Y/%m/%d %H:%M:%S") # テーブル登録 table.put_item( Item=item ) # メール送信 title = "お問い合わせが来ました" message = "会社: " + item['company_name']\ + "\n名前: " + item['name']\ + "\nメールアドレス: " + item['email']\ + "\n電話番号: " + item['tel']\ + "\n内容:" + item['content']\ src = "no-reply@test.com" dst = "admin@test.com" rsponse = send_email(src, dst, title, message) # slack連携 url = 'https://hooks.slack.com/services/ slackから発行されたwebhooks url' # 自分のワークスペース,チャンネルのものに置き換えてください data = { 'text': '<!here>\nお問い合わせが来ました。\n *会社* \n' + item['company_name'] + '\n *名前* \n' + item['name'] + '\n *メールアドレス* \n' + item['email'] + '\n *電話番号* \n' + item['tel'] + '\n *内容* \n' + item['content'] } headers = { 'Content-Type': 'application/json' } req = urllib.request.Request(url, json.dumps(data).encode(), headers) with urllib.request.urlopen(req) as res: body = res.read() # 成功 return { 'statusCode': 200, 'body': json.dumps('success!') }
これで以下のようなメッセージが飛びます
@here お問い合わせが来ました。 *会社* テスト株式会社 *名前* テスト名前 *メールアドレス* hogehoge@test *電話番号* 000-0000-0000 *内容* 内容
最後に
例として挙げたソースコードは各機能をくっつけただけかつエラーハンドリングまともにしてないなど修正、リファクタリングする必要はありますが、ただ実装するだけなら簡単にできました。
メールの送信実行以外は lambda_handler
にほぼ処理を書いていてごちゃごちゃしてしまったのでこれから機能単位で分離していこうと思います。
また、実行しながら上記コードを書いているわけではないのでおかしいところなどありましたらご連絡していただけると助かります。