JavaScript

可选优化

Maybe you don’t need Rust and WASM to speed up your JS
过早优化是万恶之源

  1. 调用函数时传递和声明一样多的参数,不使用可选参数。
  2. 单态化函数,简单来说让每个参数的形状(对象的结构(包括属性值)、或者函数本身)都永远不变(像是immutable?)。
  3. 克制地使用缓存 —— 除非查找它比计算它容易。
  4. 想办法减少 GC 的压力,例如申请一个大的 TypedArray 存储定长数据。
  5. 如果只是在 ASCII 范围内工作,用 Uint8Array 代替 String。

还有一些常识:

  1. 用 class 维护对象的形状,不去改变 prototype。
  2. 从维护形状考虑,不要用 Record 当 Map/Set 使 —— 直接用 Map 即可。

Tools

pnpm

pnpm 在处理 bin 的方式上跟 yarn 不同,在unix系统下,yarn 会直接在 .bin 文件夹下 .js 文件的软链接(package.json 中bin项中列出的文件):

  1. "bin": {
  2. "esno": "esno.js",
  3. "esmo": "esmo.mjs"
  4. },

作为可执行脚本,而 pnpm 会改成嵌套后的 sh:

  1. #!/bin/sh
  2. basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
  3. case `uname` in
  4. *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
  5. esac
  6. if [ -z "$NODE_PATH" ]; then
  7. export NODE_PATH="..."
  8. else
  9. export NODE_PATH="$NODE_PATH: ..."
  10. fi
  11. if [ -x "$basedir/node" ]; then
  12. exec "$basedir/node" "$basedir/../esno/esmo.mjs" "$@"
  13. else
  14. exec node "$basedir/../esno/esmo.mjs" "$@"
  15. fi
  1. #!/usr/bin/env node
  2. import spawn from 'cross-spawn'
  3. import { resolve } from 'import-meta-resolve'
  4. const spawnSync = spawn.sync
  5. const argv = process.argv.slice(2)
  6. resolve('esbuild-node-loader', import.meta.url).then((path) => {
  7. process.exit(spawnSync('node', ['--loader', path, ...argv], { stdio: 'inherit' }).status)
  8. })

按照官方说法

  1. Binstubs (files in node_modules/.bin) are always shell files, not symlinks to JS files. The shell files are created to help pluggable CLI apps in finding their plugins in the unusual node_modules structure. This is very rarely an issue and if you expect the file to be a JS file, reference the original file directly instead, as described in #736.

https://pnpm.io/limitations
https://github.com/pnpm/pnpm/issues/1282
image.png
windows中 yarn 也都是 shell,所以pnpm这种反而是正确的做法。
pnpm 这样的做法带来的问题在于,原先 vscode 可以直接 node 执行 .bin 中文件,pnpm安装后,只能去依赖地址里找bin的原始文件执行,或使用 npx / yarn/pnpm 执行器 等来执行 bin 文件。