20210429のNode.jsに関する記事は6件です。

【勉強】Next.jsで簡単な掲示板作成

はじめに 私はモダンな技術の実務経験が無いため、Javascriptを勉強しています。 この記事では以前、Next.jsを勉強した際に作成した簡易掲示板について記載しました。 なぜ掲示板か 教材に掲示板を選んだ理由は、初めての個人開発ということもあり、 CURD全ての機能が備わっている物が良かったからです。 個人的に勉強はしたいが何を題材にすればよいかわからない方におすすめです。 なぜNext.js? 数あるJavascriptのフレームワークの内、Next.jsを選んだ理由についてです。 どうしてもNode.jsを使いたかったので、それと相性がいいこととが第一条件で、 一番の決め手は知人に進められたからです。 個人開発なので使う技術は普段触れない物で良いと思うのですが、 今思えば無知な状態からNext.jsではなくReactを一通り学んだ後にNext.jsに触ればよかったです……。 実際に作った画面 機能 投稿表示 新規投稿 投稿削除 環境 名前 役割 scss デザイン全般 Next.js(React.js) フロントエンド Node.js サーバーサイド MySQL データベース GitHub https://github.com/okioka/NextBBS ※ローカルですが実際にPCで動かすこともできます。 感想 大変だったこと コンポーネント指向を理解することが難しかったです。 JavaServletでしかWebの開発をしたことがなかったことから、 今まではHTML、CSS、JavaScriptで分けて考えることが自分の中の常識としてありましたが、 コンポーネント指向では一つにして考えるので慣れるまで時間がかかりました。 モチベーションを保つ事が大変でした。 今回は小規模で終わりが見えていたのでモチベーションの維持ができましたが、 個人開発で大規模な開発をする時に、まずはどうやってモチベーションを 維持するか考えないといけないです。 やはり自分が好きなもの、本当に欲しいと思っている物を作ることが モチベーション保つ秘訣だと思いました。 学びがあったこと 今自分が触れている技術と比べて新しいので資料が少なかったです。 公式ドキュメントなどを見て調べる習慣がつきました。 調べてもわからないことは聞くべきだと思います。 仕事ではわからないことを聞くことは当たり前ですが、 個人的な勉強で聞くことをしていませんでした。 わからないことは知り合いに聞いたり技術書を読むとで解決することができました。 自分の考えだけで解決しようとするのではなく、 自分では思いつかないような考え方に日頃から触れるようにしましょう。 おわりに 最後まで読んでいただきありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

API Gateway + LambdaでCSVデータ取得のWebAPIを作る [Node.js]

