JavaScript and TypeScript¶
Note
Don’t use CoffeeScript. Unless the repository is a fork, use Decaffeinate to convert CoffeeScript to ECMAScript.
License¶
Use the MIT license.
Version¶
ECMAScript¶
Frontend code is written for ECMAScript 6 (ES6) (see the status of feature support in modern browsers). We don’t support Internet Explorer 11.
Tip
To transform older code to ECMAScript 6, use lebab, but be aware of its bugs. There is a lebab plugin for Sublime Text. Use these preferences (Preferences > Package Settings > Lebab > Settings - User):
{
"transforms": [
"arrow",
"arrow-return",
"let",
"for-of",
"for-each",
"arg-rest",
"arg-spread",
"obj-method",
"obj-shorthand",
"no-strict",
"exponent",
"class",
"commonjs",
"template",
"default-param",
"includes"
]
}
To transform newer code to ECMAScript 6, use Babel with the defaults query from browserlist.
Node¶
Applications are written for the latest LTS version of Node. Packages are written for non-end-of-life versions (see the status of Node versions).
To upgrade Node, change the node-version key in GitHub Actions workflows and the node (or nikolaik/python-nodejs) image in Dockerfiles. Check the relevant changelog for breaking changes.
Preferences¶
Plain JavaScript is preferred to using jQuery, unless functionality depends on jQuery plugins. To replace jQuery in a project, refer to You Might Not Need jQuery. Similarly, use the Fetch API instead of the Axios package, etc.
- Package manager
pnpm, for its built-in supply-chain protections (dependency cooldown, trust policy, build scripts blocked by default) and its strict
node_moduleslayout. Do not use npm or yarn.- User interface
Vue is preferred to React. That said, do not use frameworks for simple interfaces.
- Asset management
- Sass
sass (dart-sass). Do not use node-sass, which is deprecated.
- Formatter
Biome. See HTML code style.
Requirements¶
Use pnpm, not npm or yarn. Set the Node version in the engines property and the pnpm version in the packageManager property of package.json.
List outdated dependencies:
pnpm outdated
Upgrade outdated dependencies:
pnpm update
Upgrade Vue dependencies:
vue upgrade --next
Supply chain¶
To protect against supply chain attacks, set in pnpm-workspace.yaml:
minimumReleaseAge: 10080
trustPolicy: no-downgrade
no-downgrade has false positives if packages drop provenance attestation. Exclude the versions that pnpm install reports:
trustPolicyExclude:
- chokidar@4.0.3
- semver@6.3.1
By default, pnpm enables minimumReleaseAge (1 day) and blockExoticSubdeps (prevents transitive dependencies from using git or tarballs).
Vulnerabilities¶
Dependabot alerts
If the Dependabot alert is for a build dependency (like node-sass) or a test dependency (like mocha), you can dismiss it with “Risk is tolerable for this project”. The npm ecosystem has false positives.
To check for vulnerable dependencies:
pnpm audit --prod
Note
pnpm audit (without --prod) has false positives (Vue example).
To upgrade vulnerable dependencies:
pnpm audit --fix update
This updates the lockfile to non-vulnerable versions, where the dependency ranges allow it. Check each package’s changelog before committing.
Where the dependency ranges don’t allow it, pnpm audit --fix can add overrides to package.json to force non-vulnerable versions, instead.
Code style¶
package.json¶
Do not set the scripts property. Instead, document the full commands in the readme, to reduce indirection and obfuscation.
Vue¶
When navigating between “pages”, respect native browser behaviors (open in new tab, etc.) by using an
<a>link or<router-link>.
Continuous integration¶
Important
In GitHub workflows, install project dependencies safely with:
- run: pnpm install --frozen-lockfile --ignore-scripts
Create a .github/workflows/js.yml file.
Tip
In most cases, you can reuse the js workflow. For example:
name: Lint JavaScript
on: [push, pull_request]
jobs:
lint:
uses: open-contracting/.github/.github/workflows/js.yml@main
permissions:
contents: read
If you don’t use this workflow, and the project uses npm, include this step:
- run: npx lockfile-lint --path package-lock.json --type npm --allowed-hosts npm --validate-https