「Elixir/Phoenix初級(1)はじめの一歩」を読みました

Phoenixがわからないせいで個人開発がストップしたのでお勉強していきます。

Elixir/Phoenix 初級?: はじめの一歩 (OIAX BOOKS)

Elixir/Phoenix 初級?: はじめの一歩 (OIAX BOOKS)

成果物はこちら → c18t/hello-phoenix

TOC

  • はじめに
  • 01: Elixir/Phoenixへの誘い
  • 02: 各種ソフトウェアのインストール
  • 03: Elixirの初歩
  • 04: 基本データ型
  • 05: Hello, world!
  • 06: 経路設定の初歩
  • 07: コントローラとアクション
  • 08: HTMLとテンプレート
  • 09: パラメータ
  • 10: HTML文書の区分とスタイルシート
  • 11: BootstrapとFont Awesome
  • 12: モジュールと関数
  • 13: リストとタプル
  • 14: マップとキーワードリスト
  • 15: ビューモジュール
  • 16: ページ間のリンク
  • 17: 画像
  • 付録A: Chromeデベロッパーツール
  • 付録B: ベンチマークの計測
  • 付録C: Homebrewのインストール
  • 付録D: Node.jsのインストールと更新
  • 付録E: 本番モード(prod環境)

はじめに

  • 本書の対象はWebアプリ開発にはじめて挑戦する人
    • マジか。ElixirでWebアプリ開発の学習を初めてやる人なんてどれくらいいるんだ…
  • 第1巻では下記のテーマは扱わない
    • パターンマッチング
    • パイプ演算子
    • 再帰
    • 並行プログラミング
  • OIAX BOOKS『Ruby on Rails 5.0 初級①』をベースに、内容をElixir/Phoenix向けに書き直しているため、本文にかなりの重複がある
    • なるほどそれで対象読者がそうなったのか
  • ソフトウェアのバージョンはガンガン無視していきます

01: Elixir/Phoenixへの誘い

02: 各種ソフトウェアのインストール

割愛。Hex, rebar, Phoenixをインストールしました。

03: Elixirの初歩

お試しのスクリプト

n = 1
n = n + 1
IO.puts n

Erlangでは変数に再代入できなかったけど、Elixirでは可能。参照が差し替わるだけだからやらかしは起きないはず。

$ elixir primer/v01/ch03/variable.exs
2
  • IOはモジュール。
  • .putsは関数。関数のカッコは省略可能。
  • 式の終端は改行またはセミコロン
  • #以降はコメント
  • =begin ... =endで複数行コメント
    • 丸っきりRubyだ。

04: 基本データ型

割愛。整数、文字列、アトム。

Hello, world!

$ mix phoenix.new modest_greeter --no-ecto
* creating modest_greeter/config/config.exs
* creating modest_greeter/config/dev.exs
* creating modest_greeter/config/prod.exs
* creating modest_greeter/config/prod.secret.exs
* creating modest_greeter/config/test.exs
* creating modest_greeter/lib/modest_greeter.ex
* creating modest_greeter/lib/modest_greeter/endpoint.ex
* creating modest_greeter/test/views/error_view_test.exs
* creating modest_greeter/test/support/conn_case.ex
* creating modest_greeter/test/support/channel_case.ex
* creating modest_greeter/test/test_helper.exs
* creating modest_greeter/web/channels/user_socket.ex
* creating modest_greeter/web/router.ex
* creating modest_greeter/web/views/error_view.ex
* creating modest_greeter/web/web.ex
* creating modest_greeter/mix.exs
* creating modest_greeter/README.md
* creating modest_greeter/web/gettext.ex
* creating modest_greeter/priv/gettext/errors.pot
* creating modest_greeter/priv/gettext/en/LC_MESSAGES/errors.po
* creating modest_greeter/web/views/error_helpers.ex
* creating modest_greeter/.gitignore
* creating modest_greeter/brunch-config.js
* creating modest_greeter/package.json
* creating modest_greeter/web/static/css/app.css
* creating modest_greeter/web/static/css/phoenix.css
* creating modest_greeter/web/static/js/app.js
* creating modest_greeter/web/static/js/socket.js
* creating modest_greeter/web/static/assets/robots.txt
* creating modest_greeter/web/static/assets/images/phoenix.png
* creating modest_greeter/web/static/assets/favicon.ico
* creating modest_greeter/test/controllers/page_controller_test.exs
* creating modest_greeter/test/views/layout_view_test.exs
* creating modest_greeter/test/views/page_view_test.exs
* creating modest_greeter/web/controllers/page_controller.ex
* creating modest_greeter/web/templates/layout/app.html.eex
* creating modest_greeter/web/templates/page/index.html.eex
* creating modest_greeter/web/views/layout_view.ex
* creating modest_greeter/web/views/page_view.ex

