shetommy.comのver1.0.0のやり残しを潰していく
この辺の作業ログ
まずはアラートに対応する。Next.jsのバージョンが10で、11が出てるのでアップデートしろ、的な内容のようだ
ここの通りにやればいいんかな?
ここの通りにやればいいんかな?
$ npm install react@latest react-dom@latest
+ react@17.0.2
+ react-dom@17.0.2
updated 2 packages and audited 500 packages in 3.493s
found 1 moderate severity vulnerability
run `npm audit fix` to fix them, or `npm audit` for details
Reactのアプデの後で脆弱性があると言われたが、そのままNext.jsのアプデしたら解消した
npmの使い方がよくわかってないので、ついpackage.jsonを手書きで編集してバージョン上げようとしてしまうのだが、普通はnpm経由で行う模様
$ npm outdated
Package Current Wanted Latest Location
@notionhq/client 0.2.1 0.2.4 0.4.1 shetommy-com
@types/react 17.0.11 17.0.11 17.0.27 shetommy-com
@typescript-eslint/eslint-plugin 4.27.0 4.33.0 4.33.0 shetommy-com
@typescript-eslint/parser 4.27.0 4.33.0 4.33.0 shetommy-com
eslint 7.28.0 7.32.0 7.32.0 shetommy-com
eslint-plugin-import 2.23.4 2.24.2 2.24.2 shetommy-com
eslint-plugin-react 7.24.0 7.26.1 7.26.1 shetommy-com
prettier 2.3.1 2.4.1 2.4.1 shetommy-com
typescript 4.3.2 4.4.3 4.4.3 shetommy-com
Next.js、Notion APIだけ上げればと思っていたけど、地味にバージョン遅れてるな
とりあえずここを見てる。
npm updateってupdateしてくれないのか……なんなんだ……
パッケージ更新は二通り手段があるみたい
- package.jsonを更新して、再install
- ncuを使う
ncuの使い方はこことか
更新してみた
$ sudo npm install -g npm-check-updates
$ ncu -u
Upgrading /Users/xxx/Dev/shetommy-com/package.json
[====================] 16/16 100%
@types/react 17.0.11 → 17.0.27
@typescript-eslint/eslint-plugin ^4.27.0 → ^4.33.0
@typescript-eslint/parser ^4.27.0 → ^4.33.0
eslint ^7.28.0 → ^7.32.0
eslint-plugin-import ^2.23.4 → ^2.24.2
eslint-plugin-react ^7.24.0 → ^7.26.1
prettier ^2.3.1 → ^2.4.1
typescript ^4.3.2 → ^4.4.3
@notionhq/client ^0.2.1 → ^0.4.1
Run npm install to install new versions.
とりあえず画像対応を後回しで、Notion APIのバージョンだけ上げようとしたら、日付プロパティが取れなくなった?!
const publishDateObject = post.properties['publish date']
const dateString =
publishDateObject == undefined
? post.last_edited_time
: publishDateObject.date.start
const date = new Date(dateString).toLocaleDateString()
@notionhq/clientを"version": "0.2.1"→ "version": "0.4.1"にアップデートした
TypeScriptのバージョンアップのせいなのかな?
よくわからない
とりあえずNotion側でプロパティ名にアンダースコア入れて対応したらビルドできた
const publishDateObject = post.properties.publish_date
うーん……
いやでもnullはnullだった。
仕様的にpublish dateがnullだと、作成日付を入れる仕様にしてたから、パッと見は上手くいってるように見えてしまった
データ構造を整理すると、
{
object: 'page',
id: 'xxx',
created_time: '2021-07-08T22:49:00.000Z',
last_edited_time: '2021-07-09T07:06:00.000Z',
cover: null,
icon: null,
parent: {
type: 'database_id',
database_id: 'xxx'
},
archived: false,
properties: {
publish_date: { id: 'xL%5EM', type: 'date', date: [Object] },
Name: { id: 'title', type: 'title', title: [Array] }
},
url: xxx
}
{
id: 'xL%5EM',
type: 'date',
date: { start: '2010-05-29', end: null }
}
これ前も確か同じことでTypeScriptの型ワーニング解消できなかった気がする。。。
とりあえずバージョンを戻して、Next.jsだけ上げる
TypeScriptで解消できない型の問題
- propsの型指定が上手くいかない
- オブジェクトのプロパティのアクセス指定が上手くいかない
- Notionで定義したプロパティに型がないので受けられない
- (Notion APIの型定義が足りないのか、俺が何かInterfaceつくらないといけないのかもよくわからない)
一週間ぐらいじっくりTypeScriptの勉強しないといけないのを感じている
これをみるか、
オライリー本を買うかの二択かな
学習ロードマップは以下二つを見た
全戻ししようかと思ってたけど、冷静に考えるとNotion API以外のパッケージのアップデートが影響してる気がするので、@notionhq/clientだけのアップデートにしてみる
いや、そんなことはなかった。
@notionhq/clientだけアップデートしても同じようにDateが取れなくなる……
とりあえずNext.jsのバージョンあげたが、GithubのDependabot alertsが解消されなかった
というかむしろ増えた。
そもそもyarn.lockは使ってなかったので、リネームして退避した
でもワーニングが消えなかったので、dismiss扱いにした
とりあえずGAを入れるところからやろう
このワーニングは、GAとは別件だった。
react-dom.development.js?61bb:67 Warning: validateDOMNesting(...): <tr> cannot appear as a child of <table>. Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by the browser.
単に<tbody>がない、と言われているだけだった
ansi-regexのワーニングが気になる
OGP設定、こちらのissueに色々書きこんでる
うーんここにswitch文を使いたかった
<meta
property="og:description"
content={
titlePre == 'Home' || 'Articles'
? '蔀のポートフォリオサイト&個人ブログ'
: 'Written by 蔀'
}
/>
式じゃないとダメらしい
三項演算子のネストができるらしいので、こうした
<meta
property="og:description"
content={
titlePre == 'Home'
? '蔀のポートフォリオサイト'
: titlePre == 'Articles'
? '蔀の個人ブログ'
: 'Written by 蔀'
}
/>
時間があったので、足元を固めるつもりで、JSとTSのWeb教材を読みなおした
なんとなくで進める限界を感じていたので、改めてゆっくり学習しなおすにはいいタイミングだったと思う
このページネーションについてのissueはすぐにでも潰せそう。実装イメージもついた
ただNotion APIから返されたデータに対する型づけがまだ俺の中で解決せず
API仕様の理解はほぼほぼできたと思う
- Promiseを返す
- APIのリポジトリのREADME読むと、エラーハンドリングもそこそこ細かくできることがわかった
- 課題は二点
- (Notionの)プロパティの扱い。NotionはユーザーがDBの項目を自由に名づけて、データ型も設定することができるので、そこをTypeScriptとしてどう扱うか
- そういうのはもうAnyが楽なんじゃないか……ともすこし思っている
- DBのフォーマットは自分でつくったものなので、ソース中との整合性を取ればいいだけなんだろうけど、そこがよくわからない
- propsの型づけ
- 単純な例ならいくつか見つけたんだけども、今回はAPIの戻り値の型を指定しなければならなくて、これがよくわからない
- (Notionの)プロパティの扱い。NotionはユーザーがDBの項目を自由に名づけて、データ型も設定することができるので、そこをTypeScriptとしてどう扱うか
基礎から固め直すアプローチはよかったと思う。前進してる感じはある
ここがヒントになる?
DBにあるページをpublished dateでfilter()して、その後sort()すればいい気がしてきた
個人PCに開発環境なかったので入れる
- VSCodeを落とす
- リポジトリをcloneする
Node.jsすら入ってなくて草
入れます
色々やった……めんどくさいのでhistoryだけ
337 brew install node
338 node -v
339 xcode-select --install
340 brew install --build-from-source python@3.9
341 sudo brew install --build-from-source python@3.9
342 brew doctor
343 sudo brew install --build-from-source python@3.9
344 brew install --build-from-source python@3.9
345 brew link python@3.9
346 brew install node
353 npm install next react react-dom\n
354 npm audit
355 npm audit fix
356 npm run dev
.env.localを再作成した。
中身を控えておくの忘れて、いざつくりなおそうとしたら結構難しかった。
Vercelに本番環境向けに設定していたのを思い出して、そこからコピーした。
npm run dev
でlocalhostで実行できることを確認した
nodeのバージョンが全然違ったり、regexのワーニングが修正できたりしたので、こっちを本番にするかな
今までssh接続でgit pushしてたけど、今回からhttpsでやることにした
手順はこちら。
自分用にまとめると、
- (自分のMacBookのKeyChainからGithubのキーは削除しておく)
- GithubのUser > Setting > Developer settings > Personal access tokensでトークンを発行
- push時にユーザー名、パスワードが要求されるので、↑のトークンをパスワードとして利用
- Success!
という流れ。今後は簡単なのでこっちにしようと思う
なぜかnodeのバージョンが全然違う……
昔の会社
brew -v
Homebrew 3.2.16
node -v
v16.11.1
npm -v
8.0.0
npm view react version
17.0.2
調べたら、Node.jsの最新LTSはもう16以降になっていた
14でもサポートはしているみたいなので、商用で安定性重視ならアリかもしれないが、まあ俺の個人サイトで16にしない理由はないだろう
ちなみに気になっていたansi-regexのセキュリティワーニングもなんか消えた
結果オーライ
今日は実装イメージついてるところをやってこうかなと思います
ESlintとPrittierが何もしてないので効かなかった。
- VSCodeの拡張からESlintとPrittier
- onSaveでフォーマットするように設定
https://qiita.com/KKKKK/items/3b9dba55653cb7993bf5 - VSCode右下の通知欄に出てたダイアログで、「フォーマッタが二種類あるがどちらを選ぶ?」みたいなのが出るので、Prittierを選んだ
- 任意のファイルに
let text = "Hello, world";
を入れて保存して、セミコロンが消えて、シングルクオーテーションになることを確認 - ↑ここまでやっても、ESLintのワーニングが出てくれなかった
setting.jsonを指定してやらないと効かなかったみたい
let text = 'Hello, world'
のtextにconstにしろワーニングが出たのを確認
ちなみに下線引かれないんだけど、これはそういうものだっけ?
これに対応する
Gitで、こんなワーニングが出た。
git pull
hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged. You can squelch this message by running one of the following
hint: commands sometime before your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
よく理解できていないが、
↑を読んで、pull.rebase false
を設定した
ここのmapの返り値の{ }
を囲んでいる( )
は何のカッコなんだ?
const paths = sampleUserData.map((user) => ({
params: { id: user.id.toString() },
}))
{ x, y }: Type
で、Type.xとType.yが取れるのか。
つまり下記のコードが同じ意味。やっと理解できた
type Props = InferGetStaticPropsType<typeof getStaticProps>
export default function Post(props: Props) {
const page = props.page
const blocks = props.blocks
}
export default function Post({page, blocks}: Props) { }
開発環境だとAny撲滅できたと思って、pushしたらVercelでガンガンコケるのムカつくな……
ローカルでもstrict指定みたいなんするといいのかな?
型ガードがうまく書けない
↑ここを参考にして、こんなのを書いてみた
declare type PropertyType =
| 'number'
| 'title'
| 'rich_text'
| 'url'
| 'select'
| 'multi_select'
| 'people'
| 'email'
| 'phone_number'
| 'date'
| 'files'
| 'checkbox'
| 'formula'
| 'relation'
| 'rollup'
| 'created_time'
| 'created_by'
| 'last_edited_time'
| 'last_edited_by'
declare type TitlePropertyType = 'title'
export const isTitle = (type: PropertyType): type is TitlePropertyType => {
return type === 'title'
}
これで、
const title = isTitle(titleProperty.type) ? titleProperty.title : ''
こんな感じで使いたかったんだけど、絞りこみが効いてなかった……
Notion APIをバージョンアップしたら、操作したいプロパティの型定義がなくなって、型のプロパティを指定しないといけなくなって困ったけど、↓この記法でいけるみたい
declare type temp = QueryDatabaseResponse['results']
これで一応プロパティの存在チェックもしてくれる模様
あっ、Array挟んでる……終わった……
KeysMatchingで頑張ればできんのかな?
まさかのType[number]でいけるという……
declare type temp = QueryDatabaseResponse['results'][number]['properties']
これでいけそう
declare type NotionProperty =
QueryDatabaseResponse['results'][number]['properties']
export const getTitle = (property: NotionProperty) => {
return property.Name.type == 'title' ? property.Name.title[0].plain_text : ''
}
getStaticProps
のparamsがnullableになっちゃうのが気になってたんだけど、インターフェイスを指定することで読めるようになるっぽい。
というかよく読んだらidも渡せそうだし、後続処理で必要なページのパラメーターはタイトルとidだけだった
interface IParams extends ParsedUrlQuery {
title: string
id: string
}
export const getStaticProps = async (context: GetStaticPropsContext) => {
const page = context.params?.page
これだとreturn省略できて、
const page = database.find((page) => getPageTitle(page.properties) == title)
これだとreturn必須になる(アロー関数の戻り値に{ }をつける)の、よく間違えて、{ }アリでreturn省略してしまう
const page = database.find((page) => { return getPageTitle(page.properties) == title})
こんな書き方もできる
export type Partial3DPoint = Partial2DPoint & { z: number }
こんな書き方もできる
export type Partial3DPoint = Partial2DPoint & { z: number }
if (block.has_children && !block[block.type].children) {
この.children
ってプロパティ、なくなった?
リテラル型でずっと苦しんでいる
この分割代入、リテラル型でネストされてるからこれだと取れないと思ってたけど、なんか取れるな。なんでだろ……
const elements = richTexts.map((value, index) => {
const {
annotations: { bold, code, color, italic, strikethrough, underline },
text,
} = value
console.log(Object.keys(value))
wait - compiling...
event - compiled successfully
[ 'type', 'text', 'annotations', 'plain_text', 'href' ]
?!
想定と違うものが入ってる……
ListBlockChildrenResponse['results']
じゃないのか