Nuxt 3 から Nuxt 4 への移行とは、nuxt を 4.x に上げ、app/ ディレクトリへの移動と、useFetch・useAsyncData の挙動の変更(data の shallowRef 化、既定値 undefined、pending の意味など)に合わせてコードを直す作業です。 Nuxt 3 は 2026-07-31 に公式サポート期間を終えましたが、3.21.11(npm の 3x タグ)は今回の検証でも問題なく動作しました。移行するかどうか、いつ行うかは各プロジェクトの事情で判断してください。

この記事では、pages・components・composables・server/api・layouts・middleware・plugins を含む Nuxt 3.21.11 の小さなサンプルを作り、Nuxt 4.5.2 へ実際に移行しました。npx nuxi upgrade のログ、出た型エラー・警告の実物、移行前後で画面の値がどう変わったか(Playwright で読み取り)、ビルド時間と出力サイズ、さらに Nuxt 5 に向けた compatibilityVersion: 5 で実際に起きたサーバーエラーまで載せています。

Nuxt 3 → 4 移行の早見表

変更点 Nuxt 3 Nuxt 4 今回のサンプルで起きたこと 直し方
ディレクトリ 直下に pages/ など app/ の下(旧構成も自動判定で動く) ~/types/task が見つからない(TS2307) shared/types/ へ移し #shared/... で import
data の反応性 ref(深い) shallowRef(浅い) push しても画面が更新されない 配列ごと置き換える/deep: true
data・error の既定値 null undefined === null の判定が常に false === undefined か !data.value
pending(immediate: false) 最初から true 実行するまで false 「読み込み中」表示が変化 status で判定
同じキーの呼び出し 別々に動く data・error・status を共有 警告 [NUXT_E3004]、合計が「0 件」 キーを分ける
route.meta.name 使える route.name に一本化 表示が空文字 route.name
TypeScript 設定 .nuxt/tsconfig.json 1つ app / server / shared / node に分割 — ルートの tsconfig.json を references に
head の hid / vmid Nuxt 3.21 で既に型エラー 削除 Nuxt 3.21 の時点で TS2353 削除する
依存ライブラリ vue-router 4.6.4 vue-router 5.3.1 旧 vue-router が残り型チェックが失敗 package.json から vue-router を外す

一時的に Nuxt 3 の動きに戻す設定も用意されています(後述の表)。まず戻し設定で動かし、1項目ずつ外していく進め方もできます。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Nuxt3からNuxt4への移行手順|実際のエラーと対処を全記録」

検証に使ったバージョンと流れ

項目 移行前 移行後
nuxt 3.21.11 4.5.2
Vue 3.5.43 3.5.43
Vite(ビルドに使われた版) 7.3.6 8.3.1
vue-router 4.6.4 5.3.1
@unhead/vue 2.1.17 3.4.1
nitropack 2.13.4 2.13.4
Node.js 22.22.2 22.22.2(Nuxt 4.5.2 は ^22.19.0 || ^24.11.0 || >=26.0.0)
TypeScript / vue-tsc 5.9.3 / 3.3.11 5.9.3 / 3.3.11
flowchart LR
  A[Nuxt 3.21 で型エラー0] --> B[compatibilityVersion: 4 で試す]
  B --> C[npx nuxi upgrade]
  C --> D[依存の整理]
  D --> E[app/ と shared/ へ移動]
  E --> F[挙動の変更を修正]
  F --> G[compatibilityVersion: 5 で試す]

移行前のサンプル(Nuxt 3.21)

task-board/
├── app.vue
├── nuxt.config.ts
├── components/TaskList.vue
├── composables/useTasks.ts
├── layouts/default.vue        # route.meta.name を表示
├── middleware/auth.ts
├── pages/index.vue            # useFetch と data の書き換え
├── pages/tasks/[id].vue       # null 判定と immediate: false
├── plugins/logger.ts
├── server/api/tasks/index.get.ts
├── server/api/tasks/[id].get.ts
├── types/task.ts              # app と server の両方から import
└── utils/format.ts

移行で影響が出やすい部分だけ抜粋します(移行前)。