Fetch and install dependencies? [Yn]
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build

We are all set! Run your Phoenix application:

    $ cd modest_greeter
    $ mix phoenix.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phoenix.server

modest_greeterプロジェクトが出来たので動かしてみる。

$ cd modest_greeter
$ mix phoenix.server

12:22:04.503 [info]  Compiling file system watcher for Mac...

12:22:06.052 [info]  Done.
==> file_system
Compiling 7 files (.ex)
Generated file_system app
==> gettext
Compiling 1 file (.yrl)
Compiling 1 file (.erl)
Compiling 20 files (.ex)
Generated gettext app
===> Compiling ranch
warning: String.strip/1 is deprecated, use String.trim/1
  /Users/private/Projects/github.com/c18t/hello-phoenix/modest_greeter/deps/poison/mix.exs:4

==> poison
Compiling 4 files (.ex)
warning: Integer.to_char_list/2 is deprecated, use Integer.to_charlist/2
  lib/poison/encoder.ex:173

Generated poison app
==> phoenix_pubsub
Compiling 12 files (.ex)
Generated phoenix_pubsub app
===> Compiling cowlib
src/cow_multipart.erl:392: Warning: call to crypto:rand_bytes/1 will fail, since it was removed in 20.0; use crypto:strong_rand_bytes/1

===> Compiling cowboy
==> mime
Compiling 1 file (.ex)
Generated mime app
==> plug
Compiling 1 file (.erl)
Compiling 48 files (.ex)
warning: function :cowboy_stream_h.data/4 is undefined (module :cowboy_stream_h is not available)
  lib/plug/adapters/cowboy2/stream.ex:9

warning: function :cowboy_stream_h.info/3 is undefined (module :cowboy_stream_h is not available)
Found at 2 locations:
  lib/plug/adapters/cowboy2/stream.ex:13
  lib/plug/adapters/cowboy2/stream.ex:21

warning: function :cowboy_stream_h.init/3 is undefined (module :cowboy_stream_h is not available)
  lib/plug/adapters/cowboy2/stream.ex:5

Generated plug app
==> phoenix_html
Compiling 8 files (.ex)
Generated phoenix_html app
==> phoenix
Compiling 74 files (.ex)
warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/phoenix/endpoint/handler.ex:39

warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/mix/tasks/phoenix.gen.model.ex:155

warning: Enum.partition/2 is deprecated, use Enum.split_with/2
  lib/mix/phoenix/schema.ex:234

warning: Plug.Conn.WrapperError.reraise/3 is deprecated. Use reraise/1 or reraise/4 instead.
Found at 2 locations:
  lib/phoenix/controller/pipeline.ex:138
  lib/phoenix/router.ex:280

Generated phoenix app
==> phoenix_live_reload
Compiling 4 files (.ex)
Generated phoenix_live_reload app
mix phoenix.server is deprecated. Use phx.server instead.
==> modest_greeter
Compiling 11 files (.ex)
warning: Plug.Conn.WrapperError.reraise/3 is deprecated. Use reraise/1 or reraise/4 instead.
Found at 2 locations:
  web/router.ex:4
  web/router.ex:12

Generated modest_greeter app
[info] Running ModestGreeter.Endpoint with Cowboy using http://0.0.0.0:4000
12:22:20 - info: compiled 6 files into 2 files, copied 3 in 815 ms

f:id:Cormorant:20180526184453p:plain

動いた!

Hello, world!をやるため、不要なファイルを削除していく。

rm web/controllers/page_controller.ex
rm web/static/css/phoenix.css
rm web/views/page_view.ex
rm -rf web/templates/page/

続いて、router.exの修正

defmodule ModestGreeter.Router do
  use ModestGreeter.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", ModestGreeter do
    pipe_through :browser
  end
end

レイアウトテンプレートの修正

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>ModestGreeter</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
  </head>

  <body>
    <%= render @view_module, @view_template, assigns %>
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>
  </body>
</html>

経路の作成

web/router.exget "/hello", HelloController, :showを追加。

アクションの作成

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, _params) do
    render conn, "show.html"
  end
end

ビューの作成

defmodule ModestGreeter.HelloView do
  use ModestGreeter.Web, :view
end

テンプレートの作成

<p>Hello, world!</p>

再度サーバー実行

mix phoenix.server