はじめに 本記事では、「API Gateway」と「Lambda」を使って、「ブラウザからCSVアップロード→データ取得する」までをテーマにまとめています。 あまりLambdaを触ったことがないという人にもわかりやすいように画像多めに載せてみました。 Wantedyストーリー記事 の内容をこちらのQiitaに記載しています。 やりたいこと やりたいことの流れとしてはこんな感じです。 ① クライアント側でCSVファイルをアップロード ② URLを叩いて、API Gatewayにアクセス ③ Lambda発火 ④ LambdaがアップロードされたCSVからデータを取得する 図を書くまでもないかもしれないですが、一応このような感じですね。 Lambdaの前準備 Lambdaのコードを乗せる箱をAWS上に作ります。Lambdaのコンソール画面から任意の関数名をつけて新しく関数を作成してください。今回VPCに入れる必要はないので、詳細設定は特に設定せずに作成しておきます。 ランタイムはNode.js 14.xを選択しました。 API Gateway 以下、API Gatewayの設定です。今回はREST APIで作っています。 アクションのプルダウンからメソッド「POST」を作成します。Lambdaプロキシ統合を使用しています。リージョンと作成したLambda関数を指定して「保存」をクリックします。 メソッドレスポンスのHTTPステータスにはデフォルトで「200」しか設定されていませんので、「400」「500」も追加してあげましょう。 ※OPTIONSメソッドが自動で作成されます。これはCORS設定で必要なメソッドのため消さずにこのままにしておきます。 CORS参考リンク: REST API リソースの CORS を有効にする バイナリメディアタイプの設定 クライアント側からはCSVファイルを添付して、multipart/form-data形式でフォームデータを送信します。 上記までのAPI Gatewayの設定のままではバイナリデータを受け取れません。 別途設定してあげる必要があります。 「設定」をクリックしたら、「バイナリメディアタイプ」にmultipart/form-dataを入力します。 追加して、任意のステージにデプロイしたらAPI Gatewayの設定は完了です。 Lambda関数のコンソール画面で、作成したAPIエンドポイントが紐付いているのを確認してください。 Lambda multipart/form-data形式のパラメータを受け取り、CSVデータを取得するコードの記述例を載せます。 自前でmultipart/form-dataやCSVをパースしたりするのは大変です。 そこで以下ライブラリを使用しました。 lambda-multipart-parser csv-parse encoding-japanese lambda-multipart-parserは、イベントで受信したmultipart/form-dataのbodyをパースしてファイルデータとテキストデータを以下のようなJSON形式にしてくれます。 { files: [ { filename: 'test.pdf', content: <Buffer 25 50 6f 62 ... >, contentType: 'application/pdf', encoding: '7bit', fieldname: 'uploadFile1' } ], field1: 'VALUE1', field2: 'VALUE2', } ライブラリ「csv-parse」は、Windows, Apple, Linuxそれぞれの改行コードを自動認識してくれるので便利です。 エンコードライブラリを入れたのは、CSVファイルの文字コードにUTF-8(BOM付・BOM無)、Shift-JIS、EUC-JP等が存在するからです。 ライブラリの「csv-parse」にもエンコードするオプションがついていますが、日本語特有のEUC-JPには対応していない等、これだけに頼るのはちょっと心配です。日本語のあらゆる文字コードに対応した「encoding-japanese」で「csv-parse」で対応する文字コードに変換(今回はUTF-8)してあげてから、CSVデータをパースするようにします。 今回は、アップロードしたCSVの中身のデータをクライアント側にレスポンスとして返してあげます。 'use strict' const parser = require('lambda-multipart-parser'); const parse = require('csv-parse/lib/sync'); const Encoding = require('encoding-japanese'); exports.handler = async(event, context) => { // 返却するレスポンスのステータスコード初期値は500にしておく const res = { statusCode: 500, headers : { // API Gateway CORS有効時には以下のヘッダーリストが必要 "Access-Control-Allow-Headers" : "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "OPTIONS,POST" } }; try{ console.log(`Function ${contxt.functionName} started.`); // multipart/form-data形式のパラメータをパース const req = await parser.parse(event); const params = { file: req.files[0].content, text: req.text // file以外のパラメータがあればこのように取得する } console.log(`エンコードを開始します...`); const detected = Encoding.detect(params.file); // 文字コード自動検出 console.log(`アップロードファイルの文字コードは${detected}です`); const convertedFile = Encoding.convert(params.file, 'UTF8', detected); // UTF8へ変換 const data = Buffer.from(convertedFile); // 変換後に文字コード配列になっている為、Bufferに戻す console.log(`エンコードが完了しました`); console.log(`CSVデータのパースを開始...`); const records = parse(data, { delimiter: ",", // カンマ区切り trim: true, // フィールド値に空白がある場合に無視 bom: true, // UTF8の場合にBOM有無判定 skip_empty_lines: true, // 空行があった場合は、読込をスキップする from_line: 1 // 行の読み込み開始行を指定(今回は1行目固定) }); const responseBody = { records: records, message: params.text }; console.log(`Function ${context.functionName} end.`); res.statusCode = 200; res.body = JSON.stringify(responseBody); return res; }catch(err){ console.error(err, `Function ${context.functionName} abend.`); res.body = JSON.stringify({ message: err.message }); return res; } } 梱包ファイル 今回ライブラリを使用しているので、コード単体では動作しません。 モジュールを含めてzip化してからLambdaにアップロードします。 $ yarn init (もしくは npm init) initできたら、各ライブラリをyarn add もしくはnpm installでインストール ディレクトリファイルを一覧化しました。(参考までに) tree -L 1 . ├── index.js ├── node_modules ├── package.json └── yarn.lock 1 directory, 3 files 作業しているディレクトリ配下でアップロード用にzip化するコマンドを入力してください。 (今回は動作を確認するだけなので、webpackは使用しません) $ zip -r src.zip index.js node_modules/ 同じ階層にzipファイルができているはずです。それをLambdaのコンソール画面でアップロードします。 HTMLでアップロード画面作成 クライアント側からファイルをアップロードできるように画面を作ります。 今回はVue.jsとaxiosを使って、API GatewayのエンドポイントURLに向けてPOSTを投げます。あまりに画面がシンプル過ぎたので、ボタンと入力フォームだけelemental-uiで中央寄せするスタイルを少しあてています。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>CSV Uploader</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js"></script> <link rel="stylesheet" href="./style.css"> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> </head> <body> <div id="app"> <div class="wrapper"> <form> <input type="file" id="file" ref="file" @change="handleFile" class="input"/><br> <el-input type="text" v-model="message" placeholder="edit me!"></el-input> <el-button type="primary" round @click="uploadFile" class="sendBtn">送信</el-button> </form> </div> </div> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <script type="text/javascript"> const vm = new Vue({ el: "#app", data() { return { file: '', message: '' } }, methods: { handleFile() { this.file = this.$refs.file.files[0]; // アップロードファイルをセット }, uploadFile() { const formData = new FormData(); formData.append('file', this.file); formData.append('text', this.message); axios.post('API GatewayのエンドポイントURL', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(res => { this.message = ""; console.log("Success!"); console.log(res.data.records); console.log(res.data.message); }).catch(err => { console.log(`Failed... ${err}`); }) } } }) </script> </body> </html> アップロード画面 CSVファイルアップロード こんな感じのランダムなデータで生成されたCSVファイルを用意しました。 ちなみにこのファイルの文字コードはShift-JISです。 メッセージ付きで送信してみます。 レスポンスの中身をconsole.logで出しているので、Chromeのデベロッパーツールで見てみます。「Success!」というログのあとに沢山の配列データと、入力して送信したメッセージ「てすと」が表示されています? 違うメッセージを入力してもう一回送信してみます。配列データの中身も見てみると CSVの中のデータが返ってきているのを確認できました^^ 文字コードがちゃんと認識されていたか確認するには、Lambdaの方でログを出していたのでCloudWatchのログイベントを見てみます。 Shift-JISのファイルがちゃんと、SJIS(Shift-JIS)として認識されていますね? さいごに 今回は、Lambdaで取得したデータをそのままクライアント側へ返すだけでしたが、DBに登録したり、S3バケットにPutしてクライアントからダウンロードできるようにしたりと取得したあとにできることの幅は色々あります。 パースする箇所だけ変えれば、Excelからも同じようにデータを取得できます。 サーバーレスのいいところは、1機能をWebAPIとしてさくっと作れるところです。 今後もサーバーレスでできることを紹介していけたらと思います?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Firebase】Next.jsのアプリケーションがdeploy後に動かなくなった問題への対応

探してもコレといったものが見つからなかったので、未来の自分への備忘録と、同じ問題に悩んでる人がもしいたら参考になれば幸いですという思いを込めて。 環境 以下を使用したアプリケーション構成。 Firebase Hosting/Functions Next.js 事象 ある日、deployしたWebアプリケーションがエラーを吐いて動かなくなった。 エラーは以下。(Cloud Functionsのログに出力されていた) Error: Cannot find module '/workspace/.next/server/font-manifest.json' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15) at Function.mod._resolveFilename (/workspace/node_modules/next/dist/build/webpack/require-hook.js:4:1784) at Function.Module._load (internal/modules/cjs/loader.js:562:25) at Module.require (internal/modules/cjs/loader.js:692:17) at require (internal/modules/cjs/helpers.js:25:18) at requireFontManifest (/workspace/node_modules/next/dist/next-server/server/require.js:1:1723) at new Server (/workspace/node_modules/next/dist/next-server/server/next-server.js:3:729) at NextServer.createServer (/workspace/node_modules/next/dist/server/next.js:1:2935) at process._tickCallback (internal/process/next_tick.js:68:7) 対応 実際のところ原因はわかってないのだが、Cloud FunctionsのランタイムのNode.jsのバージョンを10→12に変えてdeployしたら直った。 firebase.jsonのfunctions.runtimeのところを修正すればよい。 ... "functions": { "source": ".", "predeploy": [ "npm --prefix \"$PROJECT_DIR\" install", "npm --prefix \"$PROJECT_DIR\" run build" ], "runtime": "nodejs12" ←ここを"nodej10"から"nodejs12"に変更した } ... firebase initで、functions選んでた場合、Cloud Funtionsのランタイムのデフォルト値がNode.js 10になるようなので(少なくともfirebase initしてから変えたことはなかった)、FirebaseでNext.jsのアプリケーションを組む場合は注意したほうが良いかと。 関連 似たようなエラーが発生した事例として、2019年頃のissueで取り扱われているものがある。 https://github.com/vercel/next.js/issues/6287 ※このissueの事例は「pages-manifest.jsonが見つからない」のに対し、私の事例は「font-manifest.jsonが見つからない」なので、同じエラーというわけではない。単にググってひっかかった似たエラーの事例というだけである ここでのやり取りを見る限り、以下のようなことをやったら(+.nextディレクトリ消してnext buildを再度実行)解決した、と書かれている。 - next.config.jsのserverless:trueを削除 - getInitialPropsにasyncを付けていなかったので付けた ただ私の例だとnext.config.jsにはもともとserverless:trueの設定は書いてなかったし、getInitialpropsも使ってなかった(getStatisPropsとかgetServerSidePropsは使ってたけどそっちはちゃんとasync付けてた)ので、やはり厳密に同じ事例ではないらしい。 まあ2019年の事例だしね。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