<!-- pages/index.vue(移行前) -->
<script setup lang="ts">
const tag = ref('')
const { data: tasks, pending, refresh } = await useTasks(tag) // key: 'tasks'

// 別の場所で同じキー 'tasks' を別の transform で使う
const { data: summary } = await useFetch('/api/tasks', {
  key: 'tasks',
  transform: (list) => ({ total: list.length }),
})

function addLocal() {
  tasks.value?.push({ id: 99, title: 'ローカル追加', done: false, tags: [] })
}
</script>
<!-- pages/tasks/[id].vue(移行前・script 部分) -->
<script setup lang="ts">
import type { Task } from '~/types/task'

definePageMeta({ middleware: ['auth'], name: 'task-detail' })
const route = useRoute()
const id = String(route.params.id)
const { data: task, error } = await useFetch(`/api/tasks/${id}`)

const notFound = computed(() => task.value === null)

const { data: memo, pending: memoPending, execute } = useAsyncData(
  `memo-${id}`,
  () => $fetch<Task>(`/api/tasks/${id}`),
  { immediate: false },
)
</script>
// server/api/tasks/[id].get.ts(移行前:自動インポートを利用)
export default defineEventHandler((event) => {
  const id = Number(getRouterParam(event, 'id'))
  if (id > 3) {
    throw createError({ statusCode: 404, statusMessage: 'Task not found', data: { id } })
  }
  return { id, title: `タスク ${id}`, done: false, tags: [] }
})

手順0:Nuxt 3 のうちに整えておくこと

移行前に nuxt typecheck をエラー0件にしておくと、移行で増えたエラーだけを見分けられます。 今回、Nuxt 3.21.11 の時点で次が出ました。

nuxt.config.ts(7,16): error TS2353: Object literal may only specify known properties, and 'hid' does not exist in type ...
plugins/logger.ts(2,7): error TS2591: Cannot find name 'process'. ...
pages/tasks/[id].vue(11,9): error TS2321: Excessive stack depth comparing types ...
エラー 原因 対処(Nuxt 3 のまま可能)
'hid' does not exist Nuxt 3.21 は既に Unhead v2 系(@unhead/vue 2.1.17)で、hid がない hid: 'description' を削除
Cannot find name 'process' process.server はブラウザ側の型にない import.meta.server に置き換え
Excessive stack depth テンプレート文字列 URL の $fetch で戻り値の型推論が深くなる $fetch<Task>(...) と型を明示

TypeScript のバージョンにも注意が必要です。2026年9月時点で npm の typescript の latest は 7.0.2 で、vue-tsc 3.3.11 と組み合わせると型チェック自体が起動しませんでした。

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/tsc' is not defined by "exports" in .../node_modules/typescript/package.json

typescript@~5.9(または 6.0.3)に固定すると動きました。 型チェック用の TypeScript は、vue-tsc の対応を確認してから上げると安心です。

手順1:compatibilityVersion: 4 で先に試す

Nuxt 3 のまま、Nuxt 4 の既定値に切り替えて動かせます。 パッケージを上げる前に挙動の差を洗い出せるのが利点です。

// nuxt.config.ts(Nuxt 3.21.11)
export default defineNuxtConfig({
  future: { compatibilityVersion: 4 },
  compatibilityDate: '2025-07-15',
})

起動時に [nuxt] i Running with compatibility version 4 と表示されます。型チェックはこの状態でもエラー0件でしたが、画面の値は変わりました。 ビルドして Playwright(Chromium)で読み取った結果です。

確認した値 Nuxt 3.21(通常) Nuxt 3.21 + compat 4 Nuxt 4.5(修正前) Nuxt 4.5(修正後)
合計件数(summary.total) 0 件 0 件 0 件 3 件
「ローカル追加」後の件数 4 3 3 4
レイアウトのルート名 "" / 詳細で task-detail "" "" index / task-detail
/tasks/9(404)の表示 見つかりません(404) 表示されない 表示されない 見つかりません(404)
immediate: false の状態 memoPending=true memoPending=false memoPending=false memoStatus=idle

