I can fly!!

地元ITベンダー→公務員→フルリモートのフリーランス Webエンジニア もうすぐ2児の父

$npm run dev 実行時のエラー、仮想マシンを再起動したら直りました。

npmのエラーって、ログ見ても全然ピンと来ないので本当に嫌い・・・ npm系のエラーはだいたい
$ rm -rf node_modules
$ rm package-lock.json
$ npm cache clear --force
これらを実行した後に、
$ npm i
$ npm run dev
などやると直ることが多いんだけど今回はそれでも直らず、、、おもむろに仮想マシンを再起動してビルドし直したら無事に通りました。
理由は全くわかりません。
(仮想マシンじゃなくmac本体で開発してる場合も、mac再起動したら直るかもね。)

とはいえ直ったので、次にまた困った時用のメモって感じで。あと、この方法はググっても出てこなかったのでいつか誰かに助けになればと思って。

以下、今回の詳しい状況。

開発環境

macos上にvagrantで立てた仮想マシン(amazon linux 2018.3)

エラーが起きた状況

別メンバーが作業中のブランチに切り替えて、
$ npm i
$ npm run dev
を実行した際にエラー発生。なお、別メンバーの環境上では問題なく動いていた。

エラーログ

$ npm run dev 実行時ログ

$ npm run dev
> n@1.0.0 dev /var/www/cenq
> node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js
66% building 841/889 modules 48 active /var/www/cenq/node_modules/entities/index.jsnpm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! n@1.0.0 dev: `node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the n@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     /home/vagrant/.npm/_logs/2020-01-14T07_56_29_229Z-debug.log

/home/vagrant/.npm/_logs/2020-01-14T07_56_29_229Z-debug.log

0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'run', 'dev' ]
2 info using npm@6.13.4
3 info using node@v10.18.0
4 verbose run-script [ 'predev', 'dev', 'postdev' ]
5 info lifecycle n@1.0.0~predev: n@1.0.0
6 info lifecycle n@1.0.0~dev: n@1.0.0
7 verbose lifecycle n@1.0.0~dev: unsafe-perm in lifecycle true
8 verbose lifecycle n@1.0.0~dev: PATH: /usr/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/var/www/cenq/node_modules/.bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/vagrant/.local/bin:/home/vagrant/bin
9 verbose lifecycle n@1.0.0~dev: CWD: /var/www/cenq
10 silly lifecycle n@1.0.0~dev: Args: [ '-c',
10 silly lifecycle   'node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js' ]
11 silly lifecycle n@1.0.0~dev: Returned: code: 1  signal: null
12 info lifecycle n@1.0.0~dev: Failed to exec dev script
13 verbose stack Error: n@1.0.0 dev: `node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
13 verbose stack     at EventEmitter.emit (events.js:198:13)
13 verbose stack     at ChildProcess.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:198:13)
13 verbose stack     at maybeClose (internal/child_process.js:982:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid n@1.0.0
15 verbose cwd /var/www/cenq
16 verbose Linux 4.14.154-99.181.amzn1.x86_64
17 verbose argv "/usr/bin/node" "/usr/bin/npm" "run" "dev"
18 verbose node v10.18.0
19 verbose npm  v6.13.4
20 error code ELIFECYCLE
21 error errno 1
22 error n@1.0.0 dev: `node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`
22 error Exit status 1
23 error Failed at the n@1.0.0 dev script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

React, Material-UI, React Redux, redux-saga, TypeScript, Firestoreを使ってチャットアプリを作りました。

せっかくの長い正月期間、だらだら過ごさないためにも「気になってた技術全部キャッチアップしてやる!!」と意気込んで取り組みました。 正月で家族が集合する中、場の空気を壊さぬよう早起きしたり、夜更かししたり、抜け出したりしながら何とか完走しました。笑 (大いに便宜を図ってくれた妻に感謝。)

成果物

チャットアプリ

ソースコード

機能

  • ユーザー名の変更
  • チャットルーム作成
  • チャットルーム一覧表示
  • 入室
  • メッセージ送受信

面白くも何ともないただのチャットアプリです。技術のキャッチアップが目的なのでアプリとしてのクオリティはめちゃ低いです。Firebase Hostingを使って公開してます。認証は未実装です。

開発環境

MacOS上にvagrantで立ち上げた仮想マシン(ubuntu16.04)で開発しました。

使用した技術

  • React
  • Material-UI
  • React Redux
  • redux-saga
  • TypeScript
  • Firestore
  • eslint, prettier

この記事で書いてること

各種ライブラリの導入手順(主にコマンド)や細かい設定。(途中からだるくなって終盤めっちゃ適当) あと、開発してみての所感など。

この記事で書かないこと

各種ライブラリの使い方、概念、思想、実装コードなどは記事の中には書いてません。 (実装部分についてはgithubにあげてるのでそちらを参照してください。)

参考URL

Ubuntuに最新のNode.jsを難なくインストールする https://reactjs.org/ https://material-ui.com/ https://create-react-app.dev/docs/adding-typescript/ https://prettier.io/docs/en/integrating-with-linters.html React × TypeScript × ESLint × Prettier 環境構築 https://react-redux.js.org/ https://stackoverflow.com/questions/35667249/accessing-redux-state-in-an-action-creator https://stackoverflow.com/questions/38544928/redux-calling-store-getstate-in-a-reducer-function-is-that-an-anti-pattern https://medium.com/@shoshanarosenfield/redux-thunk-vs-redux-saga-93fe82878b2d https://firebase.google.com/docs/web/setup?authuser=0 https://firebase.google.com/docs/web/setup?hl=ja https://firebase.google.com/docs/firestore/quickstart?hl=ja https://redux-saga.js.org/ redux-sagaで非同期処理と戦う https://github.com/redux-saga/redux-saga/blob/master/README_ja.md

所感

React Redux, redux-sagaがすごく大変でした。普段のLaravel + Vue + VuexでのSPA開発でFluxの概念には触れているので、その概念や思想の部分についてはよくわかるし理解できるのですが、実際に実装するとなると考えることが多くて。。。「技術のキャッチアップ」が目的だったので、妥協せずに公式ドキュメントを読み込んでアンチパターンを踏まないように実装しました。

Firestoreについては、無料でdatabase機能やイベントのPub/Sub機能を享受出来るし、ドキュメントも充実してるので、プロトタイプや勉強目的であれば最高に使いやすいなと思いました。でもプロダクト版に利用することを考えると、秘匿情報を守るために結局サーバを立ててFirebase Admin SDKなるものを使う必要があるので案外簡単ではないと感じます。巷では「超お手軽簡単」のイメージが強いので、この辺のセキュリティ意識が乏しい人が安易に使うと危ないかもと思いました。

TypeScriptについては、最初は「いちいち型定義するのめんどくさい。こんな調子だと日が暮れちまうよ。」って感じでした。コンパイルも全然通らんし。 でも、だんだんに慣れるし、思えば指摘がリアルタイムで丁寧だし、何よりコンパイル通りさえすればだいたいバグなく動いてくれるので、トータルで見ると開発効率上がってるんだと思います。「普段はネチネチと小言のうるさい頭カチコチめんどくさ真面目野郎だと思われてるけど、卒業間際になってそのありがたみに気づいた生徒達にめっちゃ感謝されるタイプの教師」みたいだなと思いました。

あとは副次的な効果として、1ヶ月前くらいから習得に励んでるVimがだいぶ板につきました。

今後の課題

  • reducerやsagaなど、肥大化しがちな箇所を適切な粒度で分割
  • reduxのconnectをcontainerに切り離す
  • TypeScriptの書き方を覚える(定義した型の再利用とかしたい。出来るのかな?)
  • 便利機能の導入(redux-toolkitとかredux saga firebaseとか)

まあ、ディレクトリ構成とか設計の部分になると、チーム毎プロジェクト毎に最適解が変わるのでベースの考え方だけ押さえておけるように引き続き勉強したいと思います。

以下、開発メモ

最新安定版のnodejsをインストール

aptリポジトリアップデート $ sudo apt update

nパッケージをインストールするためにnodejsとnpmインストール $ sudo apt install -y nodejs npm

nパッケージをインストール $ sudo npm install n -g

最新安定版のnodejsインストール $ sudo n stable

不要パッケージ削除

$ sudo apt purge -y nodejs npm
$ exec $SHELL -l

バージョン確認

$ node -v
v12.14.0

$ npm -v
6.13.4

reactプロジェクト作成

$ npx create-react-app chat

  • 開発用サーバ起動
$ cd chat
$ npm start
Compiled successfully!

You can now view chat in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://10.0.2.15:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

localhostの3000ポートにアクセスするとデフォルトページが確認できる。 reactのデフォページ

$ cd src
$ rm -f *

material-ui 導入

  • パッケージインストール
$ npm install @material-ui/core
$ npm install @material-ui/icons
  • font, iconファイルの読み込み 下記の2行をpublic/index.htmlのheadタグに追記する
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />``
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
  • レスポンシブ用メタタグ挿入 下記をheadタグに挿入
<meta
  name="viewport"
  content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
/>
  • サンプルファイル作成 src/index.jsを作成する
// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Button from '@material-ui/core/Button';

function App() {
  return (
    <Button variant="contained" color="primary">
      Hello World
    </Button>
  );
}

ReactDOM.render(<App />, document.querySelector('#root'));
  • ビルド&サーバ起動 $ npm start ※このコマンド一発でサーバ起動だけじゃなくビルドもやってくれてるぽい。

ブラウザで確認すると、material-uiが適用されたボタンが表示される。 サンプル

TypeScript導入

  • パッケージインストール $ npm install --save typescript @types/node @types/react @types/react-dom @types/jest

※create-react-appの時に $ npx create-react-app my-app --template typescript これでやれば一発だったぽい。 既存のプロジェクトに導入すると移行大変そうだし、typeScript使うなら最初に入れるのが良さそう。

  • jsファイルの拡張子をtsxにリネーム まだindex.jsしかファイルないし、コーディングもしてなかったので助かった。

eslint prettier導入

  • prettierインストール eslintはreactプロジェクトにデフォルトで含まれているらしくprettierのインストールだけでいいらしい。(確かにpackage.json見るとそれっぽいのある。) $ npm i prettier eslint-plugin-prettier --dev

  • package.json編集

// package.json
...
 },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