browserify中にソースコードを文字列置換で書き換えるbrowserify-sed

node.js 向けのファイルを束ねてブラウザで実行できるようにする browserify で、node.js 用の通常コードとブラウザ用コードで一部の記述を変えたいときに使えるプラグイン browserify-sed を書いてみたので紹介します。 私は軽量に make でビルドする派なので CLI では以下のように使います。 browserify src/index.js -o build/bundle.js \ -t [ browserify-sed "s/__VERSION__/1.2.3/g" ] ↑の例では、ソースコード中の __VERSION__ という文字列をすべて 1.2.3 に置き換えています。 以前は perl -i -pe や sed -i でソースコード書き換えをしていたので、それと同じ sed 書式になっています。perl で慣れてる人には読みやすいはず。既存 Makefile もコピペで切替えできた。 なお perl や sed は行単位のストリーミング置換なのに対して、 browserify-sed はファイル全体をマッチさせる仕組みなので、 複数行に渡る置換もできます。 逆に、行単位で、行頭・行末でマッチさせたいときは mg フラグを付けて下さい。 browserify src/index.js -o build/bundle.js \ -t [ browserify-sed "s#^(exports.*? = void 0)#// $1#mg" ] ↑は TypeScript が関数とかを exports するときに定義前にいちど void 0 で先行初期化するコードを吐くのを削除するものです。たいてい要らない。 複数の置換を行うときは、; で並べます。 # ; で並べる browserify src/index.js -o build/bundle.js \ -t [ browserify-sed "s/foo/FOO/g; s/bar/BAR/g;" ] # たぶん下記でも OK browserify src/index.js -o build/bundle.js \ -t [ browserify-sed "s/foo/FOO/g" "s/bar/BAR/g" ] browserify src/index.js -o build/bundle.js \ -t [ browserify-sed "s/foo/FOO/g" ] -t [ browserify-sed "s/bar/BAR/g;" ] 事前に browserify 本体と browserify-sed を準備して下さい。 npm install browserify browserify-sed 20行くらいの短いコード なので、特定のファイルのみを置換対象に絞るとかの細かなオプションは、実装していません。 macOS の sed は GNU でないので -i に対応していなかったり、 Alpine など Docker の軽量イメージでは perl が入っていなかったり、 ときどき面倒なことがあった。 browserify-sed を使えば node だけでビルドが完結できて便利になりそう。 なお s/foo/bar/ の文字列置換処理(置換関数へのコンパイル)の実装は別モジュール sed-lite.ts です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GWに向け簡単にオリジナル旅程サイトを作成