http://localhost:4000/hello にアクセスすると

f:id:Cormorant:20180526184735p:plain

テンプレートの内容がレイアウトに沿って出た!

06: 経路設定の初歩

割愛。よくあるフレームワークのルーティングと同じように定義する。

07: コントローラとアクション

割愛。リクエストの構造体connについては8章、16章、そして次巻で取り扱う。 メタプログラミングのコラムあり。

08: HTMLとテンプレート

HTML自体の説明とテンプレートについて。erbとだいたい一緒。

テンプレートに値を渡すには、アクションのrender関数の第3引数にキーワードリストを渡す。テンプレート内ではキーワードで要素にアクセスできる。

アクションの修正

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, _params) do
    render conn, "show.html", name: "Alice"
  end
end

テンプレートの修正

<p>Hello, <%= @name %>!</p>

f:id:Cormorant:20180526184807p:plain

テンプレート中の @ はマクロであり、キーワードリストの値を取得するコードに展開される。

レイアウトテンプレートでも渡されたキーワードリストを参照できる。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>ModestGreeter (<%= @name %>)</title>
    ...

f:id:Cormorant:20180526184948p:plain

ライブリロードされることも確認できた。

09: パラメータ

クエリパラメータを受け取るにはこうする。

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, params) do
    render conn, "show.html", name: param["name"]
  end
end

f:id:Cormorant:20180526185034p:plain

URLパスにパラメータを埋め込むにはこうする。

defmodule ModestGreeter.Router do
  use ModestGreeter.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  scope "/", ModestGreeter do
    pipe_through :browser

    get "/hello", HelloController, :show
    get "/hello/:name", HelloController, :show
  end
end

URLパラメータの省略記法はないのでパラメータなしのルートも作成する。

f:id:Cormorant:20180526185144p:plain

デフォルト値を設定するにはこうする。

defmodule ModestGreeter.HelloController do
  use ModestGreeter.Web, :controller

  def show(conn, params) do
    render conn, "show.html", name: param["name"] || "world"
  end
end

f:id:Cormorant:20180526185152p:plain

汚染が気になる…

f:id:Cormorant:20180526185209p:plain

ちゃんと除染されてた。

10: HTML文書の区分とスタイルシート

割愛。HTMLとCSSについて。PhoenixはBrunchでSCSSなどのリソースを変換・出力をしている。

11: BootstrapとFont Awesome

割愛。章タイトルまま。

12: モジュールと関数

モジュールの定義と利用について。

defmodule Hello1 do
  def greet(name) do
    IO.puts "Hello, #{name}!"
  end
end

Hello1.greet "Alice"
Hello1.greet "Bob"
$ elixir primer/v01/ch12/hello1.exs
Hello, Alice!
Hello, Bob!

関数はモジュール外に定義できないので注意。

exファイルをコンパイルするとbeamファイルができる。

defmodule Hello do
  def greet(name) do
    IO.puts "Hello, #{name}!"
  end
end
$ elixirc primer/v01/ch12/hello2.ex
$ ls
Elixir.Hello2.beam modest_greeter     primer
$ iex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe][kernel-poll:false]

Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Hello2.greet "Alice"
Hello, Alice!
:ok
iex(2)>

スクリプトはカレントディレクトリのBeamファイルも読み込む。

Hello2.greet "Alice"
Hello2.greet "Bob"
$ elixir primer/v01/ch12/hello2.exs
Hello, Alice!
Hello, Bob!

後は割愛。引数のアリティとデフォルト値について。また、無名関数について。

13: リストとタプル

割愛。コラムはErlang / Elixirのリストは連結リストだから末尾の参照は遅いよという話。

14: マップとキーワードリスト

割愛。

15: ビューモジュール

割愛。テンプレートから@view_moduleでアクセスできる。

16: ページ間のリンク

割愛。リンクは<a>タグではなくlink関数とパスヘルパーで作ろうねという話。パスヘルパーの最後の引数[]を省略するエレガントなやり方は次巻で。

17: 画像

割愛。

付録A〜D

割愛。

付録E: 本番モード(prod環境)

mix deps.get --only prod
MIX_ENV=prod PORT=4001 mix do compile, phoenix.server

感想

本当にはじめの一歩といった内容で、さすがにWebアプリ開発は全くの初心者ってわけではないのであまり自分向きではなかった。Elixirの言語仕様については他所でやってしまったので、Phoenixの情報を期待していたんだけど、自分にとって目新しいものはルーティングと付録Eくらいか。

