Next.js 16: "use server" / "use client" 境界で「export 起因の事故」を潰す
Next.js 16: "use server" / "use client" 境界で「export 起因の事故」を潰す(公式エラーメッセージに沿った最小ルール)
この記事は、Next.js 16 の公式ドキュメントと公式リポジトリのエラーメッセージ(invalid-use-server-value など)を根拠に、
-
"use server"と"use client"の 境界を跨ぐ import/export で - 「export 設計が原因」のリンターエラー/ビルド時エラー/実行時エラーを起こしにくい構造
を 第三者が再現できる形で整理します。
0. 結論(質問への回答と、NO になる但し書き)
質問
この記事に書かれた事柄さえ守れば
"use server" "use client" 間での export が原因の リンターエラーや実行時エラーは起きない、という理解でよいか?
答え
NO
NO になる但し書き(抜け漏れなく)
- Next.js 本体の不具合・挙動差(公式リポジトリ上の issue / discussion による報告)により、設計ルールを守っていてもエラーが出るケースが「ゼロ」とは断言できません。
- Server Actions には、export 設計とは別の理由で、実行時に
Failed to find Server Action ...のようなエラーが起き得ます(公式ドキュメントに「なぜ起きるか/どう直すか」が説明されています)。 - Next.js 16 では
next lint自体が削除され、ESLint の “唯一の最強設定” を Next.js が公式に 1つに定義していません。そのため「世界で唯一の最強 lint 設定で絶対に落ちない」までを公式根拠だけで保証できません。
ただし、この記事のルールを守ることで 「export 設計が原因で起きる代表的な事故」(後述)は、構造的に潰せます。
1. まず押さえる公式仕様(ここがブレると事故る)
1.1 "use client" は「クライアント境界」を作る
'use client' は、そのファイルを **クライアントで動くコンポーネントの入口(境界)**として宣言します。
境界ファイルから export されたコンポーネントが、クライアント側のエントリーポイントになります。
1.2 "use server" は「サーバーで実行される関数/ファイル」を指定する
use server は、関数(またはファイル)を サーバー側で実行させるためのディレクティブです。
ファイル先頭に置くと「そのファイル内の関数はサーバーで実行される」と説明されています。
2. 重要:"use server" の export 制約は「import した時」だけの話ではない
よく混乱するポイントなので、先にハッキリ書きます。
- Next.js の公式エラードキュメント(
invalid-use-server-value)は、
「"use server"ファイルが async 関数以外を export したときに発生する」 と説明しています。 - つまり本質は **「
"use server"を付けたファイルの export 形」**です。 - エラーが “いつ見えるか” は、開発サーバーやビルドが そのモジュールを処理(評価)したタイミングです
(実務上は「どこかから import されてモジュールグラフに入ったとき」に顕在化しやすい)。
2.1 典型エラー:"use server" file can only export async functions ...
「"use server" ファイルで async 以外(定数、object、enum、class など)を export してしまう」事故です。
公式ドキュメントの通り、修正方針は async 関数だけを export する です。
3. ルール(これだけ守れば “export 起因” の代表事故を再現しにくい)
ポイントは **「"use server" を置くファイルを“async 関数だけ export する専用ファイル”として固定」**することです。
3.1 ルールA:"use server" ファイルは async 関数だけ export
✅ OK
// src/actions/user.ts
'use server'
export async function updateUser(formData: FormData) {
// ...
}
export const deleteUser = async (id: string) => {
// ...
}
❌ NG(この記事では禁止)
'use server'
export const X = 1
export default { a: 1 }
export function syncFn() {}
export class C {}
export enum E { A }
3.2 ルールB:"use server" ファイルで barrel export / re-export を禁止
✅ OK:async 関数を このファイルで定義して export
❌ NG(混入が起きやすい)
'use server'
export * from './anything'
export { something } from './other'
3.3 ルールC:共有したい “値/enum/class/sync関数” は必ず別ファイルへ
✅ OK(分離)
// src/shared/enums.ts
export enum LogLevels { Info = 'INFO', Warn = 'WARN', Error = 'ERROR' }
// src/actions/log.ts
'use server'
import { LogLevels } from '../shared/enums'
export async function sendLog(level: LogLevels, message: string) {
// ...
}
3.4 ルールD:"use client" 側は “import して使うだけ” に寄せ、中継 re-export を増やさない
✅ OK
'use client'
import { updateUser } from '../actions/user'
export function Form() {
return <button onClick={() => updateUser(new FormData())}>update</button>
}
❌ NG(この記事では避ける:境界追跡が難しくなる)
'use client'
export { updateUser } from '../actions/user'
4. Next.js 16 で「厳しめチェック」を固定する(再現手順)
4.1 重要:Next.js 16 では next lint が削除されている
Next.js 16 では next lint が削除され、ESLint CLI を使う形に移行しています。
したがって、この記事では ESLint CLI を前提にします。
4.2 Next.js 公式の“厳しめプリセット”として eslint-config-next/core-web-vitals を使う
公式ドキュメント上、eslint-config-next/core-web-vitals は「ベース設定に加え、Core Web Vitals に影響するルールを warning → error に上げる」構成で、多くのプロジェクトに推奨されています。
例:CI で「警告ゼロ」を強制し、型チェックとビルドもセットで通す
package.json
{
"scripts": {
"lint": "eslint . --max-warnings=0",
"typecheck": "tsc -p tsconfig.json --noEmit",
"build": "next build",
"ci": "npm run lint && npm run typecheck && npm run build"
}
}
eslint.config.mjs(Flat config 例)
import nextVitals from 'eslint-config-next/core-web-vitals'
import nextTs from 'eslint-config-next/typescript'
export default [
...nextVitals,
...nextTs,
]
注意:ESLint はルール追加でいくらでも厳しくできます。
この記事は「Next.js 公式が提供する設定の範囲で、再現しやすい“厳しめ”」を提示しています。
5. この構造で潰せる “export 起因” の事故(代表例)
-
"use server"ファイルで async 以外(enum / const / object / class など)を export してしまう
→ ルールA・Cで回避 -
"use server"ファイルでexport */ re-export を使い、意図せず async 以外が混入
→ ルールBで回避 -
"use client"側で中継 re-export を増やして境界が読めなくなる
→ ルールDで回避
6. それでも残る “export 設計だけでは 0 にできない” 実行時エラー
代表例として、公式ドキュメントに載っている Failed to find Server Action ... は、
export の形が正しくても デプロイや実行環境に起因して発生し得ます。
この種のエラーは「export 設計ルール」では 100% 予防できません。
7. 参考リンク(公式)
-
use client(Directive) -
use server(Directive) - エラーメッセージ:
invalid-use-server-value - エラーメッセージ:
failed-to-find-server-action - ESLint 設定(Next.js 16)
Discussion