はじめに みなさんこんにちは、新型コロナウイルスのせいで楽しみにしていたGWどこにも出かけることができなく1日PCと向き合っていますOzoraです。 家にいても暇なのでGithub pageとGatsbyを使って簡単にオリジナルの旅程をまとめたページを公開できるレポジトリをGithubで公開しました。 ただ旅程サイトを作っても退屈ですので、Github actionで、pushからだけでなく旅行先からスマホで直接githubのWebページから編集し、自動でデプロイされるような構成にしてみました。 これを機にGithub Actionを今まで使ったことがない人はぜひぜひ体験してみてください〜 自分が作成したサイトのサンプルはこちらでご覧いただけます。 使い方 基本的にはレポのREADMEに記載していますが、こちらでも説明すると、 https://github.com/ozora-ogino/gatsby-trip-plan をForkします ローカルにクローンして/content/blogに旅行予定をMarkdownファイルで作成 Github Access Tokenを作成してレポジトリの設定欄のSecretsにGH_TOKENという名前で設定します git push というような流れになります。 旅行先からスマホで自分専用の旅行予定がまとまったサイトがあれば便利ですし、何より友達や家族にドヤ顔できますのでぜひ利用してみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vscodeでnode.js開発始める環境作り-Remode-Container

Remote-Containerって便利 Lambda作るときにサクッとローカル環境つくりたかった。そしてローカル汚したくないのでDocker使おうと思いました。 1.ファイルコピー 予め作っておいた.devcontainerを作業ディレクトリを作ったらコピーする $ tree .devcontainer .devcontainer ├── Dockerfile └── devcontainer.json 内容は今のところシンプル。好きに育てればよいです。 Dockerfile FROM node:14 RUN set -x .devcontainer.json { "name": "Existing Dockerfile", "context": "..", "dockerFile": "./Dockerfile", "settings": { "terminal.integrated.shell.linux": null }, "extensions": [ "oderwat.indent-rainbow", "ionutvmi.path-autocomplete", "chrmarti.regex", "wayou.vscode-icons-mac", "alefragnani.bookmarks", "humao.rest-client" ] } vscode操作 [><]からReopen in Container 選んで実行 完成 あとは、npm init 使えるようになってるので、どんどん作っていけばいいです。 ローカルでバージョン管理とかやめれるのが良いのかなーと思っています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む