ESM(ECMAScript Modules)はimport / exportで読み書きするJavaScript標準のモジュール形式、CommonJSはrequire / module.exportsを使うNode.js従来のモジュール形式です。Node.jsは「拡張子」と「package.jsonのtype」でファイルごとにどちらの形式かを決めており、混在時のエラーの多くは、この判定と書いた構文が食い違うことで起こります。

この記事では、Node.js 18.20.8 / 20.18.3 / 20.20.2 / 22.11.0 / 22.22.2 / 24.21.0 の6つの版で同じコードを動かし、ERR_REQUIRE_ESM、ERR_REQUIRE_ASYNC_MODULE、「Cannot use import statement outside a module」が出る・出ないを表にしました。requireでESMを読み込める版(20.19以降・22.12以降)を境に結果が変わるため、手元の版と見比べながら読めるようにしています。エラー文から最短の直し方を引ける逆引き表も付けました。

ESMとCommonJSの早見表

比べる点 CommonJS(CJS) ESM
読み込み const x = require('x') import x from 'x'
書き出し module.exports = ... / exports.a = ... export default ... / export const a = ...
読み込みのタイミング 実行時に同期で読む 実行前に依存関係を解析して読む
拡張子で指定 .cjs .mjs
.js の扱い typeなし、または "type": "commonjs" "type": "module"
__dirname / __filename 使える import.meta.dirname / import.meta.filename
require 使える createRequire で作る
トップレベルawait 使えない 使える
相対パスの拡張子 省略できる(./lib) 必要(./lib.js)
JSONの読み込み require('./data.json') import data from './data.json' with { type: 'json' }
相手の形式を読む import()、または新しい版では require() import でそのまま読める
出たエラー まず試す直し方
Cannot use import statement outside a module package.jsonに "type": "module" を足す、または拡張子を .mjs にする
ERR_REQUIRE_ESM Node.jsを20.19以降 / 22.12以降にする、または await import() に変える
ERR_REQUIRE_ASYNC_MODULE 読み込む側を await import() に変える
require is not defined in ES module scope import に書き換える、または createRequire を使う
__dirname is not defined in ES module scope import.meta.dirname に置き換える

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

(記載例)出典:株式会社RJC「Node.js ESMとCommonJSの違い|import混在の解決表」

この記事の確認環境

項目 内容
動かした版 Node.js 18.20.8 / 20.18.3 / 20.20.2 / 22.11.0 / 22.22.2 / 24.21.0
入手方法 22.22.2は実行環境のもの、ほかはnpmの node パッケージで作業フォルダに導入
OS Linux(x64)
仕様の確認 Node.js公式ドキュメントの「Modules: CommonJS modules」と「Modules: ECMAScript modules」のページを開いて確認

出力例のパスは /home/taro/app に置き換えています(表示は環境に合わせて置き換えています)。スタックトレースの行(at ...)は省いています。

Node.jsがESMかCommonJSかを決める仕組み

判定の順番

Node.jsは、ファイルを読むたびに次の順で形式を決めます(公式ドキュメントで確認)。

flowchart TD
    A[ファイルを読み込む] --> B{拡張子は?}
    B -- .mjs --> E[ESM]
    B -- .cjs --> C[CommonJS]
    B -- .js --> D{一番近いpackage.jsonのtype}
    D -- module --> E
    D -- commonjs --> C
    D -- 指定なし --> F{import / export などESMの構文がある?}
    F -- ない --> C
    F -- ある --> G[新しい版: ESMとして読み直す / 以前の版: SyntaxError]

拡張子が最優先で、.js のときだけpackage.jsonのtypeを見ます。 typeは、そのファイルから親フォルダへたどって最初に見つかるpackage.jsonのものが使われます。

拡張子 × type指定の早見表

ファイル typeなし "type": "commonjs" "type": "module"
.js CommonJS(ESMの構文があれば新しい版ではESMとして読み直す) CommonJS ESM
.mjs ESM ESM ESM
.cjs CommonJS CommonJS CommonJS

