I'm trying to hash a string using crypto
in a Vue 3 application.
async function hash (token) { const data = new TextEncoder().encode(token) const byteHash = await crypto.subtle.digest("SHA-256", data) // ^ the below error is thrown here const arrayHash = Array.from(new Uint8Array(byteHash)) const hexHash = arrayHash.map(b => b.toString(16).padStart(2, '0')).join('').toLocaleUpperCase() return hexHash }
As far as I know, crypto
is now available in browsers, so there is no need to use browserify
instead.
However, I encountered the following error in the browser console:
Error: Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.subtle" in client code.
I understand this error as "Vite is configured to externalize the crypto
module during the build process." But I don't find such a setting in my vite.config.js
:
// Plugins: import vue from '@vitejs/plugin-vue' import vuetify from 'vite-plugin-vuetify' // Utilities: import { defineConfig } from 'vite' import { fileURLToPath, URL } from 'node:url' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin vuetify({ autoImport: true }) ], define: { 'process.env': {} }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) }, extensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx', '.vue'] }, server: { port: 3000 }, test: { setupFiles: ['../vuetify.config.js'], deps: { inline: ['vuetify'] }, globals: true } })
Are there any "built-in" Vite default settings that could cause this issue? Is this issue configured elsewhere? How can I solve this problem and use the crypto
module in my application?
The problem is that both NodeJS and the browserhave a module called
crypto
(which implements thewebcryptostandard), they are compatible, but need to be Accessed differently because in the browser it is provided by awindow
context that does not exist in NodeJS.If you work directly in the browser, you won't see the difference because
window
is the default context.But Vite is working in the context of NodeJS, it (correctly) believes that this module is not available as
crypto
in the browser, and therefore throws an error. It doesn't know/care that this module also exists in the browser, but aswindow.crypto
.Maybe it can be configured in
vite.config.js
, but I'm not very familiar with it.I came up with the following solution, which works in both environments:
Now this function works in both environments.