ゆずめも

メモ的なブログです。主に勉強した事について書いてます。

素振り環境にparcelのご提案

最近Reactを素振りするための環境として、前から話題になってたparcelを使ってみたらとても簡単に動作環境作れたのでその紹介

ja.reactjs.org

parceljs.org

githubに今回のコード等すべて置いといたので、読むの面倒な人はそちらで

github.com

環境作成と依存ライブラリインストール

前提としてnode.jsが動作する環境を作っている想定で話して行きます

適当にプロジェクトを作って、npmやyarnを使って以下のものをインストールする

# プロジェクトディレクトリ作成
mkdir test_proj
cd test_proj

# npm
npm init -y
npm i react react-dom
npm i -D parcel

# yarn
yarn init -y
yarn add react react-dom
yarn add -D parcel

srcディレクトリ等を作る

# ディレクトリ作成
mkdir src
mkdir view

# ファイル作成
touch src/app.js
touch view/index.html

Reactのコードを書く

雑に"Hello World"を表示するReactのコンポーネントを作る

// src/app.js
import React from 'react'
import ReactDOM from 'react-dom'

function App() {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app')

読み込むhtmlを作る

さっき作ったReactのコードを読み込むhtmlファイルを作る

ここで注目するポイントは<script>タグでエントリーポイントのファイルを指定している部分で、parcelでビルドするといい感じにブラウザで動く状態に変換してくれる

<!-- view/index.html -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>React Sample</title>
</head>
<body>
  <div id="app"></div>
  <script src="../src/app.js"></script>
</body>
</html>

動かしてみる

作成したプロジェクトを動かしてみる

# npm
npx parcel view/index.html

# yarn
yarn run parcel view/index.html

上のコマンドを実行するとlocalhost:1234でサーバーが立ち上がり、"Hello World"が表示される

まとめ

ちょっと動かしたいだけなのにwebpackの設定面倒だなーと思ってたので、雑に試すならparcel最高だなと思った

まだ素振りと、ラズパイで動いてる雑なwebシステムにしか使ってなくてあんまりわかってないんだけど、一応productionコンパイル*1とかもできるみたいなのでちょっとずつ使ってみようと思ってる

reactのlazy load & suspenseを試してみた

ちょっとずつしか手が出せてなかったReact.jsをニートになったのを気に学び直している
その過程でReact.lazyとSuspense`をwebpackで試したのでそのログ

reactjs.org

tl;dr

コード自体はここに全部おいてある

github.com

動作チェック

動かすための方法はREADME.mdに書いてあるので、そちらを参照していただくとして
実行してページを開くと一瞬「Loading...」という文字が表示され、lazyロードしたComponentが読み込まれると「Happy Birthday Nogizaka46」*1という文字が表示されます

解説

パッケージについて

基本的には上記のgithubにおいてあるコードのpackage.jsonを見てもらうとして

今回dynamic importをしているので、babelでそれを扱うプラグインをインストールしている

babeljs.io

プロジェクトコード

componentをロードするときにReact.lazy(() => import(''))としてると、ファイルが分割されlazyロードすることができる

これで読み込んだcomponentを<Suspense>で囲うことで、dynamic import*2が読み込まれるまではfalllbackプロパティで指定した要素(今回の場合は「Loding...」という文字列)が表示され、ロードが終わるとcomponentが普通にレンダリングされる

import React, { Suspense } from 'react'

const Nogi = React.lazy(() => import(/* webpackChunkName: "Nogi" */'./Nogi'))

export default function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <Nogi />
      </Suspense>
    </div>
  )
}

react-split-sample/App.js at master · yuzu-sandbox/react-split-sample · GitHub

まとめ

個人でやってるもののほんの一部に使っているだけで、Reactを仕事で使ったことがほぼなく、lazy loadが求められるほどパフォーマンスセンシティブなものを作ってないので、この対応がどこまで通用するのかはわからないがかなり簡単にコード分割が実現できるのでよかった

ただwebpackのこの辺↓と組み合わせるとどうなるのか気になるところなので、今度試したい

webpack.js.org

*1:お察しください https://twitter.com/yuzu_441/status/1098781354710294528

*2:要するにPromise

Goのnet/httpパッケージを使ったAPI開発を素振りしてた

最近調査を兼ねてgolang触ってみてるのでメモがてらgoでのhttp処理の書き方をまとめる

Goのnet/httpパッケージの仕組み

まだ全然詳しくないので、雑に言うとhttp.Handlerを定義し、それをパスと関連を付ける事によってルーティングされて実行される

例えば

package main

import (
  "fmt"
  "net/http"
)

func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello World")
  })
  
  http.ListenAndServe(":8080", nil)
}

これでgo run等で実行すると以下のようにcurlで実行できるようになる

curl -v 'http://localhost:8080'

POST等の判別

リクエストのメソッド(GET, POST等)を判断するためにはhttp.RequestMethodプロパティを参照すればいい

例えばGETかそれ以外かを見分けるならこんな感じ

if r.Method == http.MethodGet {
  fmt.Fprintln(w, "Get Method")
} else {
  fmt.FPrintln(w, "Other Method")
}

POSTでForm valueを取得する

POSTメソッドにFormの形式で送る

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintln(w, r.FormValue("nogizaka"))
    })

    http.ListenAndServe(":8000", nil)
}

これでcurlで"nogizaka=maiyan"をPOSTすると「mayiyan」が返ってくる

curl -v -X POST -F "nogizaka=maiyan" 'http://localhost:8000'

JSONをPOSTする

web application作ってるとよくあるjsonを投げて、それを解釈してJSONを返す*1

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

// jsonのSchema
type InputJsonSchema struct {
    Name string `json:"name"`
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    // request bodyの読み取り
        b, err := ioutil.ReadAll(r.Body)
        if err != nil {
            fmt.Println("io error")
            return
        }

        // jsonのdecode
        jsonBytes := ([]byte)(b)
        data := new(InputJsonSchema)
        if err := json.Unmarshal(jsonBytes, data); err != nil {
            fmt.Println("JSON Unmarshal error:", err)
            return
        }
        fmt.Fprintln(w, data.Name)
    })

    http.ListenAndServe(":8000", nil)
}

これでcurlを投げるとnameプロパティに設定したものが返ってくる

curl -v -X POST -d '{"name": "乃木坂"}' 'http://localhost:8000'

まとめ的なもの

ちょこちょこ軽いapiなら'net/http'だけで作るみたいなの見たことあった気がしたので挑戦してみたけど、流石に何かしらweb framework入れて開発したほうがいい気はした

まだ配列操作*2とかDBへの処理軽く見ただけで実際に動かせてないのでそこらへんやったら何か作れそう

*1:Content-Typeはifで分けるだけっぽいので無視してる

*2:厳密にはスライス操作かな