英文:
Vue3/Vite: module has been externalized
问题
你的代码中出现了关于使用 crypto
模块的问题。在浏览器环境中,crypto
模块通常会被 externalize,导致无法直接访问 crypto.subtle
。这可能是由于 Vite 默认设置中进行了配置,但在你的 vite.config.js
中没有看到明确的设置。
要解决这个问题,你可以尝试在你的项目中添加以下配置到 vite.config.js
中:
// vite.config.js
export default defineConfig({
// ...其他配置
build: {
rollupOptions: {
// 防止 crypto 模块 externalize
external: ['crypto'],
},
},
})
这个配置会告诉 Vite 在构建时不要 externalize crypto
模块,从而使你可以在客户端代码中访问 crypto.subtle
。
请确保添加这个配置后重新构建你的应用程序以查看是否问题已解决。
英文:
I'm trying to use crypto
to hash strings in a Vue 3 app.
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
}
From my understanding, crypto
is available in the browser nowadays, so it needs no browserify
replacement.
Nevertheless, I'm getting the following error in my browser console:
Error: Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.subtle" in client code.
I interpret this as "Vite is configured to externalize the crypto
module in the build process". But I can see no such setting in my vite.config.js
:
// Plugins:
import vue from '@vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'
// Utilies:
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 "baked in" Vite default settings, that could cause this? Is this configured somewere else? How can I fix this issue and use the crypto
module in my app?
答案1
得分: 1
问题在于NodeJS和浏览器都有一个名为crypto
的模块(实现了webcrypto标准),它们是兼容的,但需要以不同的方式访问,因为在浏览器中,它是由不存在于NodeJS的window
上下文提供的。
如果您直接在浏览器中工作,您就看不到这个区别,因为window
是默认上下文。
但是Vite在NodeJS上下文中工作,它(正确地)认为在浏览器中没有作为crypto
的模块,因此会引发错误。它不知道/不关心这个模块在浏览器中也以window.crypto
存在。
也许可以在vite.config.js
中进行某种配置,但我对它不太熟悉。
相反,我提出了以下解决方案,它在两种环境中都有效:
function getCrypto() {
try {
return window.crypto;
} catch {
return crypto;
}
}
async function hash(token) {
const compatibleCrypto = getCrypto();
const data = new TextEncoder().encode(token);
const byteHash = await compatibleCrypto.subtle.digest('SHA-256', data);
const arrayHash = Array.from(new Uint8Array(byteHash));
const hexHash = arrayHash
.map(b => b.toString(16).padStart(2, '0'))
.join('')
.toLocaleUpperCase();
return hexHash;
}
这个函数现在在两种环境中都可以工作。
英文:
The issue lies in the fact that NodeJS and the Browser both have a module called crypto
(that implements the webcrypto standard) that are compatible, but need to be accessed differently, because in the browser it is provided by the window
context that does not exist in NodeJS.
You don't see the difference if you are working directly in the browser, as window
is the default context.
But Vite is working in the NodeJS context, it (correctly) decides that this module is not available as crypto
in the browser and thus throws the error. It does not know/care that this module exists in the browser as well but as window.crypto
.
Maybe this can be configured in vite.config.js
somehow, but I am not very firm with it.
I came up with the following solution instead, which works in both environments:
function getCrypto() {
try {
return window.crypto;
} catch {
return crypto;
}
}
async function hash(token) {
const compatibleCrypto = getCrypto();
const data = new TextEncoder().encode(token);
const byteHash = await compatibleCrypto.subtle.digest('SHA-256', data);
const arrayHash = Array.from(new Uint8Array(byteHash));
const hexHash = arrayHash
.map(b => b.toString(16).padStart(2, '0'))
.join('')
.toLocaleUpperCase();
return hexHash;
}
This function works in both environments now.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论