+    "lint": "eslint src --ext .ts --ext .tsx --fix" <- この1行を追記
  },

もう一箇所

// package.json
...
// この3行を削除して、eslintrc.jsonに切り出す。
-  "eslintConfig": {  
-    "extends": "react-app"  
-  },  
  • eslintrc.jsonを作成
// eslintrc.json
{
    "extends": [
        "react-app"
    ],
    "plugins": [
        "prettier"
    ],
    "rules": {
        "prettier/prettier": "error"
    }
}

これでlinterが動くようになる。

  • linter実行 $ npm run lint eslintが静的解析、prettierがコード整形をやってくれる。

redux導入

  • モジュールインストール $ npm install --save react-redux $ npm install @types/react-redux

redux-saga導入

$ npm install --save redux-saga

Firestore導入

  • cliインストール $ sudo npm install -g firebase-tools

  • sdkインストール $ npm install --save firebase

あとはドキュメントに従ってfirebase側のセットアップを色々やる。

// firebase.json
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "build", <=ここ変更
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "emulators": {
    "firestore": {
      "port": 8080
    },
    "hosting": {
      "port": 5000
    }
  }
}
  • firebaseの初期化 firestoreしか使わないので、firestore()をexportして、使う先でimportする感じに実装した。
//firebaseinit.js
import * as firebase from "firebase/app";

