Originally published on php-to-js.learnio.dev — part of the PHP to JavaScript course. View this lesson on the original site.
One file, one module — export what you need, import what you use
PHP loads files with require and brings classes into scope with use. JavaScript ES modules use export and import at the top of each file. One file is one module.
PHP habit: require and use
<?php
require_once __DIR__ . '/helpers.php';
require_once __DIR__ . '/Formatter.php';
use App\Utils\Formatter;
$formatter = new Formatter();
echo $formatter->formatCurrency(19.99);
JavaScript equivalent
// formatter.js — exports
export function formatCurrency(amount, currency = 'GBP') {
return new Intl.NumberFormat('en-GB', { style: 'currency', currency }).format(amount);
}
export const VERSION = '1.0.0';
// main.js — imports
import { formatCurrency, VERSION } from './formatter.js';
console.log(formatCurrency(19.99));
console.log(VERSION);
| PHP | JavaScript (ESM) | Notes |
|---|---|---|
require_once 'file.php' |
import ... from './file.js' |
Static — resolved before run |
use App\Formatter |
import { Formatter } from '...' |
Named import |
| Public class in file | export class Formatter {} |
Explicit export |
| No direct equivalent | export default fn |
One default export per file |
Named vs default export
// Named — many per file, names must match on import
export function add(a, b) { return a + b; }
// Default — one per file, importer picks the local name
export default function log(message) {
console.log(message);
}
import { add } from './math.js';
import logger from './logger.js';
<?php
// Closest PHP pattern: one main class per file + namespace
namespace App\Math;
function add(int $a, int $b): int { return $a + $b; }
Rename and namespace imports
import { formatCurrency as formatMoney } from './formatter.js';
import * as Formatter from './formatter.js';
Formatter.formatCurrency(10);
Same idea as use Foo as Bar in PHP.
Browser vs Node
In HTML, module scripts need type="module":
<script type="module" src="/js/main.js"></script>
In Node, set "type": "module" in package.json or use .mjs files. New projects should use ESM; older code may use require (CommonJS) — covered in the tooling chapter.
Try it
The sandbox runs a single file, so this simulates a module’s public API in one object:
const formatter = {
formatCurrency(amount, currency = 'GBP') {
return new Intl.NumberFormat('en-GB', { style: 'currency', currency }).format(amount);
},
VERSION: '1.0.0',
};
console.log(formatter.formatCurrency(49.99));
console.log('Module version', formatter.VERSION);
In a real project you would split this into formatter.js (export) and main.js (import). The split is the point — not one giant global file.
From PHP to JavaScript — JavaScript Syntax Foundations for PHP Devs