Repository: iTowns/itowns (JavaScript)

Issue:
[Proposal - Requirements] Formalize web browsers requirements for iTowns
## Context

There is currently no documented web browsers requirements for iTowns in the whole repository.

The closest to a documentation is our configuration file of the `babel` compiler which states that we are *theoretically* targeting the oldest browsers possible to be ES5 compatible. That means that we are supporting browsers a decade old (e.g. IE11)!

This causes a number of issues:
- we have no guarantee that iTowns indeed works on those old platforms
- the distributed code is unreadable due to code transformations by `babel`
- the distributed code size is large due to polyfills for unsupported constructs on those platforms (even for constructs well-supported for years by mainstream browsers).

Those issues will be exacerbated if we do not take some actions.

## Discussion

@iTowns/product-owners @iTowns/core-devs I propose that we discuss in this issue the minimum targets that we should support with iTowns.

Note that `three` will drop support of `webgl1` at the end of the month, which means that all our targets should at least support `webgl2`, Safari being the last mainstream browser to add support for `webgl2` circa 2021.

A proposed solution is too only support the `defaults` target given by [browserlist](https://github.com/browserslist/browserslist), that is the last two versions of all mainstream browsers (> 0.5% usage) + Firefox ESR at the date of release.

## Actions

- Documents the requirements (`README.md`, website, ...)
- Implements the proposal (see #2252)


Discussion: Hi, thanks for the proposal.

The defaults target sounds good to me.


> A proposed solution is too only support the defaults target given by [browserlist](https://github.com/browserslist/browserslist), that is the last two versions of all mainstream browsers (> 0.5% usage) + Firefox ESR at the date of release.

Agreed with that target too
That's a good reflection, it'll close this PR #1231 




Got some inputs from IGN's "Géoportail", they officially support versions of Firefox, Chrome, Edge and Safari no older than a year.

Waiting from inputs from IGN's "Géoplateforme" but I think we can proceed with this proposal and implement it! =)

Given the `webgl2` constraint and agreed `defaults` target, our target will be:
https://browsersl.ist/#q=defaults+and+fully+supports+webgl2
Proposal validated on IGN's side.

It seems that everyone agree with this proposal, I think we could move forward!



Fix (patch):
diff --git a/.babelrc b/.babelrc
index 728dc8aae5..ded830aa4d 100644
--- a/.babelrc
+++ b/.babelrc
@@ -4,7 +4,7 @@
             "targets": {
                 "browsers": "defaults and supports webgl2"
             },
-            "modules": "auto"
+            "modules": false
         }]
     ],
     "plugins": [
@@ -17,6 +17,7 @@
                 ".css"
             ]
         }],
+        ["module-extension-resolver"],
         ["@babel/plugin-transform-runtime", {
             "regenerator": false
         }],