const firebaseConfig = {
    apiKey: "AIzaSyAnFKAoPCH9LYbSD_vUBEtqmsmAnxKVpOY",
    authDomain: "react-chat-3cd68.firebaseapp.com",
    databaseURL: "https://react-chat-3cd68.firebaseio.com",
    projectId: "react-chat-3cd68",
    storageBucket: "react-chat-3cd68.appspot.com",
    messagingSenderId: "1067905229521",
    appId: "1:1067905229521:web:8cfb086a2e3bcf3dfadbf0",
    measurementId: "G-P4H92P4780"
  };

  firebase.initializeApp(firebaseConfig); 
  const db = firebase.firestore();
  export default db;
// 使う側
// api.ts
import "firebase/firestore";
import db from "./firebaseInit";
import { eventChannel } from "redux-saga";

export function fetchRooms() {
  return new Promise(resolve => {
    db.collection("rooms")
      .get()
      .then(querySnapShot => {
        let rooms: { id: string; roomName: string }[] = [];
        querySnapShot.forEach(doc => {
          rooms.push({
            id: doc.id,
            roomName: doc.data().name
          });
        });
        resolve(rooms);
      })
      .catch(() => {
        resolve([]);
      });
  });
}
~~~

以上、有意義な正月だったな〜。

わりと規則的なリモートワーカーの1日

