俺的、最強のデスクトップ環境を作ってみたヘ(^o^)ノ

f:id:murajun1978:20200911200145j:plain
My Desktop

在宅勤務しつつ、YouTubeで動画配信するための環境を作ってみた

前置き

  • 会社のPC Macbook Pro
    • お家で会社の仕事をするときに使うラップトップ
  • 自作PC + Ubuntu

    • お家 + 個人の仕事 or プライベートで使うデスクトップ
    • 前回のブログで紹介したコレ↓です

    murajun1978.hatenadiary.com

  • ThinkPad X1 Yoga Gen 5

    • 外出先 + 個人の仕事 or プライベートで使うラップトップ

Web会議、Live配信

Web会議であればWebカメでもいいのですが、YouTubeでLive配信するには画質にはこだわりたいなと!

なんで、ミラーレスカメラを購入しました

バッテリー駆動だと2,3時間しか持たないので、電源共有しながら使えるようにした

当たり前ですがめちゃきれいで、背景もボケてるのでプロっぽいですw

不安は三脚に延長ポールをつけて画面の上にひょこっと出してるけど、ぐらついてちょっと怖い。。。

あ、ぐらついても手ブレ補正があるので映像には影響ないです!

マイク

これもbuild-inマイクやイヤホンマイクでもいいですが、僕の美声が台無しなのでコンデンサーマイクとアームを購入

タイプすると揺れるので、Astonのサスペンションも購入

うーん、かっこいい!

いざ〜。。。あれ、聞こえない。。。

素人で知らなかったのですが、コンデンサーマイクは単独では機能しません。。。

そう!ファンタム電源が必要なのです!あと、XLRケーブルとXLR => 3.5mmステレオ変換ケーブルをポチ

キーボード

ずっとThinkpadのキーボードを使ってましたが、赤ポチを使わないので使う意味なくない?って言われたので変えました

マウス

こちらは昔から愛用しているマウスで、トラックボールは赤玉に変えてます

最近、高速スクロールマウスがほしいのです。。。

スイッチャー and ミキサー

マルチカメラでもないし、ゲーム配信するわけでもありませんが、ATEM Miniを買ってみましたw

マイクミキサーもついてたり、映像にロゴを差し込んだりもできるので、これから活躍してくれると信じてる!

USBのスイッチングハブ

会社のラップトップとデスクトップで、同じカメラ、マイク、キーボードを使いまわしたかったのでスイッチングハブを購入

ATEM Miniの映像、音声とキーボードを切り替えてますが、ボタンひとつで切り替えできるので便利!

ディスプレイ

憧れの34インチウルトラワイド

いまんとこ、このディスプレイでVSCode、TerminalとBrowserを眺めています

湾曲しているので、目線だけで追えるのは楽かも。最初はエディタが曲がってて違和感があったけどなれた

ディスプレイの下を有効活用したかったのでアームも購入。使いやすくてお気に入り

電源周り

電源はゴチャゴチャするので、こちらに全部押し込んでます

デスク

僕はスタンディングが落ち着くので、電動昇降デスクにした

これもずっと使っている

天板はどっかで購入した

こういうのやっぱ楽しいですね。みなさんも最強のデスクトップ環境を作ってみては?

自作PC組んでみたヘ(^o^)ノ

なんかRyzenが気になったので自作PCを組んでみた

スペックはこれ!

CPU Ryzen 9 3900x
CPUクーラー NH-U12A
マザーボード MSI B550I Mini-ITX
メモリ TEAM DDR4 3200Mhz PC4-25600 32GB x 2
SSD SB-ROCKET-NVMe4-1TB
グラフィックボード ZOTAC GAMING GeForce RTX 2070 SUPER MINI
電源 SF750
PCケース LianLi TU-150WX

12core 24threads 64GB memory

