- 投稿日:2020-06-23T22:26:44+09:00
Next.jsを使って、医師国家試験の勉強ノートを公開するブログを作った話
Next.jsを使って、医師国家試験の勉強ノートを公開するブログを作った話
表題の通りです。まずは完成品とレポジトリのURLをどうぞ。
サイト:https://chilvary-beta.vercel.app
GitHub:https://github.com/yokonao/chilvary-beta
作ったきっかけ
next.jsの公式チュートリアル(URLは以下)をやったら、構築の容易さとSPAのページ遷移の速さに感動したので。これで自分のブログ作ったら超便利じゃない?と思いました。単純なページ公開だけならバックエンドなしでも可能です。
https://nextjs.org/learn/basics/create-nextjs-app?utm_source=next-site&utm_medium=homepage-cta&utm_campaign=next-websiteアーキテクチャ
アーキテクチャっていうのは大げさすぎるかもしれません。
- ローカルPCで書いたMarkdownファイルを作成
- MarkdownファイルをAWS S3にアップロード
- S3のデータを引っ張ってきて、静的サイトとしてビルド
Next.jsとは全く関係ありませんが、Markdownファイルのバージョン管理とアップロードは完全自動化しています。作業終了後Alfredをちょっと立ち上げてAppleScriptを起動すればアップロードが完了するようにしました。(AppleScriptでgit pushしてgithub actionsでS3にアップロード)。この話はまた別でしたい。
メリット
- SPAなのでページ遷移はほぼ0秒
- 超優秀なMarkdownエディタTyporaの力を借りることができる
参考:https://qiita.com/4_mio_11/items/223326c3289f6b2c2a07
実際の記事にはどんなこと書いてんの?
クエスチョンバンク(QB)を解きながら、疑問に思った点を調べてMarkdownファイルにまとめる。国試の勉強は長期戦なので、1年後の自分に向けて書いてます。
スタイルに関しては、Typoraのテーマで使用されているcssファイルとBulmaを併用してます。記事をローカルで作成した時とほぼ同じ見た目で公開しつつ、ヘッダーなどを作る際はBulmaのコンポーネントを利用できるになっています。
チュートリアルから進化している点
S3のディレクトリ構成が完成品のブログにそのまま反映されています。説明が難しいですがサイトを一度巡回していただければ、意図が伝わるはず...
本当に手元で作成したフォルダがそのままwebサイトになるイメージです。
Next.jsのすごいところ
このwebサイト、markdownファイルの中身をNext.jsに渡してあげれば成立するので以下のような拡張もできると思います。
データの置き場所をS3からデータベースにする
Markdown形式で記事をアップロードできるwebアプリを作成してS3を介してつなぐ
メディアサイトのようなものを作成しようとすると、認証機能など難しい点も出てくるでしょう。しかし、ローカルで作成した文書をSPAとして公開できるサイトをこれだけ簡単に自分で1から作れてしまうのは、Next.js様様かな、と感じます。もちろんGitHub Pagesなどもっと楽な選択肢もありますが、SPAや自由にカスタマイズできるというメリットは十分あると思います。
個人的には自分で見返す際もページ遷移に時間をとられないのでストレスフリーで気持ちいいです。普段やる気にならない勉強も記事作成という遊び感覚でできるようになりましたし。
今後
現在は、ビルド時に全てのページを静的に作成しているので、記事を追加・変更する際は再ビルドが必要になります。
しかし最近、Next.jsは静的なwebサイトに動的なページ更新機能を搭載できるようになりました。Incremental Static Regenerationというやつです。この機能を使いたかったのですが、現在はバグが存在するようなので実現できませんでした。
Next.jsのレポジトリではこのバグに関するissueに最優先事項のラベルがつけられていたので、修正がきたら導入したいと思っています。これさえ導入できれば、Markdownファイルの保存から公開までがほぼ自動化できる...
補足
Incremental Static Regenerationについては以下のサイトの説明が超わかりやすいです。(英語ですけど...)
https://arunoda.me/blog/what-is-nextjs-issg
件のバグのissue
- 投稿日:2020-06-23T22:26:44+09:00
Next.jsを使って医師国家試験の勉強ノートを公開するブログを作った話
Next.jsを使って医師国家試験の勉強ノートを公開するブログを作った話
表題の通りです。まずは完成品とレポジトリのURLをどうぞ。
サイト:https://chilvary-beta.vercel.app
GitHub:https://github.com/yokonao/chilvary-beta
作ったきっかけ
next.jsの公式チュートリアル(URLは以下)をやったら、構築の容易さとSPAのページ遷移の速さに感動したので。これで自分のブログ作ったら超便利じゃない?と思いました。単純なページ公開だけならバックエンドなしでも可能です。
https://nextjs.org/learn/basics/create-nextjs-app?utm_source=next-site&utm_medium=homepage-cta&utm_campaign=next-websiteアーキテクチャ
アーキテクチャっていうのは大げさすぎるかもしれません。
- ローカルPCで書いたMarkdownファイルを作成
- MarkdownファイルをAWS S3にアップロード
- S3のデータを引っ張ってきて、静的サイトとしてビルド
Next.jsとは全く関係ありませんが、Markdownファイルのバージョン管理とアップロードは完全自動化しています。作業終了後Alfredをちょっと立ち上げてAppleScriptを起動すればアップロードが完了するようにしました。(AppleScriptでgit pushしてgithub actionsでS3にアップロード)。この話はまた別でしたい。
メリット
- SPAなのでページ遷移はほぼ0秒
- 超優秀なMarkdownエディタTyporaの力を借りることができる
参考:https://qiita.com/4_mio_11/items/223326c3289f6b2c2a07
実際の記事にはどんなこと書いてんの?
クエスチョンバンク(QB)を解きながら、疑問に思った点を調べてMarkdownファイルにまとめる。国試の勉強は長期戦なので、1年後の自分に向けて書いてます。
スタイルに関しては、Typoraのテーマで使用されているcssファイルとBulmaを併用してます。記事をローカルで作成した時とほぼ同じ見た目で公開しつつ、ヘッダーなどを作る際はBulmaのコンポーネントを利用できるになっています。
チュートリアルから進化している点
S3のディレクトリ構成が完成品のブログにそのまま反映されています。説明が難しいですがサイトを一度巡回していただければ、意図が伝わるはず...
本当に手元で作成したフォルダがそのままwebサイトになるイメージです。
Next.jsのすごいところ
このwebサイト、markdownファイルの中身をNext.jsに渡してあげれば成立するので以下のような拡張もできると思います。
データの置き場所をS3からデータベースにする
Markdown形式で記事をアップロードできるwebアプリを作成してS3を介してつなぐ
メディアサイトのようなものを作成しようとすると、認証機能など難しい点も出てくるでしょう。しかし、ローカルで作成した文書をSPAとして公開できるサイトをこれだけ簡単に自分で1から作れてしまうのは、Next.js様様かな、と感じます。もちろんGitHub Pagesなどもっと楽な選択肢もありますが、SPAや自由にカスタマイズできるというメリットは十分あると思います。
個人的には自分で見返す際もページ遷移に時間をとられないのでストレスフリーで気持ちいいです。普段やる気にならない勉強も記事作成という遊び感覚でできるようになりましたし。
今後
現在は、ビルド時に全てのページを静的に作成しているので、記事を追加・変更する際は再ビルドが必要になります。
しかし最近、Next.jsは静的なwebサイトに動的なページ更新機能を搭載できるようになりました。Incremental Static Regenerationというやつです。この機能を使いたかったのですが、現在はバグが存在するようなので実現できませんでした。
Next.jsのレポジトリではこのバグに関するissueに最優先事項のラベルがつけられていたので、修正がきたら導入したいと思っています。これさえ導入できれば、Markdownファイルの保存から公開までがほぼ自動化できる...
補足
Incremental Static Regenerationについては以下のサイトの説明が超わかりやすいです。(英語ですけど...)
https://arunoda.me/blog/what-is-nextjs-issg
件のバグのissue
- 投稿日:2020-06-23T21:47:59+09:00
Reactの問い合わせフォームの作成
プログラミングの勉強日記
2020年6月23日 Progate Lv.146
React Ⅳ問い合わせフォームの作成
今回はContactFormというコンポーネントを作成して作る。
フォームのJSXはHTMLとは違う書き方をするので気を付ける。フォーム全体は
<form>
タグで囲む。inputタグは<input />
、textareaタグは<textarea />
と書く。送信ボタンHTML同様にinputタグを使い、type='subimit'
を指定する。表示名を変えたい場合にはvalue='表示名'
とする。例<form> <textarea /> <input type='submit' /> </form>送信完了メッセージの作成
フォームが送信されたかどうかはstateで管理する。そのためにisSubmittedという真偽値型のstateを用意する。falseのときはフォームをtrueのときは送信完了メッセージを表示する。なので、初期値はfalseである。
ContactForm.jsconstructor(props){ super(props); this.state={isSubmitted:false}; } ... render(){ let contactForm; if(this.state.isSubmitted){ contactForm= //送信完了メッセージのJSX(※()で囲む) }else{ contactForm= //フォームのJSX } ... return( <div>{contactForm}</div> ); ...onSubmitイベント
フォームが送信されたときに処理を実行するには、formのタグに対してonSubmitイベントを指定する。
<form onSubmit = [()=>{処理}}> ... </form>stateの値を更新するメソッドを作成して、フォームの送信時に呼び出す。
ContactForm.js//1.stateの値を更新するメソッドの定義 handleSubmit(){ this.setState({isSubmitted:true}); } ... render(){ //2.フォーム送信時にメソッドを呼び出す <form onSubmit={()=>{this.handleSubmit()}}> ...問い合わせフォームを作成する
ContactForm.jsimport React from 'react'; class ContactForm extends React.Component { constructor(props) { super(props); this.state = { isSubmitted: false, }; } handleSubmit(){ this.setState({isSubmitted:true}) } render() { let contactForm; if (this.state.isSubmitted) { contactForm = ( <div className='contact-submit-message'> 送信完了 </div> ); } else { contactForm = ( <form onSubmit={()=>{this.handleSubmit()}} > <p>メールアドレス(必須)</p> <input /> <p>お問い合わせ内容(必須)</p> <textarea /> <input type='submit' value='送信' /> </form> ); } return ( <div className='contact-form'> {contactForm} </div> ); } } export default ContactForm;
- 投稿日:2020-06-23T21:29:44+09:00
wasm-pack + WebWorker + react-scripts
前提
- 重い計算を Rust + WebAssembly でやる
- WebAssembly のパッケージは wasm-pack でビルドする
- WebAssembly は WebWorker で動かす
- アプリは React で書く
- アプリの設定を頑張りたくないので react-scripts (create-react-app) を使う
react-app-rewired
react-scripts では、WebWorker と WebAssembly のロードができないので設定する必要がある。
react-scripts で eject せずに設定を追加するために react-app-rewired を使う。worker-loader では WebWorker から WebAssembly を import できなかったので、workerize-loader を使う。
こんな感じで
config-overrides.js
を書く。config-overrides.jsconst path = require("path"); module.exports = function override(config, env) { config.module.rules.push({ test: /\.worker\.js$/, use: { loader: "workerize-loader" }, }); const wasmExtensionRegExp = /\.wasm$/; config.resolve.extensions.push(".wasm"); config.module.rules.forEach((rule) => { (rule.oneOf || []).forEach((oneOf) => { if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) { // Make file-loader ignore WASM files oneOf.exclude.push(wasmExtensionRegExp); } }); }); // Add a dedicated loader for WASM config.module.rules.push({ test: wasmExtensionRegExp, include: path.resolve(__dirname, "src"), use: [{ loader: require.resolve("wasm-loader"), options: {} }], }); return config; };これで拡張子が
.worker.js
のファイルを WebWorker として読み込めるようになる。
package.json
のscripts
を以下のように書いておく。package.json"scripts": { "build": "react-app-rewired build", "start": "react-app-rewired start" },WebWorker の実装
こんな感じで WebWorker を実装する。
example.worker.jsexport const twice = async (v) => { const { twice } = await import("example"); return twice(v); };
example
は wasm-pack で作られたパッケージで、dynamic import で読み込む。workerize-loader では、WebWorkerで呼び出せる関数を named export する。
async/await が使える。アプリの実装
いい感じにアプリ側を実装する。
workerize-loader で import したモジュールは関数になっていて、呼び出すと関数を取り出すことができる。
関数は Promise を返すようになっている。App.jsimport React, { useState } from "react"; import worker from "./hoge.worker"; const { twice } = worker(); const App = () => { const [value, setValue] = useState(1); return ( <div> <button onClick={() => { twice(value).then((result) => { setValue(result); }); }} > click me </button> <p>{value}</p> </div> ); }; export default App;実用例
凸包を計算して描画するプログラムを書いてみた。
- 投稿日:2020-06-23T16:37:42+09:00
Docker-compose ~volumeの罠~
はじめに
初投稿です。白菜と申します。プログラミングが趣味のしがない大学生です。先日コードを書いている最中に深めなツボにハマり、色々調べても関連する情報が出てこなかったので投稿させていただきます。
何が起こったのか
windowsを使っておりまして、wsl2が正式に導入されたと聞き、wsl2上でDocker-desktopを動かしてみようと思い立ちました。環境を整えてかれこれ一か月ほど遊んでいて、己のPCの環境を汚さずに様々な言語に触れられて、激アツやんと思っておりました。dockerで立ち上げたコンテナにvscodeのRemote Developmentを利用して接続し、コンテナ内でコードの編集・デバッグを行っていました。
しかし、問題発生
それはある日の暮れ、羅生門の下で雨やみを待ちながらコードを書いていた時のことでございます。springbootとかいう何某かがなんかとてもすごいつよいと聞いたので、試しておりました。日本語の公式チュートリアルのいくつかを軽く実装し、springMVCの基礎くらいはカンニングせずに書けるようになりました。調子に乗ってきたので、MySQLと連携させてデータベース処理やってみようと思い、dockerで環境を作りました。具体的には、
- javaコンテナ
- MySQLコンテナ
- phpmyadminコンテナ(データベース管理で楽するため)
の三つをdocker-composeで一つのネットワークとして作りました。ついでに書いたコード保存しときたかったので、volumeでテキトーなディレクトリをjavaコンテナ上にマウントしました。
しかしいざコードを書いてみると、データベースとの連携がうまくいきません。デバッグの度にデータベース接続エラーを吐き出します。コード自体はチュートリアルのほぼコピペなので、動かないはずがないのです・・・。これはコードじゃなくてdockerに原因があるんじゃないか?症状
上記以外にも、他のコンテナでも似たような症状が発生しました。以下はその一覧です。
- MySQLとの連携がうまくいかない
- というかおそらく連携用の設定ファイルの編集が反映されていない
- 手動で反映させたら上手くいった
- htmlを作成してコントローラと紐づけたのに、Not Foundと言われる
- React環境を作ったが、yarn startに一分以上かかる
- yarn start後、ファイルを編集してもブラウザに反映されない
共通しているのはファイルの編集・作成が反映されないということでした。
解決
色々実験してみたところ、dockerのvloumeに問題があるという結論に達しました。windows上のファイルをvolumeに指定した時に、volume内のファイルの変更がリアルタイムで反映されなくなるようです。なのでvolume指定しなけりゃいいというのも一つの解決ではあるのですが、コードを永続的に保存しておきたい場合、いちいちwindows上にコピーして持ってくるのは手間です。
volumeを使いつつ解決する方法があります。そもそもdocker for windows公式には以下のような記述があります。Store source code and other data that is bind-mounted into Linux containers (i.e., with docker run -v :) in the Linux filesystem, rather than the Windows filesystem.
「volumeマウントするファイルは、Windows上じゃなくてLinux上に置いといた方がいいよ!」
・・・・・・すみませんでした。
ちらっと見たことはあったんですけど、マウント自体はちゃんと機能してたし、別にWindows上でもよくね?と思っていたんです。まさかこんな変な不具合が出るとは思ってもいなかったんです。というわけで、wsl2のLinux上に作ったディレクトリをマウントしてReact環境を作り直したら解決しました。yarn startが20秒になったし、コードを変更したら逐一反映されるようになりました。Reactおもしれえ。
終わりに
結論、volumeでマウントするディレクトリはLinux上に作っておいた方がいいと思います。開発してる人たちが言ってるんだから多分間違いないです。我流でオラオラしようとしていた私が悪かったです。すみませんでした・・・。
公式ドキュメントはしっかり読まなきゃダメてことですね。
- 投稿日:2020-06-23T16:03:00+09:00
create-react-appでhot reloadが効かなくなった話
会津大学でプログラム書いてる学生です。
備忘録代わりにcreate-react-appでreact書いてた際にhot reloadが効かなくなった話をします。
もくじ
かんきょう
- ubuntu 18.04.4 LTS
- create-react-app 3.3.1
- react 16.13.1 くらい
あらすじ
久々にcreate-react-appでなんか作るか!と思いコーディング。
この際typescriptも入れよう!と思い途中からTypescriptを導入。
日をまたいで、さぁコーディングするかとnpm run start
したらホットリロードが効かないことに気づく。
なんかわからんけど効かない。
おそらく途中からtypescriptを導入したので、そのへんで色々あるのかなぁと予想。しこうさくご
ためしたもの
react-app-rewire-hot-loaderを導入
- react-app-rewire
- react-hot-loaderみたいなのも導入する必要があったっぽい
結果として「react-dev-utils/crossspawnがないぞ」って怒られてlocalhost立てられなかった。
解決方法は不明。create-react-appのプロジェクトを削除し、
--typescript
オプションで最初からtypescript対応プロジェクトにしたウキウキで
npm run start
してもホットリロードは効かず。
プロジェクトファイル消してもっかいつくれば大丈夫でしょ!とか思ったらそうでもなかった。たいおうさく
上手くいったのは環境変数を追加したらなんとかなりました。
参考記事に感謝。echo CHOKIDAR_USEPOLLING=true >> .env参考
Is it possible to get hot-reload with typescript working? #6503
react-app-rewire-hot-loader
vagrant上でcreate-react-appのhot-reloadが効かない場合の対応
- 投稿日:2020-06-23T13:53:23+09:00
Chefのチュートリアル
このチュートリアルでは、Chefについて学び、Chefを使ってAlibaba Cloud上でシンプルなReact.jsサイトを設定、構築、デプロイする方法を学びます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
前提条件
このチュートリアルに従うには、以下のものが必要です。
- 2つのAlibaba Cloud Elastic Compute Service (ECS)インスタンスがUbuntu 16.04でインストールされており、少なくとも2GBのRAMを持っています。これらのインスタンスのうち1つはChefノードに、もう1つはChefサーバに使用されます。また、これらのインスタンスでは、ポート22、80、443が開いていることを確認してください。
- Chefノードとサーバの両方に使用する完全修飾登録ドメイン(またはFDQN)。Alibaba Cloudドメインを購入するか、Freenomで無料で取得することができます。
Chefを知る
Chefはいくつかの異なるコンポーネントで構成されています。これらのコンポーネントを理解することが重要なので、ここではChefの3つの主要なコンポーネントを簡単に見ていきましょう。
- Chefサーバー:このコンポーネントは設定データのハブとして機能し、設定レシピ、cookbooks、ノードに適用されるポリシー、Chefによって管理されている各登録ノードを記述するメタデータがすべて保存される中心的な場所として機能します。また、このコンポーネントは、組織内の他のすべてのマシン(またはノード)がデプロイメント設定の目的で使用する中央マシンでもあります。
- Nodes:ノードの重要なコンポーネントは、物理的または仮想的なもので、Chefを使用して管理できるマシンと理解することができます。Chef-clientは各ノードにインストールされ、各ノードを希望の状態に設定するために使用されます。ノードはchef-clientを使用してchefサーバーと対話し、レシピ、テンプレート、ファイル配布などの設定情報を取得します。
- Workstation: Chef ワークステーションは、Chef の設定情報を作成または編集する場所です。設定ファイルはChefサーバーにプッシュされ、任意のノードにデプロイできるようになります。ワークステーションからChefサーバーとのやりとりは、knifeとchefコマンドラインツールを使用して行われます。
環境の設定
いよいよ実用的なことをする時が来ました。このチュートリアルでは、環境を設定し、chef を使って React.js アプリケーションを構築するために必要なツールをインストールします。
ワークステーションの設定
ワークステーションは基本的にはChefの設定の詳細をオーサリングする場所です。ワークステーションはあなたが選択したOSであれば何でも構いません。つまり、Linux、MacOS、Windowsの全てがここで動作することになります。
1.ChefDKパッケージをインストールします。Chef DK (開発キット)には、インフラストラクチャの開発とテストに必要なすべてのツールが含まれています。このチュートリアルを書いている時点では、現在の安定版(4.0.60)を使用しています。このリンクをクリックして、お使いのOSに基づいたChef DKをダウンロードしてください。
2.Chef DKをインストールしたことを確認し、コマンドラインからChef DKにアクセスできることを確認します。これを行うには、
chef —version
を実行してインストールを確認することができます。chef@workstation:~$ chef --version Chef Development Kit Version: 4.0.60 chef-client version: 15.0.300 delivery version: master berks version: 7.0.8 kitchen version: 2.2.5 inspec version: 4.3.2
- MacおよびLinuxユーザーの場合は、Chef開発キットに含まれているRubyのバージョンがデフォルトのRubyのバージョンとして設定されていることを確認する必要があります。これを行うには、以下の手順に従ってください。
- ターミナルを開き、
which ruby
を実行します。以下のような結果が得られるはずです。chef@workstation:~$ which ruby /usr/bin/ruby
chef shell-init
サブコマンドを使用して、ChefDKに含まれるRubyをシステムRubyとして設定する必要があります。ChefDKによって使用されるアプリケーションは、ワークステーション上にも存在する可能性のある他のRuby開発ツールから分離することができます。chef@workstation:~$ echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile && source ~/.bash_profile
zsh
、fish
、Windows PowerShell (posh) など、bash とは異なるシェルを使用している場合は、SHELL_NAME
をシェルに、SHELL_PROFILE
をシェルプロファイルに置き換えて、以下のコマンドを実行してください。chef@workstation:~$ echo 'eval "$(chef shell-init SHELL_NAME)"' >> ~/.SHELL_PROFILE && source ~/.SHELL_PROFILE
- もう一度
which ruby
コマンドを実行して、Chef開発キット版のrubyを使用していることを確認すると、以下のような出力が得られるはずです。chef@workstation:~$ which ruby /opt/chefdk/embedded/bin/ruby4.次に、ワークステーション用の
react-app-repo
という作業ディレクトリを作成する必要があります。このためにchef generate repo repo_name
コマンドを使用することになります。これにより、Chefが必要とするファイルやフォルダ構造が作成されます。chef@workstation:~$ chef generate repo react-app-repo && cd react-app-repo5.ワークステーションの設定が完了したので、Chefサーバーの設定と設定を行います。
Chefサーバーの設定
Chefサーバーを設定するには、以下の手順に従います。
1.ChefサーバーとしてUbuntu 16.04でインストールされたAlibaba Cloud ECSインスタンスをスピンアップし、ポート80、22、443が開いていることを確認します。クラウドでChefサーバを実行している場合は、セキュリティグループを通じてこれらのポートが開いていることを確認します。
2.Chefサーバーには、解決可能なドメインとホスト名が必要です。サーバーのホスト名がパブリックホスト名と一致していることを確認する必要があります。これは、以下のコマンドを実行することで可能です。
chef@chef_server:~$ echo YOUR_DOMAIN_NAME | xargs sudo hostname3.学習のために、このチュートリアルのために以下のbashスクリプトを作成しました。これはChef-serverパッケージをダウンロードしてインストールする際に役立つはずです。
- 以下のスクリプトをサーバ上のパス
/tmp/installChefServer.sh
にコピーしてください。chef@chef_server:~$ sudo vi /tmp/installChefServer.sh bash #!/usr/bin/env bash BOLD='\e[1m' GREEN='\e[92m' NC='\e[0m' updateLinuxPackages() { printf "${BOLD}${GREEN}=================================== Updating all packages ============================================ ${NC}\n" apt-get update } createDirectories() { if [ ! -d /creds ]; then mkdir /creds fi if [ ! -d /downloads ]; then mkdir /downloads fi } downloadAndInstallChefServer() { if [ ! -f /downloads/chef-server-core_12.19.26-1_amd64.deb ]; then printf "${BOLD}${GREEN}=================================== Downloading the Chef server package... ================== ${NC}\n" wget -nv -P /downloads https://packages.chef.io/files/stable/chef-server/12.19.26/ubuntu/16.04/chef-server-core_12.19.26-1_amd64.deb fi if [ ! $(which chef-server-ctl) ]; then printf "${BOLD}${GREEN}=================================== Installing Chef server =================================== ${NC}\n" dpkg -i /downloads/chef-server-core_12.19.26-1_amd64.deb chef-server-ctl reconfigure printf "${BOLD}${GREEN}=================================== Waiting for services ====================================== ${NC}\n" until (curl -D - http://localhost:8000/_status) | grep "200 OK"; do sleep 15s; done while (curl http://localhost:8000/_status) | grep "fail"; do sleep 15s; done printf "${BOLD}${GREEN}============================= Creating user ========================== ${NC}\n" # creating user format: chef-server-ctl user-create USER_NAME FIRST_NAME LAST_NAME EMAIL 'PASSWORD' --filename FILE_NAME chef-server-ctl user-create admin admin admin admin@example.com 'notsecure' --filename /creds/chefadmin.pem printf "${BOLD}${GREEN}============================= Creating oganization with user ========================== ${NC}\n" # creating org format: chef-server-ctl org-create SHORT_ORG_NAME 'FULL_ORG_NAME' --association_user USER_NAME --filename FILE_NAME chef-server-ctl org-create chef "Chef-learn, Inc." --association_user admin --filename organization-validator.pem printf "${BOLD}${GREEN}============================= Adding Web UI for chef ========================== ${NC}\n" chef-server-ctl install chef-manage chef-server-ctl reconfigure chef-manage-ctl reconfigure --accept-license fi printf "${BOLD}${GREEN}==================================== Your Chef server is ready! ================================== ${NC}\n" } main() { updateLinuxPackages createDirectories downloadAndInstallChefServer } main
このスクリプトでは、以下の情報を持つユーザーも作成します。
- ユーザー名: admin
- Firstname:admin
- Lastname: admin
- 電子メール: admin@example.com
- パスワード: notsecure
以下のコマンドを実行してスクリプトを実行可能な状態にします。
chef@chef_server:~$ sudo chmod u+x /tmp/installChefServer.sh
- 最後にスクリプトを実行します。少し時間がかかるかもしれません。
chef@chef_server:~$ sudo /tmp/installChefServer.sh4.ブラウザ上のChefのWebインターフェースにホスト名でアクセスできます。
ワークステーションがChef Serverと通信するように設定する
ワークステーションとChefサーバー間の通信を確立するために、すでにChefDKに含まれている
Knife
ユーティリティツールを利用します。基本的に、Knifeは、Chefサーバーを認証するために2つのファイルを必要とします。
knifeの設定ファイル
knife.rb
には、Chef サーバーの URL、RSA 秘密鍵(SSH 鍵)の場所、cookbookのデフォルトの場所などの情報が含まれています。RSA秘密鍵は、Chefサーバに送信されるすべてのリクエストを認証するために使用されます。公開鍵はChefサーバーが保持し、プライベート鍵はワークステーションが保持します。
ワークステーションとChefサーバー間の通信を確立するには、以下の手順に従ってください。
1.
knife configure
コマンドを実行して、knifeの設定を作成します。
YOUR-HOST-NAME
をchef-serverドメイン名に、SHORT-ORG-NAME
をchef
に置き換えます。また、クライアントキーを配置するための出力で指定されたパスをメモしておきます。chef@workstation:~$ knife configure WARNING: No knife configuration file found. See https://docs.chef.io/config_rb_knife.html for details. Please enter the chef server URL: [https://devops1c.mylabserver.com/organizations/chef]: https://YOUR-HOST-NAME/organizations/SHORT-ORG-NAME Please enter an existing username or clientname for the API: [user] admin ***** You must place your client key in: /home/user/.chef/chefadmin.pem Before running commands with Knife ***** Configuration file written to /home/user/.chef/credentials2.あなたの
react-app-repo
ディレクトリにknife.rb
ファイルを作成して、knife がcookbooks
の場所を知っていることを確認する必要があります。chef@workstation:~$ mkdir .chef && echo 'cookbook_path ["#{File.dirname(__FILE__)}/../cookbooks"]' >> .chef/knife.rbまた、
installChefServer.sh
スクリプトでユーザーを作成した時に作成したSSH鍵ファイルを、scp
コマンドを使ってchef-serverからワークステーションにコピーする必要があります。Note
~/.chef/admin.pem
はクライアントキーを置くために指定されたパスですが、knife configure
コマンドの出力で指定されたパスと異なる場合は変更してください。そして、以下の項目に置き換えてください。
IP-ADDRESS-OR-HOSTNAME
は、chef-serverのパブリックIPアドレス/ホスト名に置き換えます。
USER
はChefサーバーのユーザー名に置き換えてください。
PATH_TO_YOUR_SSH_KEY
は、Chefサーバの ssh-key へのパスに置き換えてください。chef@workstation:~$ scp -i PATH_TO_YOUR_SSH_KEY USER@YOUR-IP-ADDRESS-OR-HOSTNAME:/creds/chefadmin.pem ~/.chef/admin.pemあるいは、サーバへのアクセスを得るための認証手段としてパスワードを使用している場合は、以下のコマンドを実行することもできます。
chef@workstation:~$ scp USER@YOUR-IP-ADDRESS-OR-HOSTNAME:/creds/chefadmin.pem ~/.chef/admin.pem3.次に、以下のコマンドを使用してChefサーバーからSSL証明書を取得し、検証する必要があります。
chef@workstation:~$ knife ssl fetch WARNING: Certificates from www.mydomainname.com will be fetched and placed in your trusted_cert directory (/home/user/.chef/trusted_certs). Knife has no means to verify these are the correct certificates. You should verify the authenticity of these certificates after downloading. Adding certificate for www_mydomainname_com in /home/user/.chef/trusted_certs/www_mydomainname_com.crt
knife ssl check
コマンドを実行して、SSL構成を確認します。chef@workstation:~$ knife ssl check Connecting to host ec2-34-207-124-26.compute-1.amazonaws.com:443 Successfully verified certificates from ec2-34-207-124-26.compute-1.amazonaws.comこれでワークステーションの設定が完了し、knifeを使ってChefサーバーに接続できるようになりました。次のパートでは、ノードの設定を行います。
ノードの設定とブートストラップ
Chefで設定を管理する作業を開始する前に、作業するノードが必要になります。これを行うには、Ubuntu 16.04をインストールした別のECSインスタンスを作成し、ワークステーションから
Knife
とbootstrap
サブコマンドを利用します。ノードサーバを作成するだけで、ほとんどの作業はworkstation
から行われます。1.Ubuntu 16.04をインストールした別のAlibaba Cloudインスタンスを作成し、ポート80、22、443、3000が開いていることを確認します。react.jsアプリケーションはポート3000で実行されます。
2.以下のコマンドを実行して、ノードサーバのホスト名がパブリックホスト名と一致していることを確認する必要があります。
では、次のように置き換えます。
IP-ADDRESS-OR-HOSTNAME
をノードサーバのパブリック IP アドレス/ホスト名に置き換えます。ノードサーバ上のユーザの名前を持つ
USER
PATH_TO_YOUR_SSH_KEY
にノードサーバの ssh-key へのパスを指定します。chef@workstation:~$ ssh -i PATH_TO_YOUR_SSH_KEY USER@YOUR-IP-ADDRESS-OR-HOSTNAME 'echo YOUR_DOMAIN_NAME | xargs sudo hostname'3.ワークステーションから、新しいクラウドサーバーをChefサーバーが管理するノードにブートストラップするには、以下のコマンドを実行します。
以下では、
IP-ADDRESS-OR-HOSTNAME
をノードサーバのパブリックIPアドレス/ホスト名に置き換えます。ノードサーバ上のユーザの名前を持つ
USER
PATH_TO_YOUR_SSH_KEY
にノードサーバの ssh-key へのパスを指定します。
reactJS-node
でnode_name
を指定します。node_name
はノードに与えたい名前であることを理解してください。chef@workstation:~$ knife bootstrap IP-ADDRESS-OR-HOSTNAME --connection-user USER --sudo -i PATH_TO_YOUR_SSH_KEY --node-name NODE-NAME Bootstrapping 34.76.3.167 [34.76.3.167] -----> Installing Chef Omnibus (stable/15) [34.76.3.167] [34.76.3.167] downloading https://omnitruck.chef.io/chef/install.sh ...... [34.76.3.167] Getting information for chef stable 15 for ubuntu... [34.76.3.167] Installing chef 15 [34.76.3.167] [34.76.3.167] [34.76.3.167] Thank you for installing Chef Infra Client! For help getting started visit https://learn.chef.io [34.76.3.167] [34.76.3.167] Starting the first Chef Infra Client Client run... [34.76.3.167] [34.76.3.167] +---------------------------------------------+ [34.76.3.167] [34.76.3.167] 2 product licenses accepted. [34.76.3.167] [34.76.3.167] +---------------------------------------------+ [34.76.3.167] [34.76.3.167] Starting Chef Infra Client, version 15.0.300 [34.76.3.167] [34.76.3.167] resolving cookbooks for run list: [] [34.76.3.167] Synchronizing Cookbooks: [34.76.3.167] Installing Cookbook Gems: [34.76.3.167] Compiling Cookbooks... [34.76.3.167] [2019-07-01T06:52:36+00:00] WARN: Node reactJS-node has an empty run list. [34.76.3.167] Converging 0 resources ........ [34.76.3.167] Running handlers: [34.76.3.167] [34.76.3.167] Running handlers complete [34.76.3.167] Chef Infra Client finished, 0/0 resources updated in 02 secondsあるいは、サーバへのアクセスを得るための認証手段としてパスワードを使用している場合は、以下のコマンドを実行してください。
chef@workstation:~$ knife bootstrap IP-ADDRESS-OR-HOSTNAME -N NODE_NAME -x USER -P 'PASSWORD' --sudo4.自分のノードがChefサーバーに関連付けられていることを確認するには、
knife node list
コマンドを実行します。chef@workstation:~$ knife node list reactJS-node
knife node show
コマンドを実行することで、ノードのデータを見ることができます。knife node show NODE-NAMEchef@workstation:~$ knife node show reactJS-node Node Name: reactJS-node Environment: _default FQDN: ip-172-31-56-238.home.internal IP: 41.215.245.118 Run List: Roles: Recipes: Platform: ubuntu 16.04 Tags:React.jsアプリケーションの構築
chefサーバー、ワークステーション、ノードのセットアップが完了したので、 react.jsアプリケーションを構築する準備が整いました。以下のようなcookbookを書くことになります。
- node.jsのセットアップとインストール
- pm2をインストールします。
pm2
はプロセスマネージャーであり、react.js
アプリの動作を維持するのに役立ちます。
react.js
アプリケーションをインストールします。
react.js
アプリケーションを起動します。そのためにchef executeとbashリソースを使うことになります。これらのリソースはどちらもコマンドやスクリプトを実行するために使用します。
execute
リソースは単一のコマンドを実行するために、bash
リソースは複数行のコマンドを実行するために使用します。構文やプロパティの詳細については、execute リソースと bash リソースのドキュメントを参照してください。ワークステーションの
cookbooks/example/attributes/recipes
ディレクトリにあるdefault.rb
ファイルを開き、以下のように置き換えてください。bash 'Install Node.js' do cwd "/home/ubuntu" code <<-EOH curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh bash nodesource_setup.sh apt-get install nodejs -y EOH end execute 'Install pm2' do cwd "/home/ubuntu" command 'npm install pm2 -g' end execute 'Setup react app' do cwd "/home/ubuntu" command 'npx create-react-app my-app' only_if do ! File.exist?('/home/ubuntu/my-app') end end bash 'Start application' do cwd "/home/ubuntu" code <<-EOH cd my-app pm2 start npm -- start EOH endcookbookを実行するためには、Chefサーバーにアップロードする必要があります。このファイルに変更を加えるたびに、再アップロードする必要があることに注意してください。
react-app-repo
ディレクトリにあることを確認して、このコマンドを実行してください。chef@workstation:~$ knife upload cookbooks/example以下のコマンドを使用して、ノードの
run_list
にCookbookのrecipe
を追加する必要があります。chef@workstation:~$ knife node run_list add reactJS-node 'recipe[example]' reactJS-node: run_list: recipe[example]
run_list
の詳細はドキュメントで確認できます。さて、
knife ssh
コマンドを使ってreactJS-node
にcookbookをデプロイします。そして、以下のように置き換えてください。
USER
をノードサーバ上のユーザ名に置き換えてください。
PATH_TO_YOUR_SSH_KEY
にノードサーバの ssh-key へのパスを指定します。chef@workstation:~$ knife ssh 'name:reactJS-node' 'sudo chef-client' --ssh-user USER --ssh-identity-file PATH_TO_YOUR_SSH_KEYこれで、ブラウザのウィンドウに
http://NODE_SERVER_IP_ADDRESS:3000
を貼り付けて react.js アプリケーションにアクセスできるようになりました。このようなページが表示されるはずです。結論
このガイドでは、Chefを始める上での柔軟な基礎を解説しています。Chefの詳細については、Chefの公式ドキュメントを参照して、chef rallyを学ぶことからご覧ください。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-06-23T12:38:18+09:00
ApolloClient(React Hooks)でMutation後にQueryをRefetchする。
ApolloClientにて、
useMutation
でデータを更新した後にuseQuery
のデータを再取得する方法に関して
ざっと調べた結果です。useQueryのrefetch関数を利用する。
useQuery
関数の戻り値に含まれるrefetch
関数を実行することで、データの再取得ができます。
useMutation
関数が同一コンポーネント内、もしくはすぐ配下のコンポーネントならば、
こちらの関数を利用すれば事足ります。const { data, loading, error, refetch } = useQuery(ANY_GET_QUERY); const [update, { loading, error }] = useMutation(ANY_SET_QUERY, { onCompleted() { refetch(); }, });FETCHING DATA > Queries > Refetching - APOLLO DOCS
API > @apollo/react-hooks > useQuery > ResultuseMutationのrefetchQueriesオプションを利用する。
いくつかのWidgetを組み合わせた構成の画面などで、兄弟関係のコンポーネントのQueryをRefetchさせたい場合は、
useMutation
関数のオプション引数refetchQueries
が便利です。更新したいクエリ名を配列で渡すと、Mutation完了後に該当Queryを実行してくれます。
更新対象の可能性があるクエリ名を最大数記載しても、該当コンポーネントが無ければ
余分なクエリが実行されることはありません。/** * Widget A : リストの表示 */ const QUERY_A = gql` query QueryA { list(id: $id) { id name } } `; const { data, loading, error } = useQuery(QUERY_A); /** * Widget B : リストの表示 */ const QUERY_B = gql` query QueryB($id: ID!) { list(id: $id) { id date } } `; const { data, loading, error } = useQuery(QUERY_B); /** * Widget C : リストの更新 */ const [update, { loading, error }] = useMutation(QUERY_B, { refetchQueries: [ 'QueryA', 'QueryB' ], });単にクエリ名を渡すのみの場合、クエリの引数は前回のものがそのまま活用されます。
名前文字列の代わりにvariables
を指定したオブジェクトを渡すことも可能です。
配列の代わりにuseMutation
の結果を受け取る関数を渡すこともできます。const [update, { loading, error }] = useMutation(QUERY_B, { refetchQueries: ( mutationResult ) => { return [ 'QueryA', { query: 'QueryB', variables: { id: mutationResult.id } } ] }, });Updating after a mutation - APOLLO DOCS
useMutation API > Options - APOLLO DOCS
react-hoc API > options.refetchQueries - APOLLO DOCSonCompleat関数が呼ばれない
refetch
されたいくつかのクエリのうち、onCompleat
関数が呼ばれるものと呼ばれないものがありました。
今のところ原因は不明です。。。
useQuery
の戻り値のdata
はちゃんと新しくなっていたので、取り急ぎonCompleat
を利用せず、
代わりにReactのuseMemo
を活用することで対処しました。
(情報求ム)参考情報