リモートワークを始めて2週間が経ちました。なんとなーく1日のサイクルができてきたので晒してみます。ベースはだいたいこんな感じ。

f:id:hide0721yana:20190414210503p:plain
1日のサイクル

朝は5:00に起きて2hほど勉強します。でも眠たくて起きられない時があったり、息子がいつも5:30頃に目覚めて暴れ出すのでそれに翻弄されたり、妻が用事ある時なんかは私が面倒見たり、ぶっちゃけ、最近はそこまでやれてないですw

家事、育児、朝食、身支度が終わったら、仕事前に息子抱えて散歩するようにしてます。意識しないと一歩も外に出なくなってしまうので。

住宅街だけど季節を感じることもできて結構オススメ。

公務員時代にはこんな発見一度たりとも無かったなぁ。(ディスり)

8:30頃から業務を開始して17:30頃で一旦区切り。早めに夕飯を済ませて、息子の風呂とか寝かせる準備とか します。
そのあと20:00頃には息子が寝て解放されるので、仕事に戻ったり調べ物したり勉強したり。そして、22:00頃までやったら就寝〜。

とまぁ、だいたいこんな感じです。良くも悪くも息子次第なところがあるので、あまり自由が効かないけど、わりと規則的で健康的なんじゃないかなと思ってます。

リモートワークを始めて2週間が経ちました

とりあえず元気にやってます!笑

ブログ書こう書こうと思い続けて2週間。ようやく重い腰が上がりました。

ブログって書かなければ書かないほど、「ブログのネタにしたいな〜」と思うことが増えていって、いざ「書こう!!」と思った時に「あれも書かないと。。これも書かないと。。。」と収拾がつかなくなってめんどくさくなって、結局書かない。

という負のループに陥りがちですね。実は今日もそれで諦めかけたんですが、私は閃きました。

まとめて1記事で書こうとせず、一つ一つのネタを小出しにそれぞれを記事にしよう!

ということで、今日は予告編です。これまでの2週間で「ブログで書いときたいな〜」と思ったことを列挙して終わります。明日から少しずつ記事にしていきます。

フリーランスとかリモートワークに興味ある人なら結構興味そそられるタイトルじゃないかなぁと、我ながら思います。明日から頑張ります。

ブログのネタリスト

  • 自己肯定感をいかに保つか
  • 仕事道具は最高のものを
  • 健康第一
  • 家族と過ごす時間が増えた
  • 意識しないと永遠に仕事してしまう問題
  • より早く仕事モードになり、そして持続させる方法
  • 「やらなきゃいけないこと」と「やりたいこと」が一致していてとても良い
  • リモートワークでも結局時間は足りない
  • フリーランスの手続き関係の話
  • スキルめっちゃ大事
  • 「報酬」の重み
  • 1日のサイクル

この他に、tech系の記事も少しずつ・・・。
では。

PHPerKaigi2019の振り返り

phperkaigi.jp

PHPerKaigi2019に参加してきたので、早速振り返りたいと思います。
楽しくて有意義で濃密な時間というものは一瞬で過ぎ去ってしまうのですね・・・

昨日の記事はコチラ www.hideyana.com

強いエンジニアになるためのヒントを手に入れた

私は、PHPerKaigi2019にこんな気持ちで臨んでいました。

結果としては、外のモノサシというよりは強いエンジニアになるためのヒントを手に入れたので、それを共有したいと思います。
強いエンジニアは1日にしてならず
そんな言葉がぴったりだなーという印象です。

1. 経験を積む

まず場数を踏むこと。うまくいったことうまくいかなかったことあらゆる経験が血肉になります。

2. 勉強する

