首页  >  问答  >  正文

Vue3/Vite: 将模块外部化

<p>我正在尝试在Vue 3应用程序中使用<code>crypto</code>对字符串进行哈希处理。</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>据我了解,现在浏览器中可以使用<code>crypto</code>,所以不需要使用<code>browserify</code>替代。</p> <p>然而,我在浏览器控制台中遇到了以下错误:</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>我理解这个错误为“Vite在构建过程中配置了将<code>crypto</code>模块外部化”。但是我在我的<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' // 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 } }) </pre> <p>是否有任何“内置”的Vite默认设置会导致这个问题?这个问题是否在其他地方进行了配置?我该如何解决这个问题并在我的应用程序中使用<code>crypto</code>模块?</p>
P粉107991030P粉107991030390 天前644

全部回复(1)我来回复

  • P粉019353247

    P粉0193532472023-08-27 11:31:26

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

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

    回复
    0
  • 取消回复