拡張子 × type × 読み込み方法の組合せ表

読み込む側と読み込まれる側の組合せごとの結果です。「新しい版」は20.19以降の20系、22.12以降、24を指します。

読み込む側 読み込み方 読み込まれる側 結果
CJS(.cjs、typeなしの .js) require() CJS 動く
CJS require() ESM(.mjs、type moduleの .js) 新しい版は動く / 18・20.18・22.11は ERR_REQUIRE_ESM
CJS require() トップレベルawaitを含むESM 新しい版は ERR_REQUIRE_ASYNC_MODULE / 以前の版は ERR_REQUIRE_ESM
CJS await import() ESM(awaitを含んでもよい) どの版でも動く
CJS(.cjs) import 文 何でも Cannot use import statement outside a module
ESM(.mjs、type moduleの .js) import 文 ESM 動く
ESM import 文 CJS 動く(module.exports がdefaultになる)
ESM require() 何でも require is not defined in ES module scope
ESM createRequire で作ったrequire CJS・JSON 動く

バージョン別の実行結果:どのエラーが出るか

検証に使ったコード

typeを書いていないフォルダに、次のファイルを置きました。

{ "name": "cjsproj", "version": "1.0.0" }
// lib.mjs(ESM)
export function hello() { return 'hello from ESM'; }
export default { name: 'lib' };
// tla.mjs(トップレベルawaitを含むESM)
const value = await Promise.resolve(42);
export { value };
// t1.js(typeなしの .js に import 文)
import os from 'node:os';
console.log('t1 ok:', typeof os.platform());
// t2.cjs(CommonJS から ESM を require)
const m = require('./lib.mjs');
console.log('t2 ok:', m.hello(), m.default);
// t3.cjs(トップレベルawaitを含む ESM を require)
const m = require('./tla.mjs');
console.log('t3 ok:', m.value);
// t4.cjs(動的 import)
import('./tla.mjs').then((m) => console.log('t4 ok:', m.value));
// t5.cjs(.cjs に import 文)
import { hello } from './lib.mjs';
console.log('t5 ok:', hello());

バージョン別の結果表

コード 18.20.8 20.18.3 20.20.2 22.11.0 22.22.2 24.21.0
t1:typeなし .js にimport文 SyntaxError(Cannot use import statement…) SyntaxError(同左) 動く(警告あり) 動く(警告あり) 動く(警告あり) 動く(警告あり)
t2:require() でESM ERR_REQUIRE_ESM ERR_REQUIRE_ESM 動く ERR_REQUIRE_ESM 動く 動く
t3:require() でawait入りESM ERR_REQUIRE_ESM ERR_REQUIRE_ESM ERR_REQUIRE_ASYNC_MODULE ERR_REQUIRE_ESM ERR_REQUIRE_ASYNC_MODULE ERR_REQUIRE_ASYNC_MODULE
t4:import() でawait入りESM 動く 動く 動く 動く 動く 動く
t5:.cjs にimport文 SyntaxError SyntaxError SyntaxError SyntaxError SyntaxError SyntaxError

読み取れることは次のとおりです。

  • require() でESMを読めるかは、メジャー番号ではなくマイナー番号で決まります。 同じ20系でも20.18.3はエラー、20.20.2は動きました。22系も22.11.0はエラー、22.22.2は動きました
  • 公式ドキュメントの履歴では、この機能がフラグなしで使えるようになったのは v20.19.0 / v22.12.0 / v23.0.0 です。実験的という位置づけが外れたのはv25.4.0と記載されています
  • ERR_REQUIRE_ASYNC_MODULE は、requireでESMを読める版だけで出るエラーです。以前の版では同じコードが ERR_REQUIRE_ESM になります
  • import()(動的import)はどの版でも動きました。 版をそろえられない場合に確実な書き方です
  • .cjs は拡張子でCommonJSと決まるため、import文はどの版でもSyntaxErrorになります

