Adapt a project.
Treat migration as a boundary audit. Collapse the module graph, expose runtime assumptions, then replace what Porffor does not provide.
Check the shape before the syntax
A good candidate is compute-heavy, has a clear input/output boundary, and does not depend deeply on Node.js internals. A poor candidate reaches constantly into the filesystem, processes, native addons, dynamic loading, or outbound networking.
Plain Porffor builds compile one source file. Runtime import is not a module loader. Bundle a project before handing it to the compiler.
Collapse the graph
esbuild is a practical starting point. Target a modern syntax level so it does not introduce compatibility helpers.
$ npx esbuild src/index.ts \
--bundle \
--format=esm \
--platform=neutral \
--target=esnext \
--outfile=bundle.js
$ porf bundle.jsimport type disappears during parsing and is safe. Server projects are different: their build path performs bundling automatically.
Audit the runtime contract
| Dependency pattern | Adaptation |
|---|---|
node:fs, node:path, other Node modules | Move I/O outside the compiled core or replace the dependency. |
process.env | Inject fixed values at bundle time with esbuild --define. |
process.argv, process.exit | Not supplied by today's runtime; redesign the boundary. |
client fetch() | Perform outbound I/O elsewhere or defer the migration. |
Proxy or runtime-generated code | No reliable shim. Replace the design or keep this code on another runtime. |
| timers in a command-line program | Use a synchronous flow; timers belong to server mode with the event loop enabled. |
Compare, do not eyeball
Feed both runtimes identical input, capture output, and compare it mechanically. Then add the case to your test suite.
$ node bundle.js > expected.txt
$ porf bundle.js > actual.txt
$ diff -u expected.txt actual.txtMinimize the first failure
Reduce it until one language feature or API explains the divergence.
Classify it
Decide whether it is a documented gap, a dependency assumption, or a compiler bug.
Lock in the result
Keep the reduced case as a regression test before moving to the next failure.