Web技術(HTML,CSS)の解説とElixirの仕様解説が程良い塩梅で用意されており、テキスト通りすすめるための準備が大変なのを除けば、順序よくステップアップしていける内容になっているので良いと入門に良いと思います。この本の想定している読者が果たしてElixirに入門すべきかは疑問ですが…素直にRuby on RailsとかLaravelやったほうがいいと思う。ただ、本当に新しめのスタンダートな内容を丁寧に手取り足取り教えてくれるいい本だと思いますので、これからWebを始めようと考えていて、RubyPHPPythonなんてみんながやってる言語は嫌で、やるなら当然モダンでハイパフォーマンスなプログラムを書きたくて、時代は関数型言語だ!って方にならオススメできます。

インターネットやめる(やめない)話と、16歳の少女の自殺について

前回の記事から180度言ってることが変わるが、インターネットをやる(抽象的表現)のがつらくなったので暫く自粛しようと思う。

事の発端は文春が出した、農業アイドルが自殺した事件についての母のインタビュー記事だ1。例の記事を読んでしまい、そのあまりの救いのなさに怒りと悲しみがとめどなく溢れてきて、やるせなさから2日寝込んだ。

医者から楽しいことをやるようにと言われ、ならばと楽しいこと探しをしている最中にあの記事に出会ってしまった。世の中にはつらいこと苦しいことが溢れていて、それは自分の見えないところでも日々起こっているとわかっていたつもりだが、それでも目の前に突きつけられると最悪な気分になるし、つらい。

その時の様子。

こういった出会いはインターネットをやっていればまま有ることで、今回の遭遇も自分にとってはよくあるもののひとつだと思っていたのに、想像以上に衝撃を受けてしまった2

今の自分には痛ましい事件や事故を自分の外側のものとして受け止められないということらしい。普通の状態であれば怒りや悲しみが沸きこそすれ、それで2日も寝込まない。無自覚に危険な行動をとっていて、それで車にはねられたようなものだと思う。交通事故を防ぐためには、ばかみたいに車道に飛び出して歩かないようにする他ないわけで、Twitterや一般ニュースのフィードは暫く見ないことにした。はてブは悪い文化。

日報はいい習慣だと思うので続けようと思う。Twitterは、心に湧いたとりとめのないことを書き残すのにちょうどいいので続けたい気持ちもあるけど、自分はふぁぼり魔なのでタイムラインを見ないようにしててもすぐ見たくなってしまうと思う。だからやらない。時々API叩いて何か出力されるかもしれないけど他の人のツイートは見ていないと思う。とりとめのないことはscrapboxに書いていく。

...

...

...

ここまでが自分の話。

件の母親の告白について、混乱した頭では稚拙なことしか言えないので今言えることは少ないんだけど、それでも。

周囲の大人の対応が、ことごとく16歳の少女に対しての行いではないということが、どれだけ彼女を追い詰めただろうと思うと胸が苦しくなる。 本人には周りの環境が全てだろう、特に子供はそういうものだし、受け入れてしまいがちだが、それでも転校したいとか、(信頼していたという)Sさんがこわいから行きたくないとか、親に訴えるのは尋常ではないということは容易に想像できる。大人がケアしてあげるべきところで逆に責められる環境が、自殺の方法を調べて即実行という、突発的で最悪な選択を彼女にさせてしまった。

16歳は"未成熟な大人"ではなく、"子供"だ。自分はアイドルのことはさっぱりわからないが、夢見る子供はあやふやで向こう見ずだ。同世代で比較して責任感の強い子であってもだ。 普通のアルバイトでさえそのことを考慮して受け入れつつ働かせるのだから、アイドル業界は曖昧で危険な生き物の貴重な時間を借り受けてビジネスをしていることを当然自覚して運営すべきだが、マネジメントはアイドル事務所ですらないという。まっとうな大人がそばに一人でもいれば防げたことだし、それがなかったというところに、農家の出身としては日本の農業が陥っている閉ざされた異常な環境にまで考えが及んでしまう。

母親を責める声があるが、第一に責めるべきはそちらではないだろう。第二に、ということかもしれないが。子供を守る力に乏しい親というのは見ていて切ない。それが怒りになるのかもしれないが、追い詰めるのはやめたほうがいいと思う。

いま悲しみや怒りに苛まされているのは上記のような心境からだと思う。彼女は私にとって全然知らない人だし、私は完全に部外者なのに、どうしようもなく怒りが湧いてくる、ひたすらに悲しい。

つまづいたり失敗したり揺れる子供を、大人が追いつめてしまわない社会であること、少なくとも、少年少女の夢や希望がこんな最悪な形で終わることのない世の中であることを望みます。

