Zennの技術まわりの質問があれば答えるよ
「あれどうやって実装してるの?」などなどの技術的な質問だけ受け付けます!
「こういう機能がほしい」みたいな要望はここではお答えしません。
スクラップ機能、とても良さそうです。一利用者としてありがとうございます。
一般的な話かもしれないのですが、通知機構について伺いたいです。
-
通知は様々な種類があると思うのですが(Likeされた、Commentされた等)、これらはどのような形式で永続化されているのでしょうか?
RDBを使うやり方を単純に考えると、通知テーブルを用意して通知内容のオブジェクト(文字列?)をシリアライズしたものをtextカラムに保存したり、jsonカラムに保存したりするのかなと思いますが、もっと上手なやり方があるのかや、どのようなデータベースを使われているのか気になりました。 -
永続化の際はイベント駆動などで何かしら非同期的な機構が走っているのかと予想しますが、実際に使われているシステムやアーキテクチャなども参考にしたいです
いろいろ書いてしまいましたが、可能な範囲でお答えいただけたら嬉しいです。
スクラップについてまだ周知していない段階で見つけていただきありがとうございますw
(どうやって気づかれたのか気になります)
通知はけっこう苦労した部分です。仰る通りオブジェクトの種類(Article, Book, Comment, User)が多いんですよね。
Zennの場合、notification
というテーブルがあって、通知が必要になったタイミングでnotifiable_type
とnotifiable_id
に通知に関連するアイテムの情報を入れています。合わせて通知の種類と、通知先のuser_idなども保存しています。
例えば「あなたの記事にコメントがつきました」と通知したい場合、こんなイメージでレコードが追加されます。
notifiable_type: "Article"
notifiable_id: コメントがついた記事のID
user_id: 通知先のユーザーID
action: "commented" # コメントがついたという意味で
notified_from_user_id: 通知元のユーザーID(nullのこともある)
メール通知については、15分おきとかにバッチ処理でread:false
(既読済みかどうかのフラグ)となっているものを(ユーザーの通知設定がONになっている項目のみ)一括で送るようにしています。
現状こんな感じですが、もっと良い方法はあるような気がしてます。
永続化の際はイベント駆動などで何かしら非同期的な機構が走っているのかと予想しますが、実際に使われているシステムやアーキテクチャなども参考にしたいです
バックエンドにはRails(on App Engine) + PostgreSQL(on CloudSQL)を使っています。Railsだと非同期処理についてはSidekiq(+ Redis)を使うのが一般的だと思うのですが、サービスのリリース直前までApp EngineではなくCloudRunにデプロイしていた関係で、Sidekiqなどにより非同期処理は使っていません。
関連
現時点では通知なども同期的に永続化しており、負荷の大きいタスクは定期的なバッチ処理で対応していたりします(タスク用のApp Engineインスタンスを作っています)
ただ、既に限界は感じているので、このあたりは今後着手しようと思っています。
勝手に使わせていただきすみませんw
catnoseさんのユーザーページのコメントタブでたまたま発見して、新機能のようだったので少し興奮してしまいました笑
なるほど!テーブル設計までありがとうございます、参考になります。バッチ処理と同期処理を使い分けられてるんですね。
ついでに思い出したので、もう一つだけ。Like判定に特化したAPIが用意されているようで最初ほうっと思ったのですが、この辺りはISRとユーザー認証をうまく共存させる工夫でしょうか? UGC型のサービスでISRを活用するための一つの指針となりそうな解決法ですね。
なるほど!ミスってしばらくコメント一覧に出ちゃってたんですよねw
まさにその通りです。ごく一部を除いて認証が絡む部分はクライアントでマウントされてからリクエストしています。「Incremental Static Regeneration」のようにガッツリとページをキャッシュする場合、そのあたりが少し面倒になりますね…。
一応他の手段として、キャッシュするデータに「LikeしたユーザーのID一覧」を含めて、クライアント側でログインユーザーのIDと一致するか検証する方法も検討したのですが、その場合Likeした直後にページをリロードするとLikeしていないことになってしまうという問題があり、このようにしています。
Local Storageなどを使えばクリアできる問題とは思いますが、あまり複雑にしたくなかったので現状こんな感じにしています。同じ構成のサービスがどうしているのか気になるところです。
なるほど〜面白いですね。シンプルで良さげな方法だなと思いました。まだISRを活用したサービスって少なそうなので今後ベストプラクティス的なものが確立されていくのか楽しみですね。
色々とご教授ありがとうございました!サービス共に末長く活用させていただきます。
zenn-editorやその他の部分で現状テストはどれくらい用意してらっしゃいますか?また使用予定のlibraryなどありますか?
Contributeしたい時に、どうしてもテストが無いと不安になってしまうので、可能なら暇な時間にテストを書いてプルリクエストを投げたいのと、純粋に自分が初心者なので社会人の方々のそういった環境が気になる、ということで質問させていただきました。
Webアプリ(zenn.dev)の方はバックエンドを中心にテストを書いています。カバレッジは測っていませんが、主要な部分はだいたいカバーできているんじゃないかと思います。
すみません、zenn-editor
ではまったくテストを書いてません。書きたいと思っていたのですが、色々と急いでいたので…。そして書こうと思っているのですがまだ着手できていません。
純粋に自分が初心者なので社会人の方々のそういった環境が気になる
これは社会人として参考にするべき例ではないです。個人開発だからこんな感じですが、本来最初から書くべきだと思います。
(もうすぐ個人開発じゃなくなりそうなのでちゃんと書く予定です。はい)
可能なら暇な時間にテストを書いてプルリクエストを投げたい
ありがたいお話ではあるのですが、あくまでもzenn-editor
はzenn.dev
依存のものなので申し訳ないです。もっと幅広く使われているOSSへ貢献した方が実績/勉強になると思います。
時間が出来たらテストは書く予定です。すみません、はい。
(「時間は作るもの」ですよね。すみません、はい。)
お忙しい中すみません、ご返事いただきありがとうございます
catnoseさんがほぼ一人でやっていらっしゃるとの事ですので、より優先順位の高いサービスの重要なところから実装していくのは当然の事だと思います。急かすみたいな形になってしまいすみません。
ありがたいお話ではあるのですが、あくまでもzenn-editorはzenn.dev依存のものなので申し訳ないです。もっと幅広く使われているOSSへ貢献した方が実績/勉強になると思います。
純粋に自分が普段使わせていただいているもの/見ているものに対しまずは貢献/勉強したいなと思っていました、ただそれこそお忙しいでしょうし個人のプルリクエストに時間を割いていただくのも申し訳ないのと他の部分に時間を割くべきというのがありますよね、ごめんなさい。
いえ、プルリクについてはありがたさしかないです!ただあまり時間を取っていただいちゃうと、手数料を取っている商用サービスなのに対価をお支払いできずすみません…ってなりますw
後から見た人のために追記)zenn-editorもテストちゃんと書き始めました
記事や本の検索機能、サジェストについてどのように実現させているのか気になります!
また、PostgreSQLを採用した理由も可能であれば伺いたいです。(自分がmysqlしか使ってこなかったので・・・)
Next.jsのSSRということで、 getServerSideProps
を実装していると思うのですが getServerSideProps
でのランタイムエラーは上位コンポーネントの componentDidCatch
で取れない中で、そこら辺のエラーハンドリングについてどうやって抽象化したりしてるか知りたいです!
getServerSideProps
使おうと思っていたのですが、色々比較してみたところgetInitialProps
の方がページ遷移時の体験が良かったので現状ではgetInitialProps
を使っています。
(エラーハンドリングはどちらも同じようになると思います)
イメージ的には以下のようなことをやっています(色々抜粋)。
type Props = {
posts: Post[];
errorCode?: number;
}
function Page(props: Props) {
if(props.errorCode) return <Error status={props.errorCode} />; // エラー用のコンポーネント
return <div>色々</div>
}
Page.getInitialProps = async (ctx) => {
try {
const { posts } = await requestSomething();
return {
posts,
}
} catch(err) {
const errorCode = err.response?.status || 500;
return {
errorCode
}
}
}
export default Page;
ここでは省いていますが、エラーコード周りの型はTypeScriptのユニオン型で「あるかもしれない」プロパティを表現するときのTipsのような形で表現しています。
やっぱそうですよね。cDCはランタイムだけで起きた予期しないエラーにより画面が真っ白になるために置いておくが、基本的にstatusCode的なのをreturnしてコンポーネント側でnext/errorを返すみたいな実装ですよね...
ありがとうございます!少し自信が持てました!
素晴らしいサービスとそのオープンな情報を大変ありがたく参考にさせてもらっています。
認証周りについてnextjsとbackend apiを利用するパターンでどのように行うべきか、なかなか情報が出てこず迷っています。
nextjs とnextjs の api route を利用する形なら next-auth が便利そうですが、rails apiとnedxtjsを使われているzennはどのように実装されているんでしょうか?
(fastifyあたりを使ってみたいのですが、ぜひ参考にさせてもらえればと思い質問しました。)
nextjs とnextjs の api route を利用する形なら next-auth が便利そう
同意です。小規模のアプリであればこの形が良さそうだと思っています。
blitzを使ったりするとそのあたりも気軽にできたりするのかも…?(まだ触っていないので分からないですが)
僕なら今小規模なサービスを作るならDBはFirestoreやMongoDB Atlasとかにして、認証はFirebase Authenticationに任せてしまう気がします。
ZennのRails APIは2020年12月時点ではdeviseというgemを使ってcookieによるセッション認証を行っています。セキュリティのためにcookieはhttp-onlyにしたりとごく一般的な実装です。
ただ現在NestJSへのリプレイスを検討しています。その場合はpassportという定番ライブラリを使うことになりそうです。
的はずれな質問でしたら申し訳ないです。
バックエンドとフロントエンドの通信間のセキュリティについてですが、どのようにしているのでしょうか?
apikeyやcorsなど、、、
アイコンなどはインラインSVGを使い、CSSModulesのclassでスタイルを当てていると思うのですが、
SVGをアイコン毎にコンポーネント化しているのか、babel-plugin-inline-react-svgなどでインポートしているのか、その他か、どのように管理されているかを教えていただきたいです。
また、その方法でクラスの当て方はどうされているのでしょうか?
Nextjsを利用しているプロジェクトでSVGの管理に悩んでおりますので質問させていただきました。
react-svg-loaderを使っています。使い方はごく普通で以下のような感じですね。
import SvgPencil from '@assets/svg/pencil.svg';
<SvgPencil width={50} height={50} class={styles.editIcon} />
とても助かりました!
お忙しい中、ありがとうございます!
Zennの記事ページはISRではなくSSRでしょうか?
ISRだと思っていたのですが、記事の編集が即時で反映されたので気になりました。
2つお聞きしたいことがあります!
- Editor部分でMonacoではなくCodeMirrorを利用している理由が知りたいです。
- ユーザー認証でAuth0のような認証Saasを利用されていないのには理由がありますか?
よろしくお願いします!
いつもZennにはお世話になってます!
Next.jsについて一点お聞きしたいことがあります。
ベーシックにページコンポーネントを作ると、ページ間で同じコンポーネントを使っててもページごとに全ての要素が再レンダリングされるため、.explore_navLink
でやっているようなトランジションは実現できないと思います。
簡単にどうにかするなら_app.tsx
に共通コンポーネントを置けばいいとは思うのですが、なんとなく別のやり方をしてらっしゃる気がして、教えていただけたら幸いです。
(他にも何パターンか自分の中でやり方は見つけてはいるのですが、イマイチやり方にしっくりこず。。)
技術周りではないですが、UIに関して一つ質問があります。
英語と日本語が混在していると思うのですが(Add New だったり)、その辺ってどうやって使い分けているのでしょうか?ここは日本語、ここは英語、、みたいなことってそもそもしているんですかね?
よろしくお願いします。
分かりづらくてすみません。
まず、できれば全部英語にしたいという思いがあります。その方がきれいに見えるので。ただ、ユーザーさんが何の操作なのか分からない可能性があるなと感じた部分は(本当はあまりしたくないのですが)日本語にしています。
ちなみにリリースから少しずつ英語を日本語に書き換えていっています。最初はパッと見たときにカッコいい方が目を引いてユーザーが集まりやすい気がしますが、だんだんと見慣れてパッと見のカッコよさより分かりやすさの方が重要になるんじゃないか、という考えです。
なるほど!!ありがとうございます。分かりづらいとかでは全くなくて、自分もプロダクト作るときに表記に迷うところでもあり、zenn ではどうしてるのかな〜ってふわっと思っただけです!!お時間いただきありがとうございました!!
Zennに限ったことではないのですがZennも対応をしてたので2点質問があります。
1: 例えば記事の https://zenn.dev/catnose99/articles/c7754ba6e4adac
のページで、この記事では
<link rel="canonical" href="https://zenn.dev/catnose99/articles/c7754ba6e4adac">
の設定がしてありますがこれはなぜ行っているのでしょうか?
2: またこのscrapのページのURLは https://zenn.dev/catnose99/scraps/468bedaab6dbe3ecfcae
ですがこのページに対しては canonical
の設定を行っていません。この2つの差はなんなのか気になりました!
1の答え、Twitterで教えてもらいました、、
Zennも同じかと思います
1はこのツイートのとおりです!
- utm とかのクエリパラメータが色々つくケースがあるので統一したい
- 明示的に防がない場合 PaaS などが提供する http://web.app や http://vercel.app みたいなドメインも一応あるので重複扱いにならないようにしておきたい
2は多分ミスです。見落としてました…。ありがとうございます。
Vercelを活用しているかと思います。Vercelに関していくつか質問があります。
- PlanはProとEnterpriseのどちらでしょうか。
- Vercelから別サービスへの移行などは予定されていますでしょうか。
- (Pro Planの場合)BandWidthが1TBという上限がありますが、何か削減のための工夫などは実施していますでしょうか。
技術的なことだけでなくビジネス的な要素も含みますが、可能な範囲で回答よろしくお願いします。
- Proプランを使っています。
- 他サービスへの移行は予定していません。やはりNext.jsの色々な機能を使う際の検証コストが小さくて楽なので…。ただ危機感は持っていて、いざというときは移行する心の準備はできています。
- そこなんですよね。アクセスが増えてもEnterpriseの規模ではないので1TBに納める必要があります。現時点ではまだ余裕がありますが、増えないように気をつけています。たとえば以下の部分ですね
- next/imageは使っていない。使うことになってもCloudinaryを通す予定
- API Routesを使えば楽な部分でもCloud Functionsを使うようにしている
あとはアレですね。Proプランで収まらなくなったときにはクラスメソッド社の力を使えば(交渉などで)何とかなるかもしれない…というわずかな希望も持ってます笑
回答ありがとうございます!
- Proだとかなりコスパいいと感じますね。Password Protectionが割高ですが。
- 同感です。例えば今後も React Sercer Components + Vercel + Next.js などの相性などを考えると、なるべくVercelを活用したいと考えています。
- Enterprise Planについて問い合わせをVercelサポートにしているのですがかなり割高と感じました。なるべくPro Planに抑えたいと考えていたので助かりました。next/imageやAPI RoutesはやはりBandwidthを大きく消費するのでこの観点だとなるべく避けたいですよね。
Proプランで収まらなくなったときにはクラスメソッド社の力を使えば何とかなるかもしれない…
Enterprise Planの国内事例を殆どしらないので楽しみにしてます!
Zennを作るのにかかった時間を知りたいです...! リリースでここまで完成度が高い、個人開発のサービスを初めて見ました。よろしくお願いします。
いつも利用させて頂いています!素敵なサービスありがとうございます!
Zennの機能の技術的な何かというよりは、技術選定についての質問です。
ZennのCSSはCSS Modulesを利用されていると以下Scrapで拝見しました。
経緯的には styled-components ▶ linaria(試すのみ) ▶ CSS Modules
となったようなのですが、その際にVercelが開発していてNext.jsに標準で組み込まれている Styled JSX は選択肢には上がらなかったのでしょうか?
もし、上がった上で候補から外したのならその理由など知りたいです :pray:
(新規でNext.jsのサービスを検討中でそのCSS設計の参考にさせて頂きたく。。)
ありがとうございます!
一応試したような気がしますが、ほとんど検討しなかったですね…。今思うと悪くない選択肢かも?
ただ、コンポーネントのjsx部分が膨らむのは気になりますね。そこも分割出来るのかもですが。うーん、もう少しちゃんと検討するべきでしたw
うおお!早速回答ありがとうございます!!感謝です。
そうだったのですね。
ただ、コンポーネントのjsx部分が膨らむのは気になりますね。そこも分割出来るのかもですが。
実は外出しも出来るようで、その問題は解消できるかもです。
ReactはCSS周りの選択肢多くて迷いますね〜。。
catnoseさんの記事も参考に色々検討したいと思います。
zenn-cliとzenn.devとの整合性はどうやって取っているのでしょうか?気を付けないと、zenn-cliでローカルで編集したときと、本番に上げたときで表示が異なることがありそうなのですが、その辺、どのように頑張っているのか教えて下さい。
zennでは、ssgを使用してるページはありますか?
また、CSR,SSR,SSG,ISRそれぞれどんな風に使い分けていますか?
※ 略語に馴染みがない方のために括弧で正式名称を書いておきます。
利用規約やプライバシーポリシー、AboutページなどはSSG(Static Site Generation)を使用しています。使い分けとしては
- ダッシュボードなどのログインユーザーのみ閲覧ができるページ => CSR(Client Side Rendering)
- SEO上重要かつページネーションが必要な一覧ページ => SSR(Server Side Rendering)
- スクラップのように更新頻度が高いページ => SSR
- 記事や本などの速度が重要なページ => ISR(Incremental Static Regeneration)
という感じです。
回答ありがとうございます!!
次いでリプライ失礼します
- 現在はどのようなページ構成になっていますか?
Next.jsアプリをVercelからGoogle Cloudに移行した話
キャッシュを廃止した記述
なお、記事や本の詳細ページなどでは、キャッシュの設定を誤ったときのリスクの大きさからキャッシュ自体を廃止することにしました。(ソースコードの見通しが良くなった!)
少し前の記事ですが、zennではISRを廃止し、stale-while-revalidate(SWR)などを使って代替的に実装していくと書かれていて現在のページの構成を教えていただきたいです!
ちなみに、個人開発で有料ブログサービスを開発中なので特にBooksの構成が気になります!
- 有料Booksを非購入者では閲覧できなくする工夫を教えてください
有料ページを下手にISRなどでデータ取得してしまうと非購入者でもdevtoolで内容を見ることができてしまうなどの問題があり、zennの有料Booksではどのように購入者,非購入者を判断し、表示を分けているのか教えていただけるとありがたいです!
決済周りについてのご質問です。
Zennは本の売買やサポートを行う際に、Stripeを利用して決済などが行われている認識なのですが、この時にどのようなStripeの機能を利用して、決済から振込まで行っているのでしょうか?
例
- Paymentsのみで、売上を運営が管理し、決済から振り込みまで実行
- PaymentsとConnectを利用して、売上をユーザーが管理し、決済から振り込みまでを実行
こちら可能な範囲でお答えいただけたら嬉しいです。
こんにちは、RailsのAPIについて質問させてください。
今は、RESTfulなAPIで実装されてますか?GraphQLは使う検討などされてましたか?今の実装を選択された理由などありましたら教えていただければと思います m(_ _)m
はい、RESTな感じのAPIにしています。考え方的にはWeb API: The Good Partsにできるだけ則ろうとしている感じです。
途中でRestfulとパフォーマンスの両立が難しくなってきたのでGraphQLも検討したのですが、導入のハードルの高さで躓きました…。
そうなんですね。ありがとうございます!
記事のTopicsのicon画像表示について質問です!
素朴な疑問なのですが、記事のTopics文字列でのicon画像表示ってどういうロジックになっているのですが?
topicsの各技術要素の文字列対画像パスのハッシュをどこかで持っているかと思うのですが、どんどん出てくる技術要素に合わせて更新していくのがなかなか大変そうだなと思いまして。。
どのような解決手段か気になりました。
Zennのアイコン画像の登録は、基本的に「ユーザーが申請して管理者が承認する」仕組みになっています。
申請が送られると、topic_change_proposal
のようなテーブルにレコードが挿入されます。その中にCloudStorage上の画像のファイル名が格納されています。
申請を承認するとtopic_change_proposal
の画像ファイル名の値を、topic
テーブルの画像ファイル名のフィールドにコピーします。そんな感じで最新の画像のパスをtopic
テーブルにもたせています。
Zennのアイコン画像の登録は、基本的に「ユーザーが申請して管理者が承認する」仕組みになっています。
なるほどーー!ありがとうございます!!
申請性だったとは知らなかったです。この仕組みは良いですね
早速いくつか申請してみようと思います!
ですです!今はスマホからは申請できないので気づきにくいかもですね。
ありがとうございます!!
Zennを支える技術とサービス構成を読んでの質問させてください。
GAEを使っているとのことですが、
クライアントとGAEの間にロードバランサは入っていますか?
それともZENN全体のリクエストをGAE1インスタンスで処理を捌いていますか?
負荷分散の話が出てきてなかったので、どうやって捌いているのかな?と気になりました。
ロードバランサを自分で入れたりはしていないですね。GAEのオートスケール設定を使っています。
一定の条件を超えると自動でインスタンスが増えるようになっています。
具体的にはapp.yaml
のAutomatic scalingのあたりで設定をしています。
なるほど、オートスケールだけで結構捌けるんですね。
ありがとうございます!
そういえば、時々表示に時間がかかる時が、インスタンスが増えてる時って感じでしょか?
今はリアルタイムで(フロントエンド側が依存している)AWSの障害が起きているので表示に時間がかかりますね…
あと2020年12月頃にオートスケール時のレイテンシと料金対策のためにStandard環境からFlexible環境へと移行しました。
昨夜全体的に遅いなーと思ってたのは障害だったんですね。
普段の表示は早いですものね。失礼しました。
Standard環境からFlexible環境へと移行記事、読ませていただきます。
ありがとうございます!
URL の設計について聞いてみたいです。
ユーザーページが /[user_name]
なので Zenn のページである /article
や /search
などを予約語にしていると思うのですが不都合はなかったのか、またそうした理由が気になりました。
はい、仰る通りです。不都合というのは「ユーザーページを/[username]
にすることで発生する不都合」という理解で合っていますでしょうか?(この理解で回答させていただきます)
開発者側からするとユーザーページを/users/[username]
ではなく/[username]
にすることで面倒な問題が色々と発生しています。新しいページを追加するときには予約語をチェックしないといけないですし、ルーティングもやや面倒です。
とはいえ、ユーザーページのURLをできる限り簡潔にしたい、各ページのURLも推測しやすいものにしたいという考えからこのようにしています。(記事一覧は/[username]/articles
で、記事自体は/[username]/articles/[slug]
など)
という感じの回答になりますが、質問の主旨にお答えできていますかね…?
回答ありがとうございます。(分かりづらくてすみません、意図通りの回答になってます)
面倒な問題が色々と発生しています。
やっぱりそうですよね。
ユーザーページのURLをできる限り簡潔にしたい、各ページのURLも推測しやすいものにしたい
とてもよく分かります。
面倒な問題が発生してでもこちらを優先したとのことで参考になりました。
このへんはどうしてもトレードオフになってしまうんですね。
GCPとVercelを使っているとのことですが、AWS(VercelはAWSに依存しているという想定で書いています)とGCPどちらかで障害が発生するとzennの方で何かしら影響を受けるという理解で合っているでしょうか?
綺麗なUIでいつも個人ブログの参考にさせていただいています。
Articlesの目次はサーバサイド(or BFF)で処理されていると思いますが
- 文章中のheadingタグ集計・目次化する実装はライブラリを使われていますか?自前での実装でしょうか?
- 画面位置が該当headingに到達した場合、太字になる実装についてもライブラリをお使いの場合はお教えいただけるとありがたいです。(intersection observer系のライブラリでしょうか)
tocbotというnpmパッケージを使っています。
headingタグから目次を自動生成してくれる + 現在見ている部分の目次に対して指定したクラス名を付与してくれます(activeLinkClass
)。そのクラスに対してfont-weight: 700
とか指定するだけで太字にできます。
早々にご回答ありがとうございます。
npmパッケージの使い方についても、解説ありがとうございます。
横から質問失礼致します。tocbotかなり便利ですね。1つ質問なのですが、zenn ではスクロールした時に目次のstickyの方も正しくスクロールされていますがデフォルトの tocbot では sticky のスクロールはされないかと思います。こちらはどのような形で実現されているのでしょうか?
素敵なサービスをありがとうございます!
以前別の方の質問に
現状では手数料などの関係から「Paymentsのみで、売上を運営が管理し、決済から振り込みまで実行」としています。
とお答えになっておられましたが、各ユーザへの振り込み周りはどのような仕組み(サービス。。。というか銀行の提供する何かになるのでしょうか)を使ってらっしゃるのでしょうか?
答えていただける質問かわかりませんが、是非知りたいです。
どうぞよろしくお願いいたします。
あまり詳しくは書けないのですが、銀行のオンライン振込を独自のJSを使って効率化しているような感じです(あまり参考になる回答ではなくすみません)
答えづらい質問をすみません。
どうもありがとうございます!
各記事の「読了の目安」はどのように算出しているのでしょうか?
マークダウン時点の文字数を単純に割ることで計算しています。
ありがとうございます。
こんな所があるとは知らずに記事のコメントの方に質問を連投してしまっていました
大変失礼しました。
https://zenn.dev/catnose99/articles/cb72a73368a547756862#comment-0b9502e2b233d8
色々調べた結果をつらつら書いてしまい内容が冗長になってしまっているのですが要約すると以下のように古いRSSが取得されるケースがあるという内容です
$ diff \
> <(xmllint --xpath "//lastBuildDate/text()" <(curl -s https://zenn.dev/tantan_tanuki/feed)) \
> <(xmllint --xpath "//lastBuildDate/text()" <(curl -s https://zenn.dev/tantan_tanuki/feed))
1c1
< Thu, 08 Apr 2021 15:08:51 GMT
---
> Fri, 09 Apr 2021 08:42:43 GMT
何かアドバイスをご教授願えないでしょうか?
Next.jsのファイルベースルーティングのID重複の制御についてどのように実装しているかお聞きしたいです。
例えば、ユーザーの記事一覧ページ(https://zenn.dev/eringiv3)があります。
これはおそらく pages/[userId].tsx のようなファイルで実現しているのかなと思っています。
ただ、URLの階層がユーザーの記事一覧ページと被っているページ(例えば https://zenn.dev/about )があります。
その場合、ユーザーがIDを変更するときに「about」という文字列は選択できないようにするバリデーションを実装する必要があります(ユーザーがaboutというIDを設定したら、そのユーザーの記事一覧ページが見れなくなってしまうから)。
このバリデーションについて、Zennではどのような実装を行っているのでしょうか?
ユーザーが使用することのできないID一覧リストのようなものをnext buildの直前に生成しておいてpublic配下に置いておく、などでフロントエンドのバリデーションはなんとかなりそうですが、サーバーサイド側でも真面目にやろうとするとちょっと大変そうです。
質問失礼します!
フロントはNext.js、バックエンドはrailsと伺っていますが、
開発時のリポジトリは分けていますでしょうか?
自分もこの技術でサービスを作ろうとしていて、railsはdockerに乗せてAWSにデプロイ、Next.jsはvercelを考えているので、型の共有もないので別々のリポジトリで良いかなと考えているのですが、
差し支えなければリポジトリ構成を教えていただきたいです。
slugはサイト全体で(記事や本などのコンテンツの種類ごとに)ユニークにする必要があるようですがもし重複してしまった場合はどのような処理をしているのでしょうか?
ユニーク制約をかけているため、slugが重複する場合はレコードを作成できないようになっています。
回答ありがとうございます!
お忙しいところ質問失礼します!
Zennには1. 「Zenn運営用のGoogle Analytics」、2. 「ユーザが設定できるGoogle AnalyticsのトラッキングID」の二種類がありますが、1はGTMで、2はgtagで送信しているのかと思うのですが(間違っていたらすみません。)、なぜ2種類の送信の仕方をしているのでしょうか?
また、2はそのユーザのURL空間以外(例: /catnose99*以外)は発火しないようになっていますが、特にnext/routerでの遷移の時、どのように制御されていますか?
差し支えなければご教授いただきたいです!
next初心者のため、検討違いな質問であったらすみません。
こちらのスクラップに
バックエンドにはRails(on App Engine) + PostgreSQL(on CloudSQL)を使っています。
とのコメントされていましたが、
ServerSidePropsやAPIRoutesから(Prismaやpg-promiseなどを利用して)直接DB接続をしないのは何故でしょうか。
Rails(App Engine)を挟むメリットがあれば教えていただきたいです。
返信が遅くなりすみません。
これはサービスのビジネスロジックの所在をバックエンド(Rails)に統一するためです。Zennではバッチ処理や非同期処理なども多く実行されており、これらを全てNext.jsのAPI Routesで行うのは(できなくはないと思いますが)非効率な部分が多く出てくると考えています。
また「記事詳細ページだけはgetServerSideProps
でDBから直接取得する」ということもできなくはないと思いますが、RailsとNext.jsのそれぞれで「どのように記事を取得するか」や「どのように公開可能な記事だとみなすか」というロジックを持たせることになりメンテナンスが難しくなります。
とはいえこのツイートのように、今1から小〜中規模なWebサービスを作るのであればPrismaを使ってgetServerSideProps
などから直接DBに接続するような方法を取る気がします。
記事slugなのですが、特に指定しない場合、「107c4fc35748ce」のような形で、14桁の英数字小文字が生成されていると思うのですが、これはどうやって生成しているのでしょうか?(アルファベットがfまでになっているようなので、16進数のhash値なのかな?とは思っているのですが、14桁というのがピンと来ませんでした)
トップページはSSR(Server Side Rendering)とありますが、それにしても描画速度がはやくてすごいなとおもってます。なにか工夫はさていらっしゃいますか?
本の作成についてです。
チャプターの並び替えをどのようにDBで保存しているか気になっています。
見た感じ、本の保存時に、チャプターIDの配列をAPIに渡して、そのあと再取得してきたレスポンスは新しい並び順になっていました。
チャプターIDの配列をバックエンドでどのように扱って順番を入れ替えているかお聞きしたいです。