型エラーが出ないまま動きが変わる箇所があるため、画面やテストでの確認が大切です。なお「合計 0 件」は Nuxt 3 のときから同じキーの共有で起きていた表示のずれで、Nuxt 4 では開発サーバーが警告で知らせてくれるようになりました(手順6)。

手順2:npx nuxi upgrade を実行する

公式ガイドの手順どおり、アップグレードコマンドを実行します(npx nuxt upgrade でも同じ)。対話プロンプトで止まらないよう --dedupe を付けました。

npx nuxi upgrade --dedupe

実行ログ(抜粋):

o  Package manager: npm 10.9.7
o  Current Nuxt version: 3.21.11
added 20 packages, removed 28 packages, changed 42 packages, and audited 609 packages in 14s
o  Dependencies deduped
*  Successfully upgraded Nuxt from 3.21.11 to 4.5.2
—  ✨ Upgrade complete!

--dedupe を付けないと「dedupe lockfile / recreate node_modules and package-lock.json / skip」の選択肢が出ます。変更されたのは package.json の "nuxt": "^4.5.2" と lockfile だけです。

手順3:依存を整理する(vue-router が残る)

package.json に直接書いていた "vue-router": "^4.5.0" はそのまま残り、Nuxt 4.5.2 が使う vue-router 5.3.1 と2つが同居しました。この状態で nuxt typecheck を実行すると次のように失敗します。

[Vue] Resolve plugin path failed: vue-router/volar/sfc-route-blocks Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './volar/sfc-route-blocks' is not defined by "exports" in .../node_modules/vue-router/package.json

npm uninstall vue-router で外し、node_modules と package-lock.json を作り直すと解消しました(外しただけでは 5.3.1 が nuxt/node_modules の下に残り、Cannot find module 'vue-router/volar/sfc-route-blocks' に変わりました)。

npm uninstall vue-router
rm -rf node_modules package-lock.json
npm install

Nuxt が内部で使うパッケージ(vue-router、@unhead/vue など)を package.json に直接書いている場合は、移行時に見直すのがポイントです。

手順4:公式 codemod で自動化する

Nuxt 公式ガイドでは、Codemod チームと作った自動変換がまとめて実行できると案内されています(CLI のバージョンは公式ガイドの記載どおり固定)。

npx codemod@0.18.7 nuxt/4/migration-recipe
codemod(個別実行) 自動化する内容
npx codemod@latest nuxt/4/file-structure app/ への移動
npx codemod@latest nuxt/4/default-data-error-value null 判定を undefined に
npx codemod@latest nuxt/4/deprecated-dedupe-value refresh({ dedupe: true }) を 'cancel' などに
npx codemod@latest nuxt/4/shallow-function-reactivity deep: true の付与
npx codemod@latest nuxt/4/absolute-watch-path builder:watch のパスを絶対パスに
npx codemod@latest nuxt/4/template-compilation-changes モジュールのテンプレート記法の変更

今回の検証環境では codemod の配布元(codemod.com のレジストリ)へ接続できず、実行できませんでした(codemod@0.18.7 は Request failed with status code 405、codemod@latest(1.18.3)は tunnel error で取得失敗)。そのため、以下の手順5・6は codemod が行う変換を手作業で行った記録です。ネットワークに制限のない環境では、先に recipe を実行して差分を確認すると手作業を減らせます。

手順5:app/ と shared/ へ移動する

mkdir app
git mv app.vue components composables layouts middleware pages plugins utils app/
git rm server/tsconfig.json

nuxt.config.ts・server/・public/ は直下のままです。移動後の型チェックで、app と server の両方から使っていた型ファイルが見つからなくなりました。

app/components/TaskList.vue(2,27): error TS2307: Cannot find module '~/types/task' or its corresponding type declarations.
server/api/tasks/index.get.ts(2,27): error TS2307: Cannot find module '~/types/task' or its corresponding type declarations.

Nuxt 4 では ~ が app/ を指すため、直下の types/ には届きません。 app と server で共有するものは新しい shared/ に置きます。

mkdir shared
git mv types shared/types
# import を置き換え
#   import type { Task } from '~/types/task'
# → import type { Task } from '#shared/types/task'

ルートの tsconfig.json は、公式ガイドのとおりプロジェクト参照(references)に変えました。