実際のエラー文

t2をNode.js 18.20.8で実行した結果です。

Error [ERR_REQUIRE_ESM]: require() of ES Module /home/taro/app/lib.mjs not supported.
Instead change the require of /home/taro/app/lib.mjs to a dynamic import() which is available in all CommonJS modules.
  code: 'ERR_REQUIRE_ESM'

t2をNode.js 22.22.2で実行した結果です。名前つきexportはそのままプロパティに、default exportは default プロパティに入ります。

t2 ok: hello from ESM { name: 'lib' }

t3をNode.js 22.22.2で実行した結果です。

Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. Use import() instead. To see where the top-level await comes from, use --experimental-print-required-tla.
  From /home/taro/app/t3.cjs
  Requiring /home/taro/app/tla.mjs
  code: 'ERR_REQUIRE_ASYNC_MODULE'

Node.js 24.21.0では同じエラーの後半の書式が少し変わります。

Required module: /home/taro/app/tla.mjs
Require stack:
- /home/taro/app/t3.cjs

t1をNode.js 18.20.8で実行した結果です。

(node:5570) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
/home/taro/app/t1.js:1
import os from 'node:os';
SyntaxError: Cannot use import statement outside a module

t1をNode.js 22.22.2で実行した結果です。動きますが、形式を明示するよう促す警告が出ます。

t1 ok: string
(node:6899) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/taro/app/t1.js is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /home/taro/app/package.json.

いったんCommonJSとして解析し、ESMの構文を見つけたら読み直すという動きなので、起動のたびに余分な処理が入ります。package.jsonにtypeを書いておくと、警告も読み直しもなくなります。

t5をNode.js 22.22.2で実行した結果です。

(node:6951) Warning: Failed to load the ES module: /home/taro/app/t5.cjs. Make sure to set "type": "module" in the nearest package.json file or use the .mjs extension.
/home/taro/app/t5.cjs:1
import { hello } from './lib.mjs';
SyntaxError: Cannot use import statement outside a module

ESMの中で使えなくなるものと置き換え方

"type": "module" を書いたフォルダで、CommonJSの書き方をそのまま動かした結果です。ここからの結果は6つの版すべてで同じでした(異なる箇所は表に書いています)。

{ "name": "esmproj", "version": "1.0.0", "type": "module" }

requireと__dirnameはエラーになる

// e1.js
const os = require('node:os');
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/home/taro/app/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
// e2.js
console.log(__dirname);
ReferenceError: __dirname is not defined in ES module scope

module.exports = { a: 1 } と書いた場合は ReferenceError: module is not defined in ES module scope でした。エラー文の2行目に、ESMとして扱われた理由と、CommonJSに戻す方法(拡張子を .cjs にする)が書かれているので、ここを読むと判定の経緯がわかります。

対応表:__dirname・require・JSON読込・トップレベルawait

CommonJSでの書き方 ESMでの書き方 使える版 今回の実行結果
__dirname import.meta.dirname v20.11.0 / v21.2.0以降 18.20.8は undefined、20.18.3以降は動く
__filename import.meta.filename 同上 同上
__dirname(18系にも対応) path.dirname(fileURLToPath(import.meta.url)) ESMが使える全版 6つの版すべてで動く
require('x') import x from 'x' 全版 動く
require() をそのまま使いたい createRequire(import.meta.url) 全版 6つの版すべてで動く
require('./data.json') import data from './data.json' with { type: 'json' } 下の表を参照 6つの版すべてで動く(22.11.0は実験的機能の警告つき)
module.exports = x export default x 全版 —
exports.a = 1 export const a = 1 全版 —
即時関数で await を包む トップレベルawait v14.8.0以降 6つの版すべてで動く
require.resolve('x') import.meta.resolve('x') v20.6.0 / v18.19.0以降で同期の文字列を返す 18.20.8 / 20.20.2 / 22.22.2 / 24.21.0で動く(file: のURL文字列を返す)
require.main === module import.meta.main 新しい版で追加 18.20.8 / 20.20.2は undefined、22.22.2 / 24.21.0は true