大本萌景さんのご冥福をお祈りします。


  1. 母親が告白 農業アイドルだった大本萌景さん(16)は、なぜ自殺しなければならなかったのか | 文春オンライン

  2. 書いていて感じたが、少女の自殺でこんなにも心を揺さぶられてしまうのは、私が過去に自殺で女友達をなくしているからかもしれない。

2017年5月2日から書き始めたのでこれは2017年5月2日の日記です

インターネットをやりたい

ライフログふたたびという気運が(自分の中で)高まりつつあるのでいろんな記録を取りたくなっている。

WikiHubとamakan使い始めた

前々からr7kamuraさんがブログで書いてる自作ウェブサービスに興味を惹かれていて、でもなかなか登録まで踏ん切りがつかなくていつかやろうと棚上げしていた。 なんでしょうね、登録して使い始めるまで5分もかからないってわかってるのにいざやるかってなると立ち止まってしまうのは。 ウェブサービスを使いはじめてもらう(=会員登録してもらう)ためのハードルは、ユーザーにとっては想像以上に高いというのは色んな人が言ってるけど、これのことかなと思った。

…というようなことを下書きに書き始めてから9ヶ月経って、ようやくWikiHubで日報書いたりamakanに読んだ本記録し始めたのが今年の3月。ウッソだろお前ってなりますね。 見出しが「使い始めた」なのでその瞬間には始めようと思ってたんですよ…

wikihub.io amakan.net

タスク管理再開した

WorkFlowyでTODOを書き出し、その進捗をTrelloで管理するようにしました。

workflowy.com trello.com

WorkFlowyは4月の頭に「TODOを書き出したい」ということをTwitterでつぶやいたらmazuconさんが教えてくれた。Trelloは入社研修当時に教えてもらったんだけど業務で使ったことない…

WorkFlowyとTrelloはブラウザで動作するウェブアプリケーションなんですが、この手のアプリはブラウザとウィンドウが別の方が体験がいいので、WindowsMacAndroid携帯とiPadに公式アプリ入れてどこでも確認と共有ができるようにしています。アプリ版の機能はブラウザ版と同じです。

inoreaderはじめた

jp.inoreader.com

これは記事を投稿する当日に始めたのですが、RSSリーダーの利用を再開しました。インターネットと言えばこれだよなという思いがある。 今回使い始めたのが垢抜けたデザインになって人気急上昇中の inoreader . 更新頻度が低いところはあんまり巡回しないアルゴリズムで動いているのが嫌われたりするけどまあそのへんは割り切りで。ウェブサイトを直接登録するんじゃなくて、対象サイトを高い頻度で巡回しているポータルサイトRSSを登録しておくとか、そういう回避を。

今後は爆速でインターネットの記事を読んで、気になったらブックマークしていきます。ところでLive Dwango Readerの復活まだですかね???

インターネットが進捗していてよかった

インターネットのツールやサービスを再度使い始めて、なんというかインターネットさん垢抜けたなあと思いました。どこもかしこもデザインがかっこいいしUIが使いやすくなってるよね。はてなブロクも編集画面使いやすくていい感じです。

「逆引きwebpack」を読みました

技術書典"3"で購入しました…やらなきゃいけなくなったので積読消化します。

booth.pm

TOC

  • はじめに
  • 本書の概要
  • 目次
    • 基礎設定
    • SCSS
    • SCSS + PostCSS
    • Babel
    • TypeScript
    • Vue.js
    • Vue.js + SCSS + PostCSS
    • webpack-merge
  • おわりに
  • おまけ

はじめに, 本書の概要

  • 本書には目的からどのようなwebpackの設定を作ればいいのかを掲載
  • 各項目をピックアップした目的
  • サンプルコードはmya-ake/reverse-resolution-webpackで公開している
  • 対象のwebpackバージョンはv3.8.0
    • 積読している間にv4系が来ちゃった…(現時点の最新はv4.8.3)

基礎設定

公開しているサンプルを使用すると以下の環境が整う。

  • 保存時自動ビルド
  • ローカルサーバー
  • ビルド後自動リロード
  • プロダクションビルド(簡易版)
  • プロダクションビルド後の動作確認
  • HTMLにoutputしたJSファイルのsrcを埋め込む
  • scriptタグにデフォルトでdeferやasyncを付ける
  • アウトプットするファイル名にハッシュ値を追加
  • npm scriptsを複数同時に実行
  • ビルド時にdistフォルダ内のファイルを削除
  • ローカルネットワーク内での共有
  • 複数ブラウザの同期