{
  "files": [],
  "references": [
    { "path": "./.nuxt/tsconfig.app.json" },
    { "path": "./.nuxt/tsconfig.server.json" },
    { "path": "./.nuxt/tsconfig.shared.json" },
    { "path": "./.nuxt/tsconfig.node.json" }
  ]
}

nuxt prepare で .nuxt/ に tsconfig.app.json・tsconfig.server.json・tsconfig.shared.json・tsconfig.node.json が生成され、この時点で型チェックはエラー0件になりました。

task-board/
├── app/            # app.vue, components, composables, layouts, middleware, pages, plugins, utils
├── server/api/tasks/
├── shared/types/task.ts
├── public/
├── nuxt.config.ts
└── tsconfig.json

移動は必須ではありません。 旧構成のままでも Nuxt 4 は自動判定で動きます(今回もアップグレード直後の旧構成のままビルドでき、画面は「Nuxt 4.5(修正前)」列と同じ結果でした)。

手順6:データ取得の挙動の変更を直す

同じキーの共有:警告 NUXT_E3004

開発サーバー(nuxt dev)で一覧ページを開くと、次の警告が出ました。

WARN  [console.warn] ssr:warn [NUXT_E3004] Incompatible options detected for "tasks":
- different transform option
├▶ fix: You can use a different key or move the call to a composable to ensure the options are shared across calls.

Nuxt 4 では同じキーの呼び出しが data・error・status を共有するため、transform が違う呼び出しに同じキーを付けると衝突します。

 const { data: summary } = await useFetch('/api/tasks', {
-  key: 'tasks',
+  key: 'tasks-summary',
   transform: (list) => ({ total: list.length }),
 })

修正後、合計は 「3 件」 になりました。

data が shallowRef になった

 function addLocal() {
-  tasks.value?.push({ id: 99, title: 'ローカル追加', done: false, tags: [] })
+  tasks.value = [...(tasks.value ?? []), { id: 99, title: 'ローカル追加', done: false, tags: [] }]
 }

data の中身を書き換えても再描画されないため、値ごと置き換えます。 深い反応性が必要な呼び出しだけ useFetch(url, { deep: true }) にする方法もあります。

既定値が null から undefined に

-const notFound = computed(() => task.value === null)
+const notFound = computed(() => task.value === undefined)

=== null は型エラーにならないため、検索で === null を洗い出すのが確実です。

pending より status を使う

