Vue3/Vite: 将模块外部化
P粉107991030
P粉107991030 2023-08-26 13:45:43
[Vue.js讨论组]

我正在尝试在Vue 3应用程序中使用crypto对字符串进行哈希处理。

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
}

据我了解,现在浏览器中可以使用crypto,所以不需要使用browserify替代。

然而,我在浏览器控制台中遇到了以下错误:

Error: Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.subtle" in client code.

我理解这个错误为“Vite在构建过程中配置了将crypto模块外部化”。但是我在我的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
  }
})

是否有任何“内置”的Vite默认设置会导致这个问题?这个问题是否在其他地方进行了配置?我该如何解决这个问题并在我的应用程序中使用crypto模块?

P粉107991030
P粉107991030

全部回复(1)
P粉019353247

问题在于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;
}

现在这个函数在两个环境中都可以工作。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号