Vue3/Vite: Externalizing modules
P粉107991030
2023-08-26 13:45:43
<p>I'm trying to hash a string using <code>crypto</code> in a Vue 3 application. </p>
<pre class="brush:js;toolbar:false;">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
}
</pre>
<p>As far as I know, <code>crypto</code> is now available in browsers, so there is no need to use <code>browserify</code> instead. </p>
<p>However, I encountered the following error in the browser console: </p>
<pre class="brush:js;toolbar:false;">Error: Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.subtle" in client code.
</pre>
<p>I understand this error as "Vite is configured to externalize the <code>crypto</code> module during the build process." But I don't find such a setting in my <code>vite.config.js</code>:</p>
<pre class="brush:js;toolbar:false;">// 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
}
})
</pre>
<p>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 <code>crypto</code> module in my application? </p>
The problem is that both NodeJS and the browser have a module called
crypto
(which implements the webcrypto standard), 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.