最高…

devtool

devtoolはソースマップのスタイルを決める設定。だが、ソースマップの品質とビルド速度に影響するので重要な項目。今回の設定では下記の値を用いている

  • 開発
    • cheap-eval-source-map: ビルド速度とソースマップの品質のバランスが良い
  • プロダクション
    • hidden-source-map: 本番稼働時はソースマップを見れるようにする必要がない

yarn clean

Node詳しくないのでrimrafしらなかった…便利。

TypeScript

tsconfig.json。あとで公式サイトを読みます。

Vue.js

Vue.jsのビルドにresolver.aliasを使っているのは、ビルドの種類がいろいろあるため

Vue.js + SCSS + PostCSS

Vue.jsの単一コンポーネントをビルドするにはvue-loaderを通す。各ブロックのlang に応じて通すloaderを変更できる。

webpack-merge

分割したwebpack.config.jsonをまとめる事ができる。共通部分 + (開発 || プロダクション)みたいなことをやれる。

おわりに, おまけ

初技術書でこのボリュームはすごい。Nuxt.jsでsass-resources-loaderを使うトピックは今まさにやりたいことだったので助かります。

感想

読むのを放置してしまったがためにwebpack 4系が来てしまった…折角の技術同人誌なのに鮮度がいいうちに読まないのは良くないですね…

逆引き辞書なのでさらっと目を通して終わりにしましたが、あとでプロジェクト作るのでその時活用させていただきます。
素晴らしい本をありがとうございました。

「初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービス」読んでFirebase始めてみました

Vue.jsとFirebaseといういまやりたい技術ど真ん中の本を読んで実践した履歴です。

booth.pm

TOC

  • 01: まえがき
  • 02: サーバーレスシングルページアプリケーションの基本
  • 03: 開発環境のセットアップとデプロイまでの流れ
  • 04: Googleアカウントでのユーザー登録と、ログイン状態の判別
  • 05: エディターの作成:データベース作成とデータ保存
  • 06: Webサービスとして公開するまでの必要な準備
  • 07: 最後に

01: まえがき

  • 「Vue.jsとfirebaseを使って簡単なWebサービスを作ってみる」ことが目的、個々の詳細な説明は省略する
  • ちょい足しポイントを実施することでアドバンスドな学習が出来るようにしている

02: サーバーレスシングルページアプリケーションの基本

  • SPAってなに? → 簡単な歴史
  • サーバーレスってなに? → サーバインフラのリソースを気にしなくてもサーバーサイド処理ができる環境を利用することで、サーバー構築で考慮していた一部分を考慮する必要がなくなるという意味とする
  • FirebaseはBaaS、バックエンドの処理を肩代わりしてくれるサービス
  • Firebaseで出来ること → Hosting, Authentication, RealtimeDatabase

03: 開発環境のセットアップとデプロイまでの流れ

やったことを書いていきます。

$ vue init webpack-simple mymarkdown
$ yarn
$ yarn run dev

(書籍ではnpmだったけど宗教上の理由でyarn)

うごいた。
続いて、Firebaseのセットアップとデプロイ

  • アカウント作成
    • 既にGCPのアカウントを持ってる
  • プロジェクト作成
    • mymarkdown-c18t
    • ウェブアプリにFirebaseを追加
    • 表示されたスニペットをコピーして、index.htmlのscriptタグの上にペースト。/dist/build.js → /build.js
      • このコード上のAPIキーはユーザに公開されてしまうが、firebaseのコンソールに権限管理があるので大丈夫
$ yarn global add firebase-tools
$ firebase login
$ firebase init
❯◉ Hosting: Configure and deploy Firebase Hosting sites
? Select a default Firebase project for this directory: mymarkdown (mymarkdown-c18t)
? What do you want to use as your public directory? (public) dist
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N)

webpack.config.jsを修正。

  • output.publicPath/にする
  • devServer.contentBase: 'dist'を追加
  • souceMapfalseにする

index.htmlをdistに移動してビルドしてデプロイ

$ mv index.html dist/
$ yarn run build
$ firebase deploy

index.htmlが表示された!

04: Googleアカウントでのユーザー登録と、ログイン状態の判別

今度は Authentication を使ってユーザー登録・ログイン機能を用意し、ログイン状態で内容を変えてみる。

  • src/components/Home.vue 作成。
  • src/components/Editor.vue 作成。
  • src/App.vue 修正して c/Home.vue と c/Editor.vue を条件に応じてインポート
  • FirebaseのコンソールでAuthenticationを追加、Googleアカウントでログイン機能を有効化
  • src/components/Home.vue に firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider()) を呼び出す
  • src/App.vue でユーザーが取れたら this.isLogin = true にして this.userData = user する
  • src/Editor.vue にログアウトボタン
