badges / badges/shields

Migrate frontend to ESM

Open
#6,717 1 comment 5 reactions 0 assignees View on GitHub
core frontend
Dominant language
JavaScript
Stars
27.2k
Forks
5.6k
Avg merge
1d 8h
Merged PRs (30d)
46

Description

This is related to #6651, in particular https://github.com/badges/shields/pull/6651#discussion_r666389443.

### Problem

Gatsby does not support ESM. See https://github.com/gatsbyjs/gatsby/issues/23705 and linked discussions for more information.

In particular, when running `npm start` midway through migrating the whole code to ESM, I was getting errors similar to the following:
> [frontend] TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for C:...\workspace\shields\.cache\tmp-5248-0orlJ0tI72FY

`npm run build` was also producing different kinds of errors.

### Current workaround

The solution was to break the frontend down into a separate module with its own `frontend/package.json`. Unlike Shields' top-level `package.json`, `frontend/package.json` does not contain the mention `"type": "module"`, in other words it is still a CommonJS module.

In addition to mandating the extra `frontend/package.json`, the solution has the following caveats:
* the Babel configuration must be specified in `frontend/package.json`.
* the `gatsby` dependency must be specified in both `package.json` and `frontend/package.json`, Gatsby will otherwise complain that the frontend package is not a Gatsby project.
* the `start` and `build` scripts from `package.json `have an extra `cd frontend` step so that Gatsby is run from `frontend/package.json`.
* in line with the directory where Gatsby is now run, `gatsby-browser.js`, `gatsby-config.js` and `gatsby-node.js` have been moved to the `frontend` directory.
* the `supported-features.json` and `service-definitions.yml` files are now produced in the `frontend` directory. This is only a minor detail to make relative paths simpler.
* the result of the `build` script, i.e. the `public` folder, is moved up one level back into the project's root. Gatsby produces `public` in the `frontend` directory where it's run and that can't be changed (https://github.com/gatsbyjs/gatsby/discussions/1878), and Heroku expects `public` to be in the project's root and that can't be changed (
https://github.com/heroku/heroku-buildpack-nodejs/issues/385). Additionally, our Cypress end-to-end setup will expect `public` to be in the root as well.
* the `require-hacker` dependency and the `mocha-ignore-pngs.js` file were removed, as not compatible with ESM. These probably aren't needed anymore, as the ESM loader ignores PNGs anyway if my understanding is correct.
* the `import` statements in `make-badge-url.js` must be carefully tested, as they are used both by the ESM loader and Typescript loader, which have slightly different behaviours. For example, `import { URL } from 'url'` won't work there.

### Future work

Once Gatsby becomes compatible with ESM, we would simply need to revert all aforementioned workarounds (apart from the `require-hacker` one), and potentially convert `gatsby-browser.js`, `gatsby-config.js` and `gatsby-node.js` to ESM formats as well. Additionally, it is my understanding that we will need to add `js` file extensions to the existing relative imports in the frontend code.

Contributor guide

Open the contributing guide

Research direction

Start by checking whether Gatsby supports ESM, then inspect frontend/package.json, the package scripts, gatsby-browser.js, gatsby-config.js, gatsby-node.js, and make-badge-url.js. Once supported, revert the listed frontend workarounds, consider converting the Gatsby files and adding relative .js extensions, and verify npm start, npm run build, and the root public directory expected by Heroku and Cypress.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
build-system, frontend
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.