このPCで何をするのか楽しみですね。。。(何するんだろ

めっちゃゲーミングPCですが、僕はそんなにゲームしない

とりあえずUbuntuセットアップして、Kubernetesであそんでみるかなー

あと、YouTubeの動画編集をDaVinci Resolveでやってみる

うーん、使いこなせない感が半端ないw

CPUクーラーは空冷ですが、NH-U12Aは空冷最強?らしく、Ryzen 9 3900xでも冷え冷えです

メモリが3200MHzで動作してないのでBiosの設定をゴニョゴニョ

Enjoy 自作PC ヘ(^o^)ノ

murajun1978的パーフェクトRoR (Chapter 1) ヘ(^o^)ノ

パーフェクト Ruby on Rails 【増補改訂版】を購入したので、僕のやり方で読み進めていきます

↓ ゴニョゴニョしたコード

github.com

Chapter 1

僕のローカルPCにはrubyはいないので、Dockerで環境構築していきます

### Dockerfile

FROM ruby:2.7.1-alpine3.12

WORKDIR /home/app
### docker-compose.yml

version: '3.8'
services:
  ruby:
    build: .
    volumes:
      - .:/home/app
    ports:
      - 3000:3000

必要最低限のDocker環境(きっとあとでゴニョります)

Dockerのコンテナにアクセスしましょ

$ docker-compose run --rm --service-ports ruby /bin/sh

Initialize

gem installが最初に書かれてますが、ぼくはbundlerおじさんなので、bunlderでinitializeします

bundlerを使ったinitializeもちゃんと書いてくれてます

$ bundle init
# Gemfile

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem "rails" # コメントアウトします

んじゃ、installしましょう

/home/app # bundle install
An error occurred while installing nokogiri (1.10.10), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before
bundling.

In Gemfile:
  rails was resolved to 6.0.3.2, which depends on
    actioncable was resolved to 6.0.3.2, which depends on
      actionpack was resolved to 6.0.3.2, which depends on
        actionview was resolved to 6.0.3.2, which depends on
          rails-dom-testing was resolved to 2.0.3, which depends on
            nokogiri

はい、nokogiriをコンパイルできないエラーですね

# Dockerfile

FROM ruby:2.7.1-alpine3.12

RUN apk add --no-cache build-base # この行を追加

WORKDIR /home/app

↑ production用のdocker imageはおいおいやっていきます

いったん、containerから抜けて再buildしましょう

/home/app # exit
$ docker-compose build

retry!

$ docker-compose run --rm --service-ports ruby /bin/sh
/home/app # bundle install

いったんnokogiriがインストールできましたね!(ちょろいな)

$ bundle exec rails -v
Rails 6.0.3.2

最新のRailsがインストールできました

Railsの思想

  • CoC 設定より規約
  • DRY 同じことを繰り返さない
    • 僕はDRYって言葉がキライです。contextが違うのにDRYにしてしまうコードがあるからです。(こういうコードにはif文があったりします)
    • 僕はD「RYにしよう」って言わなくて、「役割ごとに処理をまとめよう」(これでも微妙)って言ったりします。
  • REST

    • ResouceがURLになるようにしましょ
    • これができていないプロジェクトは、Routesにget ..., post ... みたいなroutesがあることが多いです
    • 多分、全部Resourceで表現できるはずです。。。(多分。。。
  • 自動テスト

Generate Rails project

アプリケーションの雛形を作っていきます

$ bundle exec rails new .

アプリ名を指定してもいいですが、僕はいつもcurrent dirに作成したいので.です

実行するとファイルをorverwriteしていいか聞かれるのでYRails先生に従いましょう

/home/app # bundle exec rails new .
...
An error occurred while installing sqlite3 (1.4.2), and Bundler cannot continue.
Make sure that `gem install sqlite3 -v '1.4.2' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  sqlite3
         run  bundle binstubs bundler
Could not find gem 'sqlite3 (~> 1.4)' in any of the gem sources listed in your Gemfile.
         run  bundle exec spring binstub --all
Could not find gem 'sqlite3 (~> 1.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
       rails  webpacker:install
Could not find gem 'sqlite3 (~> 1.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.

sqliteがないって怒られます

しょうがないのでインストールしましょう

# Dockerfile

FROM ruby:2.7.1-alpine3.12

RUN apk add --no-cache build-base sqlite-dev # sqlite-devを追加

WORKDIR /home/app

containerをビルドします

/home/app # exit
$ docker-compose build

containerにアクセスして、gemをインストールしましょう

$ docker-compose run --rm --service-ports ruby /bin/sh
/home/app # bundle install

sqliteもインストールできましたね!

書籍ではRailsプロジェクトのディレクトリ構成を説明してくれているので、ざっと読みます

Railsの起動

それではRailsを起動してみましょう

/home/app # bin/rails s

...
Please add gem 'tzinfo-data' to your Gemfile and run bundle install

tzinfo-dataをインストールしろって怒られました

素直にしたがいましょう

# Dockerfile

FROM ruby:2.7.1-alpine3.12

RUN apk add --no-cache build-base sqlite-dev tzdata # tzdataを追加します

WORKDIR /home/app
$ docker-compose run --rm --service-ports ruby /bin/sh
/home/app # bundle install
/home/app # bin/rails s

...
Please run rails webpacker:install

webpackerをインストールしろと怒られました(嫌な予感。。。

/home/app # bin/rails webpacker:install
sh: node: not found
sh: nodejs: not found
Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/

はい。node.jsをインストールしろと怒られる

# Dockerfile

FROM ruby:2.7.1-alpine3.12

RUN apk add --no-cache build-base sqlite-dev tzdata nodejs # nodejsを追加

WORKDIR /home/app

どんどんdocker imageのsizeが大きくなっていくね

$ docker-compose run --rm --service-ports ruby /bin/sh
/home/app # bundle install
/home/app # bin/rails webpacker:install
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/

yarnがインストールされてないって!

ちなみにぼくはnpm派

# Dockerfile

FROM ruby:2.7.1-alpine3.12

RUN apk add --no-cache build-base sqlite-dev tzdata nodejs yarn # yarnを追加

WORKDIR /home/app

yarnがインストールできましたね

$ docker-compose run --rm --service-ports ruby /bin/sh
/home/app # bundle install
/home/app # bin/rails webpacker:install

こんどこそwebpackerをinstallできました!

docker buildするたびにbundle install するのめんどくさいので、あとでやっつけましょう

/home/app # bin/rails s -b 0.0.0.0

f:id:murajun1978:20200728010115p:plain

きた!

Scaffold

書籍ではtaskモデルを作成するみたいですね。やってみましょう。

/home/app # bin/rails  g scaffold task content:text
      invoke  active_record
      create    db/migrate/20200727160336_create_tasks.rb
      create    app/models/task.rb
      invoke    test_unit
      create      test/models/task_test.rb
      create      test/fixtures/tasks.yml
      invoke  resource_route
       route    resources :tasks
      invoke  scaffold_controller
      create    app/controllers/tasks_controller.rb
      invoke    erb
      create      app/views/tasks
      create      app/views/tasks/index.html.erb
      create      app/views/tasks/edit.html.erb
      create      app/views/tasks/show.html.erb
      create      app/views/tasks/new.html.erb
      create      app/views/tasks/_form.html.erb
      invoke    test_unit
      create      test/controllers/tasks_controller_test.rb
      create      test/system/tasks_test.rb
      invoke    helper
      create      app/helpers/tasks_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/tasks/index.json.jbuilder
      create      app/views/tasks/show.json.jbuilder
      create      app/views/tasks/_task.json.jbuilder
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/tasks.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

作成できました!

これをDatabaseに反映しましょう

/home/app # bin/rails  migrate
== 20200727160336 CreateTasks: migrating ======================================
-- create_table(:tasks)
   -> 0.0017s
== 20200727160336 CreateTasks: migrated (0.0021s) =============================

テーブルが作成されました!

Rails サーバーを起動して、画面から登録したらり、削除したりしてみましょう

/home/app # bin/rails  s -b 0.0.0.0

起動したら、http://localhost:3000/tasks へアクセスしてみましょう

f:id:murajun1978:20200728010813p:plain

データの新規登録、更新、削除などいろいろ試してみてください

まとめ

以上でChapter 1は終了です。

細かい説明はすっ飛ばしましたが、こんな感じでエラーでたら対応してトライみたいな感じです。

ま、いろんなブログには正解が最初に書いてあるので、コピーするのもいいですけど、エラーメッセージをちゃんと読んで対処していくのがオススメです!

また続きを書くので、よかったら見てください!

参考にはならないかもしれませんが。。。

Enjoy パーフェクトRuby on Rails ヘ(^o^)ノ

gooberでtailwindcssを使うヘ(^o^)ノ

前の記事でNext.jsでgooberを導入してみました

murajun1978.hatenadiary.com

今回はgooberでtailwindcssを使ってみます

Next.jsにtailwindのセットアップしていきましょう

$ npm install @tailwindcssinjs/macro @tailwindcss/ui tailwindcss
$ npm install -D @babel/core babel-plugin-macros
// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme');

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  variants: {},
  plugins: [require('@tailwindcss/ui')],
};
// babel.config.js
module.exports = {
  presets: ['next/babel'],
  plugins: ['macros'],
};

これでsetupはOKです

んじゃ、使ってみましょう

// src/pages/index.tsx
import { NextPage } from 'next';
import { styled } from 'goober';
import tw from '@tailwindcssinjs/macro';

const styles = {
  button: tw`
    relative
    w-64 min-w-full
    flex justify-center
    py-2 px-4
    border border-transparent
    text-sm leading-5 font-medium
    rounded-md
    text-white
    bg-teal-600
    hover:bg-teal-500
    focus[outline-none border-teal-700 shadow-outline-teal]
    active:bg-teal-700
    transition duration-150 ease-in-out
  `,
};

const Button = styled('button')(() => styles.button);

const Home: NextPage = () => <Button>button</Button>;

f:id:murajun1978:20200704093804p:plain

動かして確認するとわかると思いますが、一部のスタイルがあたっていないと思います

backgrand-colorですね

理由はtailwindcssinjs/macroではcros-browser対応するためにfallbacksというsyntaxを使っています

{
  ...
  backgroundColor: ["#047481", "rgba(4, 116, 129, var(--bg-opacity))"]
  ...
}

tailwindcssinjs/macroの出力は👆のように配列になってます

これがgooberにはわからないんですね

解決方法はtailwindcssinjs/macroのREADMEに書いてあります

github.com

tailwindcssinjsのpluginで出力フォーマットを変更できるみたいです!

CSSのStringで出力するpluginを導入してみましょう

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme');

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  variants: {},
  plugins: [require('@tailwindcss/ui')],
  tailwindcssinjs: { // ここ追加
    plugins: [require('@tailwindcssinjs/macro/lib/plugins/cssString').default],
  },
};

f:id:murajun1978:20200704093731p:plain

スタイルがあたりました!

Enjoy goober + tailwindcss ヘ(^o^)ノ

Next.jsでgooberを使ってみるヘ(^o^)ノ

はじめに

gooberというcss-in-jsのパッケージがあります

github.com

使い勝手はstyled-componentsとか、emotionなんかと同じです

ただ、パッケージのファイルサイズがびっくりの1KBです😆

このサイズは魅力的なので、Next.jsで使ってみましょう

Installation

$ npm install goober@next

最新がほしいのでnextバージョンを指定しました

Using with Next.js

コンポーネントを作成します

// components/HeadingTitle.tsx
import { styled } from 'goober';

export const HeadingTitle = styled('h1')`
  color: blue;
`;

Homeページで使ってみます 

// pages/index.tsx
import { NextPage } from 'next';
import { HeadingTitle } from '../components/HeadingTitle';

const Home: NextPage = () => (
  <HeadingTitle>Welcome goober with Next.js</HeadingTitle>
);

export default Home;

んじゃ、確認。。。あれ、rerenderエラーが。。。

Next.jsはpre-renderがデフォルトなので、SSR用の設定しないといけないみたいです

// pages/_app.tsx
import { createElement } from 'react';
import { setup } from 'goober';

const App = ({ Component, pageProps }) => {
  setup(createElement); // setup goober for SSR

  return (
    <Component {...pageProps} />
  );
};

export default App;

あらためて、動作確認

<head>
  ...
  <style id="_goober"> .go2445103859{color:blue;}</style>
</head>
<body>
  ...
  <h1 class="go2445103859">Welcome goober with Next.js</h1>
  ...
</body>

ちゃんとstyleがあたってますね 👍

まとめ

めちゃ簡単にNext.jsに導入できました

これで更にファイルサイズを小さく抑えることができそうですね

Enjoy goober ヘ(^o^)ノ

Prisma2で指定できるIDのType

Prisma2で指定可能なIDのTypeはドキュメントに書いてあります

www.prisma.io

// integerでautoincrementする
model User {
  id Int  @id @default(autoincrement())
  name String
}

{
  id: 1,
  name: "murajun1978"
}

// cuidを使う
model User {
  id String @id @default(cuid())
  name String
}

{
  id: "ckbnw8uvi0000aloy4biot7rc",
  name: "murajun1978"
}

// uuidを使う
model User {
  id String @id @default(uuid())
  name String
}

{
  id: "dd85a66b-95b0-498f-b188-aafee97facc9",
  name: "murajun1978"
}

Prisma2は、十分productionで使えるレベルではあると思います

絶賛、RailsからNext.js + GraphQL + Prisma2へリプレイス中

Enjoy Prisma2 ヘ(^o^)ノ

CloudflareのImage Resizingを使ってプレースホルダ画像として表示する

はじめに

Next.jsではpre-renderがデフォルトです。

pre-renderとは、server side renderingとclient side renderingの中間的な存在。(雑な説明です

みなさんはMediumってブログを見たことありますか?

Mediumの記事は画像がピンぼけして、すこしたってからきれいな画像に差し替わりますよね?あんな感じです。

解像度のあらーい画像(数バイト)をしゅっとダウンロードして、それをピンぼけ状態で表示します。

んで、裏ではOriginをダウンロードしていて、完了したときに差し替えるって仕組みです。

これを実現するためには、プレースホルダ用の画像とoriginの両方の画像が必要になります。

いちいち、両方の画像を用意するのは面倒ですよね?ね?

そこでCloudflareのImage Resizingです。

Image Resizing

ビジネスプラン以上にアップグレードして、ぽちっとするだけで利用可能になります。

f:id:murajun1978:20200610214144p:plain

実際に試してみましょう。

画像のURLがこんなだとします。

https://www.murajun1978.dev/images/profile_image.jpeg

f:id:murajun1978:20200610214504p:plain

小さくてみにくいですが、8.3kbの画像です。

これくらい小さいと気にはなりませんが、もっと解像度を下げて小さくしてみましょう。

URLはこんな感じになります。

https://www.murajun1978.dev/cdn-cgi/image/width=5,height=5,quality=5/images/profile_image.jpeg

f:id:murajun1978:20200610221312p:plain

画像は小さくて見えないですよね。。。

↑のオプションを設定しましたところ、875bまで小さくなりました。

ちなみにWebPにも対応してます。

詳しい使い方はこちらを参考にしてください。

まとめ

Reactのsuspenseとかを使うと簡単に実装できますよ。

pre-render時は、CSSのopacityを0.5とかに設定して、画像をぼかして表示します。

で、Origin画像のダウンロードが完了したら、Origin画像が表示されます。

ちょー楽勝ですね!

料金ですが、ビジネスプランは$200/月です。

ビジネスプランでImage Resizingを使う場合、10万リクエストまでは追加料金なしで利用できます。

10万リクエストを超えるたびに$10かかります。

ま、個人のサイトに$200/月はちょっとお高い気もしますが、Image Resizingだけではなく、その他の機能ももりもりついてきます。

前回紹介したWorkersでも利用できるますよ。

Cloudflareをフル活用して、いい感じに手を抜きたい人は、ビジネスプランにアップグレードしてみては?

Enjoy Cloudflare Image Resizing ヘ(^o^)ノ