$ yarn run dev

うごいた!

$ yarn run build
$ firebase deploy

うごかない…Home.vueの@click="googleLogin"が反応しない…とおもったらしばらくして動くようになった…

05: エディターの作成:データベース作成とデータ保存

$ yarn add marked -D
  • src/components/Editor.vue に markdown 入力エリア作成
  • style lang="sass" scoped

markdownがプレビューされるようになった。

  • src/components/Editor.vue にメモ選択機能追加
  • ビューモデルのデータを配列にしてぐるぐる回す

firebaseの機能と直接関係ないので省略して、Firebase Realtime DBにメモを保存するように変更する。Cloud Firestoreが推奨されているけど、今回はRealtime DBを使います。

  • Firebase Realtime DBにルールを追加
    • /memos/$uidに対し、$uid === auth.uidのときread/writeの許可
  • 保存ボタン押下時に /memos/$uid にメモのモデルを保存
  • エディタオープン時に /memos/$uid から読み取ったモデルの内容を表示

オンラインエディタだ!

06: Webサービスとして公開するまでの必要な準備

見た目の調整、サイトの説明の作成、利用規約の作成、セキュリティ対策などを行いましょう。

07: 最後に

ちょい足しをやったうえでまだまだ足りないぞ!という方向けに「強くてニューゲーム」があります。

感想

技術書典04で見かけて、BaaSやんなきゃなと思っていたところだったので渡りに船という感じで購入しました。めちゃくちゃ簡単だ…!業務で通知機能を利用したことはあったんですが、ホスティングサービスとして利用したのは初めてでした。手元のコンソールからコマンドでデプロイが簡単にできちゃうというのが強力だなというのと、SDKの使い方がわかりやすいなというのが良いポイント。

書籍については、通常の内容は簡単ですぐ動いてくれるのでやっていて楽しかったです。(知りたかったのはFirebaseの機能だったので複数メモ機能は飛ばしちゃいましたが…)また、ちょい足しポイントの難易度がそれなりに高めでやりごたえありそう。そしてそれが終わったあとも「強くてニューゲーム」が用意されているスルメぶりでゲーミフィケーション性が高いなーと思いました。3回遊べる技術書って珍しいのでは。学習を進めたら折をみてまた挑戦したいです。素敵な本をありがとうございました。

書籍で取り扱わなかったStorage、Functions、ML Kitも触ってみたいですね。

今回やった成果はこちら。

「今日からはじめる技術Podcast完全入門」やっていきました

普段から聞いてるyatteiki.fmが「技術書典04で同人誌出すぞ!」ということでこれは買うしかないでしょと行って買って読んだ、はい。

yatteiki.booth.pm

TOC

本書はこんな方にオススメ

  • ウェブエンジニア
  • フリーランス
  • クリエイター
  • 自分には何もないと考えている人

ウェブエンジニア志望(戻りたい)なのでぴったりですね!

01: Podcastをはじめよう

  • itopoidさん
  • Podcastの強みについて、ディレクター的視点から

02: Podcastを収録しよう

  • kosugeさん
  • 録音ができればなんでもいい
    • "とはいえ良いマイク、良い環境で録音するほど聴きやすい"とあり、「なんでもいい(なんでもよくない)」ってやつだ…と思いました
    • Rebuildの宮川さんもいいマイクでやってるし、のじゃおじのねこますさんも「音声が悪いと視聴をやめてしまう」って言ってるのでやるならコンデンサーマイク買ったほうがいいと個人的には思います
  • 収録環境について。マイクはYeti、録音装置は各自バラバラ、会話ツールはDiscord.
  • 仮想オーディオデバイスに流してそいつを録音するとのこと。バーチャルユーチューバーと同じだ。
  • Discordで収録するbotを作ってみよう。discord.jsを使ってDockerでbot走らせる。fluent-ffmpegで音取ってmp3にする。

03: Podcastを公開しよう

04: 番外 : スマートスピーカーで再生できるようにしよう

  • 引き続きsoramugiさん
  • Alexaのスキル、yatteskillの使い方
  • 常にそこにいる、常に待機している存在。
    • コンシューマ向けIoTの可能性で一番目立ってるのがこの体験だと思うのでスマートスピーカーいいと思います。

