Repository: pyodide/pyodide

Issue:
[Discussion] Drop support for Node versions that passed endoflife
## Proposal

Drop support for Node < 18 from the next Pyodide major release (0.25.0)

## Background

The endoflife of [Node.js 14 and 16 passed a few days ago](https://nodejs.dev/en/about/releases/). We just finished a major release, so I think this is a good time to talk about Node version support.

![image](https://github.com/pyodide/pyodide/assets/24893111/47e79d74-8362-493c-9ff5-49d3d5c7004d)

Here are the things that are currently associated with Node.js versions in Pyodide.

- The documentation mentions [how to run Pyodide in Node.js < 0.18](https://pyodide.org/en/stable/usage/index.html#node-js-versions-0-17)
- We have some compat codes for older Node versions
  - https://github.com/pyodide/pyodide/pull/4100#discussion_r1308449699
  -[compat.ts](https://github.com/pyodide/pyodide/blob/e2c2884e7a9afd90b23849220ee578bd2d523458/src/js/compat.ts#L40)
- JSPI requires Node >= 20
- The Docker image used for Pyodide CI uses Node 20

### Benefits from dropping Node < 18 support

- No more `node-fetch`.
- No more `--experimental-wasm-bigint` flags
- Better `MessageChannel` support (https://github.com/pyodide/pyodide/issues/4006)
- Some useful methods like [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)

### Drawbacks

- People who were using Node.js < 18 with Pyodide won't like it.

## Migration plan

- Mention minimal Node.js version support in docs
- Remove compat codes for old  Node.js versions
  - pytest-pyodide?

WDYT?




Discussion:
+1 thanks for checking. If it's now deprecated, then I agree it makes sense to drop it. And also I think the type of users who use node, are more able to change the version, as opposed to some browser end users who aren't.

We could set [MIN_NODE_VERSION](https://github.com/emscripten-core/emscripten/blob/0be5b609412d5b07f8157528df8e5088dae84858/src/settings.js#L1818) in Emscripten accordingly then.

Resolving patch:
diff --git a/pyodide-build/pyodide_build/create_xbuildenv.py b/pyodide-build/pyodide_build/create_xbuildenv.py
--- a/pyodide-build/pyodide_build/create_xbuildenv.py
+++ b/pyodide-build/pyodide_build/create_xbuildenv.py
@@ -113,16 +113,6 @@ def create(
     _copy_wasm_libs(pyodide_root, xbuildenv_root, skip_missing_files)
 
     (xbuildenv_root / "package.json").write_text("{}")
-    res = subprocess.run(
-        ["npm", "i", "node-fetch@2"],
-        cwd=xbuildenv_root,
-        capture_output=True,
-        encoding="utf8",
-    )
-    if res.returncode != 0:
-        logger.error("Failed to install node-fetch:")
-        exit_with_stdio(res)
-
     res = subprocess.run(
         ["pip", "freeze", "--path", get_build_flag("HOSTSITEPACKAGES")],
         capture_output=True,


Test patch:
diff --git a/src/tests/test_pyodide.py b/src/tests/test_pyodide.py
--- a/src/tests/test_pyodide.py
+++ b/src/tests/test_pyodide.py
@@ -1474,19 +1474,13 @@ def test_args_OO(selenium_standalone_noload):
 @pytest.mark.xfail_browsers(chrome="Node only", firefox="Node only", safari="Node only")
 def test_relative_index_url(selenium, tmp_path):
     tmp_dir = Path(tmp_path)
-    version_result = subprocess.run(
-        ["node", "-v"], capture_output=True, encoding="utf8"
-    )
-    extra_node_args = []
-    if version_result.stdout.startswith("v14"):
-        extra_node_args.append("--experimental-wasm-bigint")
+    subprocess.run(["node", "-v"], capture_output=True, encoding="utf8")
 
     shutil.copy(ROOT_PATH / "dist/pyodide.js", tmp_dir / "pyodide.js")
 
     result = subprocess.run(
         [
             "node",
-            *extra_node_args,
             "-e",
             rf"""
             const loadPyodide = require("{tmp_dir / "pyodide.js"}").loadPyodide;
@@ -1529,8 +1523,6 @@ def test_index_url_calculation_source_map(selenium):
     node_options = ["--enable-source-maps"]
 
     result = subprocess.run(["node", "-v"], capture_output=True, encoding="utf8")
-    if result.stdout.startswith("v14"):
-        node_options.append("--experimental-wasm-bigint")
 
     DIST_DIR = str(Path.cwd() / "dist")