-const { data: memo, pending: memoPending, execute } = useAsyncData(
+const { data: memo, status: memoStatus, execute } = useAsyncData(

immediate: false の場合、pending は実行するまで false です。status(idle / pending / success / error)で分けると、Nuxt 3 と 4 で意味が変わりません。

route.meta.name は route.name に

-<small>{{ route.meta.name }}</small>
+<small>{{ route.name }}</small>

修正後の画面は、手順1の表の「Nuxt 4.5(修正後)」列のとおり全項目が期待どおりになりました。

対処一覧(今回実際に起きたもの)

出たもの 種類 対処
'hid' does not exist in type 型(Nuxt 3.21 から) hid を削除
Cannot find name 'process' 型 import.meta.server
ERR_PACKAGE_PATH_NOT_EXPORTED ... './lib/tsc' 型チェック起動失敗 TypeScript を 5.9 / 6.0 に固定
Resolve plugin path failed: vue-router/volar/sfc-route-blocks 型チェック 直接依存の vue-router を外し lockfile 再作成
Cannot find module '~/types/task' 型 shared/types/ と #shared/...
[NUXT_E3004] Incompatible options detected 開発時の警告 キーを分ける/composable にまとめる
追加しても件数が増えない 挙動 値ごと置き換え/deep: true
404 の表示が出ない 挙動 undefined 判定
ルート名が空 挙動 route.name

一時的に Nuxt 3 の動きに戻す設定

公式ガイドに記載のある設定です。移行を段階的に進めるための一時的な設定として使えます。

変更点 戻す設定
app/ 構成 srcDir: '.'、dir: { app: 'app' }
同じキーの共有・データ破棄 experimental: { granularCachedData: false, purgeCachedData: false }
shallowRef experimental: { defaults: { useAsyncData: { deep: true } } }
pending experimental: { pendingWhenIdle: true }
キー変更時の再取得 experimental: { alwaysRunFetchOnKeyChange: true }
コンポーネント名の正規化 experimental: { normalizeComponentNames: false }
Unhead unhead: { legacy: true }
SPA ローディングの位置 experimental: { spaLoadingTemplateLocation: 'within' }
ページメタの走査 experimental: { scanPageMeta: true }
プリレンダー時のデータ共有 experimental: { sharedPrerenderData: false }
グローバル CSS のインライン化 features: { inlineStyles: true }

今回のサンプルでは起きなかった変更:error.data の自動パース、window.__NUXT__ の削除(useNuxtApp().payload を使う)、ミドルウェアのサブフォルダ index の走査、トップレベル generate 設定の廃止(nitro.prerender へ)、refresh({ dedupe: boolean }) の廃止など。該当するコードがあるかは公式ガイドの各項目で確認できます。

主要モジュールの対応状況

npm に公開されている最新版の、モジュール定義 meta.compatibility.nuxt を確認しました(2026-09-29)。

モジュール 最新版 対応する Nuxt
@nuxt/content 3.16.1 >=4.1.0 || ^3.19.0
@nuxt/ui 4.11.2 >=4.1.0
@nuxt/icon 2.5.1 >=4.0.0
@pinia/nuxt 1.0.2 ^3.15.0 || ^4.0.0 || ^5.0.0
@nuxtjs/i18n 10.6.0 >=3.0.0-rc.11
@nuxtjs/sitemap 8.5.1 >=3.9.0
@nuxtjs/tailwindcss 6.14.0 ^2.9.0 || >=3.0.0-rc.1

@nuxt/ui 4 と @nuxt/icon 2 は Nuxt 4 以上が前提です。Nuxt 3 のまま使う場合は、それぞれの前のメジャー版をリリースノートで確認して選びます。@nuxt/image・@vueuse/nuxt・nuxt-auth-utils・@nuxtjs/color-mode・@nuxt/fonts は meta.compatibility の指定がなく、依存する @nuxt/kit は 4.x 系でした。

移行前後のビルド時間と出力サイズ

同じサンプルで nuxt build を各3回(.nuxt とキャッシュを消して)実行しました。

項目 Nuxt 3.21.11 Nuxt 4.5.2 4.5.2 + compat 5
所要時間(3回) 15.5 / 22.0 / 16.6 秒 15.4 / 19.2 / 22.1 秒 —(1回のみ計測)
うちクライアントのビルド 3,769ms 2,686ms 2,710ms
.output 合計(Nitro の表示) 1.99 MB(gzip 500 kB) 2.14 MB(gzip 544 kB) 2.13 MB(gzip 540 kB)
ブラウザ用 JS 合計 216,956 B(gzip 80,396) 209,509 B(gzip 77,416) 202,952 B(gzip 75,061)

所要時間は共有環境のため±数秒ぶれ、差はばらつきの範囲でした。ブラウザに送る JS は Nuxt 4 で約3%減、compat 5 でさらに約3%減です。.output 全体はサーバー側のファイルが増えたため少し大きくなりました。

Nuxt 5 に向けて compatibilityVersion: 5 を試す

Nuxt 5 は開発中(公式ドキュメントでは nightly 扱い)で、Nuxt 4.2 以降なら多くの変更を先に試せます。

// nuxt.config.ts(Nuxt 4.5.2)
export default defineNuxtConfig({
  future: { compatibilityVersion: 5 },
  compatibilityDate: '2025-07-15',
})

実際に起きたこと:サーバーの自動インポート

型チェックで、自動インポートに頼っていた API ルートがエラーになりました。

server/api/tasks/[id].get.ts(1,16): error TS2304: Cannot find name 'defineEventHandler'.
server/api/tasks/[id].get.ts(2,21): error TS2304: Cannot find name 'getRouterParam'.
server/api/tasks/[id].get.ts(4,11): error TS2304: Cannot find name 'createError'.

nuxt build は成功しますが、実行するとこの API が 500 になりました。

[request error] [unhandled] [GET] http://127.0.0.1:7475/api/tasks/2
 ReferenceError: defineEventHandler is not defined

Nuxt 4.5.2 の設定定義を見ると、experimental.nitroAutoImports の既定値は compatibilityVersion < 5 のときだけ true でした。Nuxt 5 の公式ガイドでも、Nitro v3 で自動インポートがなくなり、明示的に import する形(Nuxt 5 では nuxt/server から)になると案内されています。Nuxt 4.5.2 の段階では h3 から import して解消しました。

// server/api/tasks/[id].get.ts
import { createError, defineEventHandler, getRouterParam } from 'h3'

export default defineEventHandler((event) => {
  const id = Number(getRouterParam(event, 'id'))
  if (id > 3) {
    throw createError({ statusCode: 404, statusMessage: 'Task not found', data: { id } })
  }
  return { id, title: `タスク ${id}`, done: false, tags: [] }
})

修正後は /api/tasks/2 が JSON を返し、/api/tasks/9 は 404、画面の値もすべて期待どおりでした。一時的に以前の動きのまま試すなら experimental: { nitroAutoImports: true } を指定します。

compatibilityVersion: 5 で変わる主な既定値(公式ガイドより)

変更 内容 個別に切り替える設定
Vite Environment API client / server の設定を1つに統合 experimental.viteEnvironmentApi
ページコンポーネント名 ルート名と一致(<KeepAlive> で使いやすい) experimental.normalizePageNames
clearNuxtState 初期値に戻す experimental.defaults.useState.resetOnClear
callHook Promise を返さない場合がある experimental.asyncCallHook
クライアント専用コンポーネント SSR 時の目印がコメントノードに experimental.clientNodePlaceholder
型チェック noUncheckedSideEffectImports を有効化 typescript.tsConfig
Options API クライアントのバンドルから除外 vue.optionsApi: true で戻す

今回、開発サーバーの表示は Vite client built と Vite server built の2行から Vite dev server built in 42ms の1行に変わりました。ブラウザ用 JS が約6.5KB 減ったのは、Options API の除外(公式の目安は約6kB)と合う結果です。Options API で書いたコンポーネントがある場合は vue.optionsApi: true を指定します。

よくある質問

Q. 移行は一度にやる必要がありますか? A. 段階的に進められます。Nuxt 3.21 で compatibilityVersion: 4 を試し、Nuxt 4 に上げたあとも「戻す設定」を使いながら1項目ずつ外していけます。app/ への移動も必須ではありません。

Q. 型チェックが通れば移行は完了ですか? A. 今回、shallowRef・undefined・pending・キー共有の4つは型エラーなしで画面の値が変わりました。E2E テストや画面での確認を合わせるのがおすすめです。

Q. codemod はどこまで自動化してくれますか? A. ディレクトリ移動、null 判定、dedupe の値、deep の付与などです。キーの衝突やレイアウトの route.meta.name のように、設計の判断が必要な箇所は手で直します。

Q. Nuxt 4 のうちに Nuxt 5 の準備はできますか? A. compatibilityVersion: 5 で試せます。今回はサーバーの自動インポートが最も大きな差で、API ルートに明示的な import を足すと解消しました。

まとめ

  • Nuxt 3.21 のうちに型エラー0件と compatibilityVersion: 4 の確認をしておくと移行がスムーズ
  • npx nuxi upgrade --dedupe で 3.21.11 → 4.5.2 へ。直接依存の vue-router 4 は外して lockfile を作り直す
  • app/ への移動で ~ の指す先が変わる。共有する型は shared/ と #shared/... へ
  • shallowRef・undefined・pending・同じキーの共有は型エラーなしで挙動が変わるため画面で確認
  • 迷ったら 公式の「戻す設定」で段階的に進められる
  • ブラウザ用 JS は約3%減、compatibilityVersion: 5 でさらに約3%減
  • Nuxt 5 に向けては、サーバーコードの明示的な import が最初の準備

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Nuxt3からNuxt4への移行手順|実際のエラーと対処を全記録」

株式会社RJCでは、フレームワークのバージョンアップを小さなサンプルで試し、手順と注意点をチームで共有しながらプロジェクトを進めています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?