diff --git a/.eslintrc.js b/.eslintrc.cjs
similarity index 98%
rename from .eslintrc.js
rename to .eslintrc.cjs
index 29a549723d..c2544517f6 100644
--- a/.eslintrc.js
+++ b/.eslintrc.cjs
@@ -14,7 +14,7 @@ module.exports = {
     settings: {
         'import/resolver': {
             webpack: {
-                config: 'webpack.config.js',
+                config: './webpack.config.cjs',
             },
         },
     },
diff --git a/Gruntfile.js b/Gruntfile.cjs
similarity index 100%
rename from Gruntfile.js
rename to Gruntfile.cjs
diff --git a/config/conventionalChangelog/config.js b/config/conventionalChangelog/config.cjs
similarity index 100%
rename from config/conventionalChangelog/config.js
rename to config/conventionalChangelog/config.cjs
diff --git a/docs/.eslintrc.js b/docs/.eslintrc.cjs
similarity index 90%
rename from docs/.eslintrc.js
rename to docs/.eslintrc.cjs
index 5de11505c7..d6e1f067a0 100644
--- a/docs/.eslintrc.js
+++ b/docs/.eslintrc.cjs
@@ -2,7 +2,7 @@ module.exports = {
     extends: [
         'eslint-config-airbnb-base',
         'eslint-config-airbnb-base/rules/strict',
-        '../.eslintrc.js',
+        '../.eslintrc.cjs',
     ],
     env: {
         node: true,
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 0000000000..fc697a9e02
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,5 @@
+{
+    "private": true,
+    "description": "JSDoc loads publish.js files with require(), so we need to configure everything under this path as a CommonJS module.",
+    "type": "commonjs"
+}
diff --git a/examples/.eslintrc.js b/examples/.eslintrc.cjs
similarity index 97%
rename from examples/.eslintrc.js
rename to examples/.eslintrc.cjs
index 33a388a22a..601cce023d 100644
--- a/examples/.eslintrc.js
+++ b/examples/.eslintrc.cjs
@@ -2,7 +2,7 @@ module.exports = {
     extends: [
         'eslint-config-airbnb-base',
         'eslint-config-airbnb-base/rules/strict',
-        '../.eslintrc.js',
+        '../.eslintrc.cjs',
     ],
     parserOptions: {
         ecmaVersion: 13,
diff --git a/package-lock.json b/package-lock.json
index 52bbc7a710..60970aa34d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,7 +31,9 @@
         "babel-plugin-inline-import": "^3.0.0",
         "babel-plugin-minify-dead-code-elimination": "^0.5.2",
         "babel-plugin-minify-replace": "^0.5.0",
+        "babel-plugin-module-extension-resolver": "^1.0.0",
         "babel-plugin-module-resolver": "^5.0.0",
+        "babel-register-esm": "^1.2.5",
         "c8": "^9.1.0",
         "chalk": "^5.3.0",
         "chart.js": "^4.4.1",
@@ -3449,6 +3451,15 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/babel-plugin-module-extension-resolver": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-module-extension-resolver/-/babel-plugin-module-extension-resolver-1.0.0.tgz",
+      "integrity": "sha512-TIwNuS8jfdmoyn+tKMM9T6fczI5y6hHbicbCTIF+RyPSNSnQMlZNnCs/pQceOEZ/0qFNbaj5p0LCLG2VS1EF7g==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/babel-plugin-module-resolver": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz",
@@ -3541,6 +3552,18 @@
         "@babel/core": "^7.0.0-0"
       }
     },
+    "node_modules/babel-register-esm": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/babel-register-esm/-/babel-register-esm-1.2.5.tgz",
+      "integrity": "sha512-WaVd3Rm42kndYnufn8u1SbUUwuCxL2GAQX/7QXUL3w/7PffB+HcXrzmAqk1x01TjhFh/npSZ9Z3MNBc6dDb6Uw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.17.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "*"
+      }
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
diff --git a/package.json b/package.json
index 126259e73f..1b509c0ce0 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,7 @@
   "name": "itowns",
   "version": "2.42.0",
   "description": "A JS/WebGL framework for 3D geospatial data visualization",
+  "type": "module",
   "main": "lib/Main.js",
   "exports": {
     ".": "./lib/Main.js",
@@ -17,7 +18,7 @@
     "test-functional": "mocha -t 100000 --require test/hooks_functional.js --recursive test/functional",
     "test-with-coverage": "c8 -n src -r html cross-env npm run test-unit",
     "test-with-coverage_lcov": "c8 -n src --reporter=lcov cross-env npm run test-unit",
-    "base-test-unit": "cross-env BABEL_DISABLE_CACHE=1 mocha --require @babel/register --file test/unit/bootstrap.js",
+    "base-test-unit": "cross-env BABEL_DISABLE_CACHE=1 mocha --file test/unit/bootstrap.js --loader=babel-register-esm",
     "build": "cross-env NODE_ENV=production webpack",
     "build-dev": "cross-env NODE_ENV=development webpack",
     "transpile": "cross-env BABEL_DISABLE_CACHE=1 babel src --out-dir lib",
@@ -27,7 +28,7 @@
     "prepublishOnly": "npm run build && npm run transpile",
     "prepare": "cross-env NO_UPDATE_NOTIFIER=true node ./config/prepare.mjs && node ./config/replace.config.mjs",
     "watch": "cross-env BABEL_DISABLE_CACHE=1 babel --watch src --out-dir lib",
-    "changelog": "conventional-changelog -n ./config/conventionalChangelog/config.js -i changelog.md -s",
+    "changelog": "conventional-changelog -n ./config/conventionalChangelog/config.cjs -i changelog.md -s",
     "bump": "if [ -z $npm_config_level ]; then grunt bump:minor;  else grunt bump:$npm_config_level; fi && npm run changelog && npm install && git add -A && git commit --amend --no-edit",
     "publish-next": "npm version prerelease --preid next && npm publish --access public --tag=next --provenance",
     "publish-latest": "npm publish --access public --tag=latest --provenance"
@@ -82,7 +83,9 @@
     "babel-plugin-inline-import": "^3.0.0",
     "babel-plugin-minify-dead-code-elimination": "^0.5.2",
     "babel-plugin-minify-replace": "^0.5.0",
+    "babel-plugin-module-extension-resolver": "^1.0.0",
     "babel-plugin-module-resolver": "^5.0.0",
+    "babel-register-esm": "^1.2.5",
     "c8": "^9.1.0",
     "chalk": "^5.3.0",
     "chart.js": "^4.4.1",
diff --git a/webpack.config.js b/webpack.config.cjs
similarity index 100%
rename from webpack.config.js
rename to webpack.config.cjs