import.meta.dirname と import.meta.filename は、公式ドキュメントでv20.11.0 / v21.2.0で追加、v22.16.0 / v24.0.0で安定版になったと記載されています。

コピペ用:どの版でも動く__dirnameとrequire

// e5.js("type": "module" のフォルダ、または .mjs)
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import { createRequire } from 'node:module';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const require = createRequire(import.meta.url);

const data = require('./data.json');
console.log('e5 ok:', __dirname, data);
e5 ok: /home/taro/app { title: 'sample', count: 3 }

Node.js 20.11以降だけを対象にするなら、次の1行で済みます。

// e4.js
console.log(import.meta.dirname, import.meta.filename);
/home/taro/app /home/taro/app/e4.js

JSONを読み込む

// e6.js
import data from './data.json' with { type: 'json' };
console.log('e6 ok:', data);
e6 ok: { title: 'sample', count: 3 }

with { type: 'json' } を省いた場合の結果は、版によってエラーコードが違いました。

版 with を省いたときのエラー
18.20.8 / 20.18.3 / 20.20.2 TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///home/taro/app/data.json" needs an import attribute of type "json"
22.11.0 / 22.22.2 / 24.21.0 TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///home/taro/app/data.json" needs an import attribute of "type: json"

以前使われていた assert { type: 'json' } という書き方は、公式ドキュメントの履歴でv22.0.0でサポートを終えたと記載されています。これから書くコードは with にそろえると、版をまたいでも同じ形で動きます。

相対パスの拡張子は省略できない

// e9.js
import { hello } from './lib';
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/taro/app/lib' imported from /home/taro/app/e9.js
Did you mean to import "./lib.js"?
  code: 'ERR_MODULE_NOT_FOUND',

ESMのimportでは、相対パスに拡張子まで書きます。 エラー文が候補(./lib.js)を教えてくれるので、そのとおりに直します。フォルダ名だけを書いて index.js を読ませる書き方も、ESMでは ./dir/index.js まで書きます。

ESMからCommonJSを読む

// c.cjs
exports.add = (a, b) => a + b;
exports.name = 'c';
// e3.js
import pkg, { add } from './c.cjs';
console.log('e3 ok:', pkg, add(1, 2));
e3 ok: { add: [Function (anonymous)], name: 'c' } 3

ESMからCommonJSを読むのは、どの版でもそのまま動きました。default importには module.exports 全体が入ります。 exports.add = ... のような単純な書き方なら、名前つきimport({ add })でも取り出せます。名前つきで取り出せないライブラリは、defaultで受けてから pkg.add のように使うと確実です。

混在を解決する4つの方法と選び方

方法1:ESMにそろえる

package.jsonに "type": "module" を足し、require / module.exportsをimport / exportに書き換えます。設定ファイルなどCommonJSのまま残したいものは、拡張子を .cjs にします。

{
  "name": "app",
  "version": "1.0.0",
  "type": "module"
}

方法2:CommonJSのまま、ESMだけimport()で読む

// CommonJS のファイル
async function main() {
  const { hello } = await import('./lib.mjs');
  console.log(hello());
}
main();

import() はPromiseを返すため、呼び出し側をasync関数にします。 今回の検証(t4)では6つの版すべてで動き、トップレベルawaitを含むESMも読めました。

方法3:Node.jsを新しくしてrequire()で読む

20.19以降 / 22.12以降 / 24では、CommonJSのコードを書き換えずに require() でESMを読めます。公式ドキュメントに書かれている条件は次の2つです。

  • 読み込むESMとその依存先に、トップレベルawaitが含まれていないこと
  • ファイルがESMと判定されること(.mjs、type moduleの .js、またはtypeなしでESMの構文を含む .js)

