изоморфный код для нативного node.js и криптографии браузера
Существует isomorphic-webcrypto, который делает вид, что делает это, но не делает этого: он создает отдельную сборку для каждой цели.
Для этого есть способ noble-crypto , но он основан на условиях if-else и не работает, если мне нужен изоморфный код mjs.
Наконец, существует метод eval require way для сквозного сборщика, но node не может использовать его в mjs.
Вкратце :
const crypto = require("crypto"); // work only in node.js but not in mjs file.
const crypto = eval(`require("crypto")`); // pass-thru bundler, then work only in node.js but not in mjs file.
window.crypto; // work only in browser
import * as crypto from "crypto"; // could work from both but must be at top level of a module, so it can't be a conditional import.
Я хотел бы использовать собственное шифрование в node.js и в браузере изоморфным способом, чтобы иметь возможность прозрачно использовать собственный импорт mjs в node и браузере.
Как я могу это сделать?
1 ответ
Хорошо. Готовы к чему-то уродливому? :-) Вот мой последний хакджоб… IsomorphicCyrpto.js:
export default
globalThis.crypto ||
(await import('node:crypto')).default.webcrypto
;
Это работает в Node.js v16 в модульном режиме ("type": "module"
в package.json или эквивалентных аргументах CLI) и, вероятно, будет работать и с вашим упаковщиком… но кто знает. ;-) Любой, кто использует этот фрагмент кода, должен тщательно протестировать его на любых платформах, на которых он хочет его использовать.
В двух словах:
- Мы используем
globalThis
, который представляетglobal
под Node.js,window
для большинства контекстов браузера и, возможно, даже может быть рабочим контекстом. - Сначала мы проверяем, есть ли вещь. Если это так, мы, вероятно, в браузере и можем просто использовать его напрямую.
- Если
crypto
это не проблема, мы, вероятно, на Node.js, и нам нужно импортировать модуль. - Поскольку это делается динамически, нам нужна
динамическая , а не истинная import
. -
import()
является асинхронным и возвращает обещание. Но эй, это все хорошо, потому чтона высшем уровне await
это вещь в Node.js сейчас!
Чтобы затем использовать модуль:
import crypto from './lib/IsomorphicCrypto.js';
console.log( crypto.randomUUID() );
Ужасно, но пока работает. Будем надеяться, что кто-то предложит лучшее решение, или контексты Node.js и браузера сойдутся в именовании в будущем.