記事にするほどでもないけど、無駄に時間を消費してしまった問題の解決方法をまとめるスクラップ
Next.js + TailwindCSS で本番環境だけCSSが反映されてない
tailwind.config.js
の purge
の設定がミスっている可能性があるので、そこを設定しなおす。
module.exports = {
// "/src/" が入ってなかったので、パスが間違っていた
- purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
// 正しいパスを指定してあげる
+ purge: ['./src/pages/**/*.{js,ts,jsx,tsx}', './src/components/**/*.{js,ts,jsx,tsx}'],
/* -- 省略 --*/
}
Next.js + Firebase Admin SDKのコンパイル時にエラーが発生する
上記のようなエラーが発生した原因は、フロントエンド側のソースコード内でFirebase Admin SDKをimportしているため。
解決方法
Firebase Admin SDKをimportしている部分を削除する事でエラーが無くなる。
因みに、型情報だけ必要な場合は以下のようにしてimportする事が可能なので、覚えておくといいかも?
import type FirebaseAdmin from "firebase-admin";
参考
注意すること
基本的に、バックエンド用のソースコードを getStaticProps
や getServerSideProps
内だけで使っていると、next.js側がそれを検知してフロントエンド側のバンドルに含めないようにしてくれるが、importだけして使用しないなどの事をしているとエラーが発生する😥
また、人によっては以下のような感じで一つのファイルにまとめている人もいるかもしれない。
export * from "./client-src"; // フロントエンドのライブラリを含んだソース
export * from "./backend-src"; // バックエンドのライブラリを含んだソース
上記のように、フロントエンド側とバックエンド側のソースコードを混在させてexportしてしまうと、仮にgetStaticProps
や getServerSideProps
内だけでバックエンドのソースコードを使用していても、next.jsが検知してくれずにエラーが発生してしまうので、注意されたし👺
一つのファイルにまとめたいなら、フロントエンドとバックエンドを別々のファイルでまとめると良い。例えば以下のような感じ👇
export * from "./client-src"; // フロントエンドのライブラリを含んだソース
export * from "./backend-src"; // バックエンドのライブラリを含んだソース
Zod v3のobject()の型引数に任意の型を渡したい
例えば以下のような実装をしたいが、そのままではエラーが発生してしまう🤯
import * as z from "zod";
interface IHoge {
hello: string;
world: string;
}
const Hoge = z.object<IHoge>({ // IHogeを型引数として渡したいが、エラーが発生する
hello: z.string(),
world: z.string()
})
上記のエラーを無くすには、zodに渡せる型に変換する型を作って、任意の型を変換してから渡してあげる事でとりあえず解決する👇
import * as z from "zod";
// zodに渡せる型に変換する型
type toZod<T extends Record<string, any>> = {
[K in keyof T]-?: z.ZodType<T[K]>;
}
interface IHoge {
hello: string;
world: string;
}
const Hoge = z.object<toZod<IHoge>>({ // IHogeを型引数として渡したい
hello: z.string(),
world: z.string()
})
注意点として、optionalな型があった場合は unknown
になってしまうので、
optionalを取り除くために
[K in keyof T]-?: ~
としている🐔
参考
VSCodeからコミットできない
VSCodeからコミットしようとすると以下のアラートが表示される。
.husky/pre-commit: 4: yarn: not found
と出ているので、どうやらhuskyにyarn
コマンドが認識されていない様子。
私の環境では、nvmを使用しているので、それが原因だった。
解決策
husky v6からは、.husky
フォルダー下にスクリプトファイルが生成されるので、そこにnvmの環境変数を設定する。
今回の場合は、pre-commit
なので.husky/pre-commit
ファイルを以下のように修正する。
#!/bin/sh
# nvmの環境変数を設定する
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# 以下は、記述済みのスクリプト
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged
上記のファイルを保存して、VSCodeからコミットできていればOK👌
もし他のスクリプトがある場合は、.husky/_/husky.sh
に記述すると良い。
#!/bin/sh
if [ -z "$husky_skip_init" ]; then
# -- 省略 --
fi
# 以下の部分を追加
export NVM_DIR="$HOME/.nvm"
if [ -e $NVM_DIR ]; then
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # nvmがあれば、nvmを有効化する
fi
参照
additionalUserInfo
を取得する方法
Firebase JS SDK v9 で 他の認証プロバイダーを使用している場合、そのプロバイダーが提供する情報を additionalUserInfo
で取得することができるが、v9では getAdditionalUserInfo()
を使わないと取得できないので注意が必要。
以下、サンプルコード👇
import { getAuth, signInWithPopup, getAdditionalUserInfo, GithubAuthProvider } from "firebase/auth"
const onLogin = async () => {
// Githubのプロバイダーを作成
const provider = new GithubAuthProvider();
// ポップアップでログイン
const result = await signInWithPopup(getAuth(), provider)
// Github プロバイダーが提供する追加情報を取得する
const additionalUserInfo = getAdditionalUserInfo(result)
// 追加情報を表示( profileの値は使っているプロバイダーによって変わります )
console.log(additionalUserInfo?.profile);
}
参考
Unable to resolve path to module ~
が出たとき
Vite で Vite × React × TypeScript × eslint-plugin-import を使っている環境で、以下のようなエラーが出た 👇
Unable to resolve path to module './App'.
解決策
settings
オプションで、拡張子を追加してあげたらエラーが無くなった。
/* -- 省略 -- */
settings: {
"import/resolver": {
node: {
+ extensions: [".js", ".jsx", ".ts", ".tsx"],
},
},
},
/* -- 省略 -- */
具体的な環境情報は以下に載せておく👇
環境情報
バージョン情報
名前 | バージョン |
---|---|
vite | v2.7.2 |
react | v17.0.2 |
react-dom | v17.0.2 |
typescript | v4.4.4 |
eslint-plugin-import | v2.25.4 |
設定ファイル情報
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"prettier",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 13,
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
ignorePatterns: [".eslintrc.js"],
overrides: [
{
files: ["./src/**/*.{js,jsx,ts,tsx,css,scss,svg}"],
rules: {
"import/order": [
"error",
{
groups: ["type", "external", "internal", "sibling"],
pathGroups: [],
alphabetize: {
order: "asc",
},
"newlines-between": "always",
},
],
},
},
],
rules: {},
};
Prism.js の自動ハイライトを無効にする
PrismJS は、import
や <script />
などの方法で読み込まれると highlightAll()
を使って自動的にページ内の全てのコードをハイライト( highlight )しようとします。
この挙動を無効にしたい場合は、ページが描画される前に以下の処理を実行します👇
window.Prism = window.Prism || {};
window.Prism.manual = true; // 自動的にハイライトするのを無効にする
参照
TypeScript で export してない型があるとエラーが発生する
ある時、以下のようなエラーが発生しました👇
モジュールの既定エクスポートがプライベート名 'xxx' を持っているか、使用しています。ts(4082)
問題のソースコードは以下のようになります👇
interface Hoge {
value: string;
}
export const sayHello = (hoge: Hoge) => {
console.log(hoge)
}
import { sayHoge } from "./a";
export const sayHelloWorld = sayHoge; // ここで上記のエラーが発生する
解決策 ①
エラーが発生した原因としては、tsconfig.json
の declaration
を true
に設定すると、プライベートな型を出力できないので、エラーが発生します。なので、declaration
を false
に設定するとコードを変更せずに解決できます👇
{
"compilerOptions": {
/* ... */
"declaration": false, // ここが true だと上記のエラーが発生する
/* ... */
},
}
解決策 ②
interface
から type
に変更することでもエラーを修正できます👇
- interface Hoge {
+ type Hoge = {
value: string;
}
export const sayHello = (hoge: Hoge) => {
console.log(hoge)
}
解決策 ③
プライベートになっている型を export することでもエラーを修正できます👇
- interface Hoge {
+ export interface Hoge {
value: string;
}
export const sayHello = (hoge: Hoge) => {
console.log(hoge)
}
参考
yarn publish
する時にアクセストークンを使う方法
ローカル環境で npm へ プロジェクトのルートディレクトリ( package.json があるディレクトリ ) に .npmrc
を作り、以下のように設定する👇
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
上記のファイルを設定したら、あとは yarn publish
するだけ。
参考
npm access token の作り方は以下を参照👇
TypeError: defaultLoader is not a function
なるエラーが発生する
Vite で vite を使って react の環境構築をしたときに以下のようなエラーが発生した。
$> npx vite
ailed to load config from vite.config.ts
error when starting dev server:
TypeError: defaultLoader is not a function
...
原因
私の場合、Windowのシンボリックリンクのフォルダー以下でコマンドを実行したことが原因だった。
対処法としては、親フォルダーがシンボリックリンクじゃない場所で、プロジェクトを作りコマンドを実行する必要がある。
参考
.lock ファイルを新しく生成すると突然TypeScriptの型エラーが発生する場合がある
@types/styled-components
など一部のパッケージでは、依存関係を定義する際にバージョンを指定していないことがあり、その場合、依存先のバージョンに対応していないがために型エラーが発生する場合がある。
'Hoge' を JSX コンポーネントとして使用することはできません。
そのインスタンスの型 'Hoge' は、有効な JSX 要素ではありません。
'render()' によって返された型は、これらの型同士で互換性がありません。
型 'React.ReactNode' を型 'import("/Hoge/node_modules/@types/styled-components/node_modules/@types/react/index").ReactNode' に割り当てることはできません。
型 '{}' を型 'ReactNode' に割り当てることはできません。
※ 上記のエラーが出た場合は、使っているパッケージを更新すれば大抵直ります。
このエラーの厄介な所は、.yarn.lock が無い状態で yarn install をしてしまうと、うまくバージョンが解決できずに上記のようなエラーが突然発生してしまう。
そのため、なるべくは .lock ファイルは削除しないようにするべきなんだが、上記のようなことが起きる時は大抵使っているパッケージのバージョンが古いために発生していることが多いので、わざと .lock ファイルを削除して挙動を確かめてみるというは案外いいのかもしれない。
tsconfig.json で exclude したファイルが TypeScript Auto Import で参照されてしまう問題
以下のように src/exclude.ts
を TypeScript のプロジェクトから除外しているのに VSCode などのAuto Import ( Intellisense ) で src/exclude.ts
が参照されてしまう問題が発生した 👇
{
"include": ["src/**/*.ts"],
"exclude": ["src/exclude.ts"]
}
原因
プロジェクト内のファイルで src/exclude.ts
を参照していると、tsconfig.json の exclude を設定していてもプロジェクトファイルとして扱われてしまう。
私の場合だと、src/index.ts
で src/exclude.ts
をインポートしてしまっていた 👇
import { ... } from "./exclude.ts";
// 👆 ここで参照したことで tsconfig.json の exclude が無効になってしまう
解決方法
今回の場合は、プロジェクトファイル内で exclude しているファイルを参照しないようにする👇
- import { ... } from "./exclude.ts";
+ import { ... } from "./non-exclude-file.ts";