type moduleのフォルダにある .js を、別フォルダのCommonJSからrequireした結果です。

// t6.cjs
const m = require('../esmproj/lib.js');
console.log('t6 ok:', m.hello());
版 結果
18.20.8 / 20.18.3 / 22.11.0 ERR_REQUIRE_ESM
20.20.2 / 22.22.2 / 24.21.0 t6 ok: hello from esmproj

この機能は --no-require-module フラグで無効にでき、--trace-require-module でどこで使われているかを表示できます(公式ドキュメントで確認、フラグの動作は未実行)。

方法4:ファイル単位で拡張子を変える

フォルダ全体のtypeを変えずに、1ファイルだけ形式を変えたいときは拡張子で指定します。ESMにしたいファイルは .mjs、CommonJSにしたいファイルは .cjs です。拡張子はtypeより優先されるので、判定で迷うことがなくなります。

選び方の判断表

状況 向いている方法
新しく作るアプリ 方法1(ESMにそろえる)
既存のCommonJSアプリで、ESM専用のライブラリを1つ使いたい(Nodeは20.19 / 22.12以降) 方法3(そのままrequire)
同上で、Nodeの版を上げられない、または複数の版で動かす 方法2(import())
読み込むESMがトップレベルawaitを使っている 方法2(import())または方法1
設定ファイルだけCommonJSで書く必要がある 方法4(.cjs)
スクリプト1本だけESMで書きたい 方法4(.mjs)
ライブラリを公開し、両方の形式から使ってもらう 次の節の exports 条件

ライブラリ側:exportsの条件で読み分ける

package.jsonの exports に import と require を書くと、読み込み方に応じて別のファイルを返せます。

{
  "name": "dual",
  "version": "1.0.0",
  "exports": {
    ".": {
      "import": "./index.mjs",
      "require": "./index.cjs"
    }
  }
}
// index.mjs
export default { kind: 'ESM版(index.mjs)' };
// index.cjs
module.exports = { kind: 'CommonJS版(index.cjs)' };

これを node_modules/dual に置き、両方の形式から読み込んだ結果です(6つの版すべてで同じ)。

// t7.cjs
const d = require('dual');
console.log('t7 ok:', d.kind);
// t8.mjs
import d from 'dual';
console.log('t8 ok:', d.kind);
t7 ok: CommonJS版(index.cjs)
t8 ok: ESM版(index.mjs)
条件名 選ばれる場面
import import 文または import() で読まれたとき
require require() で読まれたとき
default どれにも当てはまらないとき(最後に書く)

条件は上から順に評価されるので、default は最後に置きます。2つの形式で別々のファイルを配ると、同じライブラリが2回読み込まれて状態が別々になることがあります。状態を持つライブラリでは、本体をどちらか一方にして、もう一方は薄い橋渡しだけにする構成が扱いやすくなります(この構成の検証は未実行)。

エラー文から直し方を引く逆引き表

エラー文(一部) 起きていること 最短の直し方
SyntaxError: Cannot use import statement outside a module CommonJSと判定されたファイルにimport文がある package.jsonに "type": "module"、または拡張子を .mjs に。.cjs に書いている場合は require か import() に変える
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. requireでESMを読めない版でESMをrequireした Node.jsを20.19以降 / 22.12以降に上げる、または await import() に変える
Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. トップレベルawaitを含むESMをrequireした await import() に変える。場所は --experimental-print-required-tla で表示できる
ReferenceError: require is not defined in ES module scope ESMと判定されたファイルでrequireを使った import に書き換える、createRequire を使う、または拡張子を .cjs に
ReferenceError: __dirname is not defined in ES module scope ESMで __dirname を使った import.meta.dirname(20.11以降)、または dirname(fileURLToPath(import.meta.url))
ReferenceError: module is not defined in ES module scope ESMで module.exports を使った export default / export const に書き換える
Error [ERR_MODULE_NOT_FOUND]: Cannot find module ... Did you mean to import "./lib.js"? ESMのimportで拡張子を省略した 拡張子まで書く(./lib.js)
TypeError [ERR_IMPORT_ATTRIBUTE_MISSING](以前の版は ERR_IMPORT_ASSERTION_TYPE_MISSING) JSONのimportに with { type: 'json' } がない with { type: 'json' } を足す
Warning: [MODULE_TYPELESS_PACKAGE_JSON] ... Reparsing as ES module typeなしの .js にESMの構文があり、読み直しが起きている package.jsonに "type": "module" を足す