05: Podcastを続けよう

  • itopoidさん
  • 番組が終わる原因 → テーマを間違える、テンションが続かなくなる
  • 全ては継続。継続のために貴女にあったテーマ設定をしよう

06: Podcast番組企画を立てよう

  • 引き続きitopoidさん
  • 企画チェックリスト
    • 企画なんにも思いつかないのでパス
  • Podcastのおもしろさの本質はトークの内容ではない、パーソナリティの魅力と楽しげな雰囲気
  • あなたの適性Podcastパラメータを可視化しよう
    • A,D,Eが低く、B,C,Fが高い。
      • 「友達が必要なコンテンツは無理です」というのが客観的に分かってしまった…
      • 自分が詳しいコンテンツについて一人で語るみたいなのが向いていそう
    • やるとしたら、朗読好きなので、界隈の雑談をはさみつつ本を読みます的なやつになるんじゃないかな。でも朗読するよりしてもらうほうがいい

あとがき

soramugiさんが言及している、コンテンツの消費の大変さというは最近ものすごく感じていて、まあブイチューバー特ににじさんじをおっかけるのがつらいという話なんですけど、そうしてブイチューバーに疲れたらポッドキャスト聞きながら技術書典で買った本を読んでる、という、生活がコンテンツ消費のためにあるような状況で暮らしてます。そんななか、この本を読んで、ポッドキャストをやるかはともかくとして、アウトプットしていきたいなあという気持ちが燃え上がってきました。読書体験としては最高の時間だった。

感想

気合入ってた。 itopoidさんの担当した章はかなり推敲してるなって文章。炭火のような遠赤外線熱を感じます。静かにエモいので買って読もう。

あとでオーディオコメンタリー聞きながらもう一回読もうと思います。素晴らしい本をありがとうございます。

「Hello nuxt!!」を読みました

技術書典04で購入した、Hello Nuxt!!: Vue.jsのサーバサイドレンダリングフレームワークを読みました。

cf. 技術書典4で出展してきました #技術書典 - チラシ裏日記上等!!新館

TOC

はじめに

  • ユニバーサルアプリケーションって実行環境に依存しない≒PCでもスマートフォンでも動くアプリのことだったのでは…
  • Nuxt.jsは静的ファイルジェネレータとしても使用できる

02: Nuxt.jsのはじめ方

  • .vueファイル
  • vue init nuxt-community/starter-template <dir>

03: ディレクトリ構成と役割

  • pagesディレクトリはビューとルーティングに関する役割を負う
  • pagesに配置されるvueファイルに、Nuxt.jsによって独自に追加された属性について
  • 動的なルーティングの機能によってpagesディレクトリの構成から自動でrouter.jsが生成される
  • componentsディレクトリ以下は、純粋なvueコンポーネント
  • layoutsディレクト
    • デフォルトレイアウト、エラーページ、カスタムレイアウト
    • カスタムレイアウトを使用するページで、layout名を指定する
  • pluginディレクトリには、インスタンス化時に実行されるコードを記述。初期化コードなど
  • middlewareディレクトリには、レンダリング前に実施されるコードを記述。ページコンポーネントのmiddlewareに指定すると実行される。サーバサイドで実行される点に注意
  • store, assets, staticについては省略

04: ページコンポーネント

  • コンテキストは以下に渡される
    1. asyncDataメソッドの第1引数
    2. fetchメソッドの第1引数
    3. layoutをメソッドとして実行したときの第1引数
    4. ミドルウェアとして定義した関数の第1引数
  • asyncData内で取得したデータは、コンポーネントのdataとマージできる
    1. Promiseを返す
    2. async/awaitで結果を取得してリターン
    3. callbackに渡す
  • fetchはデータをストアに入れる
  • headはheadタグを設定する
  • layoutは文字列で指定する。関数を定義して動的にレイアウトを選択することもできる
  • middlewareはファイル名を文字列か文字列の配列で指定する

05: コマンド

コマンドについては割愛

おわりに

Nuxt.jsには本書では書くことができなかったさまざまな応用法が用意されている。公式ガイドを閲覧しステップアップをはかろう

総括

本日同時に読んだNuxt tech bookと比較すると、より公式ガイドの記述に沿った内容になっていて、特にページコンポーネントの理解を助けるものになっていました。コンテキストの内容やfetchとasyncDataの違いなど、公式ガイドをさらっと見ただけではよくわからないところがあったので助かりました。
あと、Nuxt tech bookとはvue-cliのテンプレート名が違った。こちらのほうが公式ガイドに乗っている名前なので、これがいいのかな。

以上です

素晴らしい本をありがとうございます。