当たり前のことだけど、強いエンジニアのみなさんは勉強量が尋常ではないなと感じました。日々コツコツ地道な積み重ねがエンジニアとしての力になります。

3. 本質(why)を理解する

ただ単に動くものを作るだけでは、エンジニアとしての胆力は身に付きづらい。どんな実装になっているのか、なぜその実装なのか。深掘りすることで力がつきます。

4. アウトプット

言わずもがなですね。ブログ、Qiita、勉強会、登壇・・・とにかくアウトプット側に立つことが大切です。

PHPerKaigi2019最高だった

たくさんの学びと刺激と仲間が得られて、本当に本当に最高のカンファレンスでした。めっちゃ楽しかったです。次の機会はLTか何か、アウトプット側で参加できればと思います。
最後に、思い出深いツイートを貼って終わります。

Laravel相談会の場でLaravelに全然関係ない質問をしてしまいましたが、「自分ならこうするかな」と、テーブルのみなさんは嫌な顔一つせず教えてくれました。PHPerあったかい。

明日からリモートだけど、全然怖くねぇ。仲間心強い。

メルカリの後藤さんとがっちり握手した瞬間が、この3日間で一番心が震えた。後藤さんがどんなマインドで転職したのか、重なる部分がとても多くて、自分自身のチャレンジ・行動がとても誇らしく思えて心の炎がマックスになった!チャレンジし続ける!!毎日少しずつでも限界を超えて成長し続ける!!

PHPerKaigiに関わった全ての人に感謝です!めっちゃ楽しかった!!お疲れ様でした!!

PHPerKaigi2019 感想その1

PHPerKaigi 2019に参戦中です。
今日学んだことを忘れないうちにメモ。
決意したこと、すぐ行動に移さないと忘れちゃうからね!

これからやろうと決めたこと

フレームワーク自作

フレームワークを自作することで、その本質が理解できる!本質の理解でより良いエンジニアになれる!! パーフェクトPHPの第7章にフレームワークの作り方が書いてるのでとりあえず写経してみる。

PhpStorm導入

PhpStormすごい。便利機能がもりもり。デフォルトの設定で素敵な体験がいっぱいできるらしい。PhpStormないとプログラム書けない病を発症することもあるので気をつける。

ブログ書く

ブログのハードルを低くするのが書き続けるコツ。質が低くてもよし。自分のために書く。習慣化する。1回ググったらそれはもうブログのネタになる。ネタ帳にメモする。目的を明確に。テンプレ化する。

本をじっくり読みすぎない

インプットしたことの80%はどうせ忘れる。ザザーっと読んでそれを繰り返すほうが定着する。ザザーっと読むだけでもなんとなく掴めるものがある。量をこなす。量をこなすと大事な部分が浮き出てくる。流れで捉える。

勉強会の主催

地元盛岡で何か勉強会を主催して、アウトプットの機会を増やす。

今日出会った素敵なPHPerの方々

twitter.com 以前からオンライン上で友達で、この度初対面。ブログ500日連続更新のすごい人。ブログのコツをたくさん聞いた!PHPer界隈ではういろうさんのファンクラブが存在していたw ういろうさんのアンカンファレンスに参加したところから、PHPerのみなさんとコミュニケーションを取れた。感謝。

twitter.com 営業職からフリーエンジニアに転身して3ヶ月目にも関わらず、バリバリやってるすごい人。仕事に関する考え方とかめちゃめちゃ共感できた。勉強の仕方とか、要素技術の見極めとかが鋭くて、成長スピードが異常。俺も負けない!!と思った!これから切磋琢磨していく!!

twitter.com PHPer茶会でたまたま隣に座ってた人に話しかけたら、まさかまさか同じ中学校の後輩だったという奇跡の人。とても若いのに意識が高くて、社内の状況と自分の立場を踏まえ勉強を進めてみたり、勉強会のスピーカー側にチャレンジしたり見習うことがたくさん。

他にもいろんな方とコミュニケーションが取れてすっごい楽しかったし、めちゃめちゃ刺激も受けました。

まとめ

PHPerKaigiやばい。たった1日でこれだけの学びと刺激と出会いがあった。もう1日楽しめるの嬉しすぎる。明日も超濃密な1日にするぞ!!