移行前のチェックリスト

確認すること 目安
node -v で版を確認したか 20.19以降 / 22.12以降ならrequireでESMを読める
package.jsonにtypeを書いたか "module" か "commonjs" を明示すると判定が安定する
相対importに拡張子を書いたか ./lib → ./lib.js
__dirname / __filename を置き換えたか import.meta.dirname / import.meta.filename
JSONのimportに with { type: 'json' } を付けたか assert は with に書き換える
CommonJSのまま残す設定ファイルは .cjs にしたか type moduleのフォルダでは .js がESMになる
requireするESMにトップレベルawaitがないか ある場合は import() で読む
起動時に MODULE_TYPELESS_PACKAGE_JSON の警告が出ていないか 出ていたらtypeを足す

よくある質問

Q. ESMとCommonJSはどちらを使えばよいですか? A. 新しく作るものはESMが扱いやすい選択です。JavaScript標準の形式で、ブラウザ向けのコードと書き方をそろえられます。既存のCommonJSのアプリは、そのままでも動き続けます。Node.js 20.19以降 / 22.12以降ならrequireでESMのライブラリも読めるため、必要になった部分から順に移せます。

Q. ERR_REQUIRE_ESMが出ました。最短の直し方は? A. Node.jsを20.19以降または22.12以降にすると、コードを変えずに解消することが多いです。今回の検証でも、同じコードが20.18.3と22.11.0ではエラー、20.20.2と22.22.2では動きました。版を上げられない場合は、require('x') を await import('x') に変えます。

Q. ERR_REQUIRE_ASYNC_MODULEはERR_REQUIRE_ESMと何が違いますか? A. requireでESMを読める版で、読み込むESM(またはその依存先)がトップレベルawaitを使っているときに出るエラーです。requireは同期で結果を返す仕組みなので、待ちが必要なモジュールは読めません。await import() に変えると動きます。

Q. .mjsと"type": "module"はどちらを使えばよいですか? A. フォルダ全体をESMにするなら "type": "module"、1ファイルだけ形式を変えたいなら拡張子(.mjs / .cjs)が向いています。拡張子はtypeより優先されるので、type moduleのフォルダの中でCommonJSの設定ファイルを置きたいときは .cjs にします。

まとめ

  • 形式は「拡張子 → 一番近いpackage.jsonのtype → 構文の検出」の順で決まる。.mjs はESM、.cjs はCommonJS、.js はtype次第
  • ERR_REQUIRE_ESM は20.18.3・22.11.0まで出て、20.19 / 22.12以降はrequireでESMを読める
  • ERR_REQUIRE_ASYNC_MODULE はトップレベルawaitを含むESMをrequireしたとき。await import() に変える
  • import() は検証した6つの版すべてで動く、混在時の確実な書き方
  • ESMでは __dirname は import.meta.dirname(20.11以降)、requireは createRequire、JSONは with { type: 'json' }
  • ESMの相対importは拡張子まで書く(./lib.js)
  • package.jsonにtypeを明示すると、判定の警告と読み直しがなくなる

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

(記載例)出典:株式会社RJC「Node.js ESMとCommonJSの違い|import混在の解決表」

株式会社RJCでは、Node.jsのモジュールの仕組みを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社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で一緒に開発しながら、 成長を楽しみませんか?