gooberでtailwindcssを使うヘ(^o^)ノ
前の記事でNext.jsでgooberを導入してみました
今回は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>;
動かして確認するとわかると思いますが、一部のスタイルがあたっていないと思います
backgrand-colorですね
理由はtailwindcssinjs/macroではcros-browser対応するためにfallbacksというsyntaxを使っています
{ ... backgroundColor: ["#047481", "rgba(4, 116, 129, var(--bg-opacity))"] ... }
tailwindcssinjs/macroの出力は👆のように配列になってます
これがgooberにはわからないんですね
解決方法はtailwindcssinjs/macroのREADMEに書いてあります
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], }, };
スタイルがあたりました!
Enjoy goober + tailwindcss ヘ(^o^)ノ
Next.jsでgooberを使ってみるヘ(^o^)ノ
はじめに
gooberというcss-in-jsのパッケージがあります
使い勝手は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はドキュメントに書いてあります
// 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
ビジネスプラン以上にアップグレードして、ぽちっとするだけで利用可能になります。
実際に試してみましょう。
画像のURLがこんなだとします。
https://www.murajun1978.dev/images/profile_image.jpeg
小さくてみにくいですが、8.3kbの画像です。
これくらい小さいと気にはなりませんが、もっと解像度を下げて小さくしてみましょう。
URLはこんな感じになります。
https://www.murajun1978.dev/cdn-cgi/image/width=5,height=5,quality=5/images/profile_image.jpeg
画像は小さくて見えないですよね。。。
↑のオプションを設定しましたところ、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^)ノ
Next.jsをCloudflare workersから配信したい! Part 2
はじめに
Part 1では workder.devにデプロイするところまでやったよね
Part2ではproductionにデプロイして、KVを使ってみましょう
Productionデプロイ
productionにデプロイする前にやることがあります。
それはAレコードの登録です。
例えば、"www.murajun1978.dev"へのリクエストをworkersに託すって設定をしないといけない。
でも、こんなのは5秒で終わる(反映するまでに5分以上かかるときがあります)
CloudflareのDNSにAレコードを追加します!
こんな感じ
次にデプロイ設定をwrangler.toml
に追記します。
ここでちょっと気をつけてほしいこと
デプロイでローカル環境で実行することはほぼないですよね?だいたいはCIでデプロイします。
CIでデプロイするってことは、GitHubなんかにデプロイするってことですよね?
そこにAPI Tokenをコミットすると。。。ね。。。
はい、wranglerには環境変数が用意されています。こちらを使うのが推奨というか、使おうね
僕はDokcerを使ってるので↓のように設定しました
# docker-compose.yml version: '3.8' services: node: build: . volumes: - .:/home/app ports: - 3000:3000 env_file: - wrangler.env
# wrangler.env CF_API_TOKEN=<YOUR API TOKEN> CF_ACCOUNT_ID=<YOUR ACCOUNT ID> CF_ZONE_ID=<YOUR ZONE ID>
んで、gitignoreにwrangler.envを追加しときましょー
CIにも↑の環境変数を設定すればOKです。
これで安心!
さ、productionの設定を追記しよう
# wrangler.toml name = "dev-site" type = "webpack" workers_dev = true route = "" [site] bucket = "./out" entry-point = "workers-site" [env.production] # プロダクション用の設定 route = "www.murajun1978.dev/*"
routeを追加するだけです!
この設定で、www.murajun1978.dev/のすべてのリクエストがworkersに転送されます
Productionデプロイ
$ npx wrangler publish --env production
やばい、簡単すぎる。。。
Cloudflareで確認するとこんな感じ
これでProductionにデプロイできました。
ここでちょっとKVを見てみましょ
ファイル名がKEYになってて、値にはファイルのHTMLやJS、CSSなんかが格納されています。
デプロイ時に、KVにKEY ファイル名 値: HTMLやJSを格納して、Edge serverから参照できるようにしているってことですね。
なので、アクセスするたびに、workersのアクセスカウントが++されていきますw
そう、HTML、JS、CSSファイルにアクセスするたびにねw
金額はささいなものなので、気にはなりませんが(少なくとも僕は)、完全無料でブログを公開したい、もしくはもっと手抜きしたい場合は、NetlifyやVercelを使うって選択になりそうですね.。
GitHub連携できるのも敷居が一気にさがります。
KVにcurrent versionを設定する
これ、やろうと思ったのですが、なんか微妙だったので僕は見送りました。
切り戻したいときはrevertすればいいかなと、とはいえKVに値をセットしてみましょ(とりあえず
まずは、KVのnamespaceを設定する必要があります
# wrangler.toml kv-namespaces = [ { binding = "CONTROL", id = <YOUR KV ID>} ] [env.production] route = <YOUR ROUTE> kv-namespaces = [ { binding = "CONTROL", id = <YOUR PRODUCTION KV ID>} ]
KV IDってのは↓です
んじゃ、KVにセットしてみましょう
$ npx wrangler kv:key put --binding=CONTROL "putting test" "test"
はい、登録できましたね!
まとめ
Cloudflare workersを2記事にまとめてみました。
マジで簡単。
ちなみに、悶絶雑なページをlighthouseで計測してみました!
Next.js + Preactなら楽勝で100Pointsですよw
近々、ブログもこちらに移行する予定です
おそらく、Vercelを使うことになると思います。
次はCloudflareのImage Resizingを使ってみようかなー
サイトはVercelから配信して、画像はS3やCloud Storageにアップロードしたものを、Cloudflareから配信するって感じです。
pre-renderするときに、画質を落としてぼかした画像を表示しておいて、裏でダウンロードが完了したら、ちゃんとした画像に差し替えるって感じですかね。(Mediumと同じやつです
こうご期待w
Enjoy Cloudflare workers ヘ(^o^)ノ
Next.jsをCloudflare workersから配信したい! Part 1
みなさま、Cloudflare workersってご存じですか?
90カ国 200都市のデータセンターで動いてるEdge serverです。
service workerのEdge server版ってとこです。
S3やCloud StorageのファイルをCDN経由で配信?
ま、それも悪くないですが、Edge serverでパッと処理してシュッと返してあげましょ!S3もCloud Storageも不要です(ヤッタ
Edge serverだから、クライアントの一番近いところで動いているので、爆速でHTMLをreponseを返すことができます。
キャッシュコントロールも可能なので、さらに爆速!Preactで更にドン!
そんな誘惑にこころ動かされたので試してみます。
注意!Workers Sitesを使うので、Cloudflare workersの有料プランである必要があります💰($5/月)
ではやってみましょう💨
Next.js
$ npx create-next-app
以上
wrangler
Cloudflare workersのCLIです。
インストール
$ npm install -D @cloudflare/wrangler
初期設定
CloudflareのアカウントIDとゾーンIDとAPI Tokenが必要です。
アカウントIDとゾーンIDは、Cloudflareのダッシュボードに表示されてるのでメモ。
API Tokenはworkers用のトークンを作成します。
こちらもダッシュボードに"API トークンを取得"ってリンクがあるので、そこからAPIトークンを作成します。
$ npx wrangler config Enter API Token:
さきほど作成したAPI Tokenを入力して終了でっす。
Siteの作成
workers siteを作成します。
$ npx wrangler init --site hello-next-worker
workers-siteってディレクトリとwrangler.tomlが作成されたはずです。
name = "hello-next-worker" type = "webpack" account_id = <あなたのアカウトID> workers_dev = true route = "" zone_id = <あなたのゾーンID> [site] bucket = "./out" entry-point = "workers-site"
account_id, zoon_idを設定します。
bucketにはNext.jsのbuildディレクトリを指定します。
これでwranglerの設定は完了です。簡単!
ビルド
Next.jsでbuildします📦
$ npx next build $ npx next export
Publish
workers devにpublishします。ProductionへのpublishはPart 2で。
$ npx wrangler publish
これで、https://hello-next-worker.<あなたのドメイン>.workers.dev
にpublishできるはずです🎉
まとめ
以上で、Next.jsのbuildしたファイルをCloudflare workers siteにpublishして、Edge serverから配信することができました!
どうでしょう?簡単でしたよね?
Part 2では、ProductionへのpublishとKVを使って、前のバージョンに切り戻したりしてみます。
Enjoy Cloudflare workers ヘ(^o^)ノ
Traefikでdocker-composeのポート重複を解決する
昨日のDockerCon LiveのセッションでTraefikの存在を知ってしまったので、ちょっと試してみました😄
同一プロジェクト、または複数のプロジェクト間でportがかぶってちょっとずつ変えているなどなど
例) App1では3000ポートをApp2でも3000ポートを使っている
僕もいままでは、App2を4000ポートに変更して対応していました
"Simplify All the Things with Docker Compose" @mikesir87 さんのセッションを見て面白かったので試してみます
Thanks a lot, mikesir87👍
僕のサンプルアプリ
ちょっと調子のってDenoで書いてみましたw
1つのプロジェクトにApp1とApp2のサーバが3000ポートでサーバが立ってます
これをTraefikを使ってProxyしてみます
サンプルコードをみてもらったら、一目瞭然なので詳しい説明はしませんが(しないのかよ!)
ハマったこと
僕がちょっとハマったことを書いておきます
僕の開発環境はLinux + Rootless dockerです
Rootless dockerがちょっとハマりました。。。
公式ドキュメントのサンプルとかでは、80番ポートでProxyしてるのですが、Rootless dockerはrootユーザで起動してないので、 localhostの80番ポートが使えなかったです😭
なので、僕のサンプルコードでは3000番ポートをリッスンするようにしてます
あとは、socketファイルのパスが違うことですね、DOCKER_HOSTを確認してくださいね
$ echo $DOCKER_HOST unix:///run/user/1000/docker.sock
動作確認
コンテナを起動します
$ docker-compose up -d
app1.localhost:3000にアクセスしてみます
app2.localhost:3000にもアクセスしてみます
まとめ
どうでしょうか、めちゃ簡単にProxyできましたね👏
同一プロジェクトでは旨味はありませんが、プロジェクトをまたがる場合は重宝しそうです
プロジェクトをまたぐ場合は、Traefikをdeamonで動作させて、Traefikのnetworkをexportしておけばいいと思います
各プロジェクトでは、このネットワークに接続することで、Proxyできるようになります
もうポートを気にする必要はない!
Enjoy Traefik ヘ(^o^)ノ