SvelteKit 无法解决依赖关系,即使它是外部的

Posted

技术标签:

【中文标题】SvelteKit 无法解决依赖关系,即使它是外部的【英文标题】:SvelteKit could not resolve dependency even though it's external 【发布时间】:2022-01-02 21:40:59 【问题描述】:

我正在制作一个用户身份验证页面,在这方面,我正在使用 bcrypt 进行散列。一切都很好,直到我在代码中实际使用了 bcrypt 模块。在开发模式下运行它完全正常,在预览构建时它运行完全正常,但是在构建过程中发生错误,部署时会导致它停止构建并出错。

这是错误:

> Using @sveltejs/adapter-vercel
 > node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:43:28: error: Could not resolve "mock-aws-s3" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
    43 │     const AWSMock = require('mock-aws-s3');
       ╵                             ~~~~~~~~~~~~~

 > node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:76:22: error: Could not resolve "aws-sdk" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
    76 │   const AWS = require('aws-sdk');
       ╵                       ~~~~~~~~~

 > node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:112:23: error: Could not resolve "nock" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
    112 │   const nock = require('nock');
        ╵                        ~~~~~~

> Build failed with 3 errors:
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:43:28: error: Could not resolve "mock-aws-s3" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:76:22: error: Could not resolve "aws-sdk" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:112:23: error: Could not resolve "nock" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
Error: Build failed with 3 errors:
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:43:28: error: Could not resolve "mock-aws-s3" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:76:22: error: Could not resolve "aws-sdk" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:112:23: error: Could not resolve "nock" (mark it as external to exclude it from the bundle, or surround it with try/catch to handle the failure at run-time)
    at failureErrorWithLog (/home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:1493:15)
    at /home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:1151:28
    at runOnEndCallbacks (/home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:1069:65)
    at buildResponseToResult (/home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:1149:7)
    at /home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:1258:14
    at /home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:629:9
    at handleIncomingPacket (/home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:726:9)
    at Socket.readFromStdout (/home/joshgil/Codes/TouchOfClassEvents/node_modules/esbuild/lib/main.js:596:7)
    at Socket.emit (node:events:390:28)
    at Socket.emit (node:domain:475:12)

我按照错误所说的,并将这些包标记为外部,但它仍然不起作用,这是我的svelte.config.js

// svelte.config.js
import sveltePreprocess from 'svelte-preprocess';
import makeAttractionsImporter from 'attractions/importer.js';
import vercel from '@sveltejs/adapter-vercel';
import path,  dirname, resolve  from 'path';
import  fileURLToPath  from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

/** @type import('@sveltejs/kit').Config */
const config = 
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: sveltePreprocess(
        postcss: true,
        scss: 
            importer: makeAttractionsImporter(
                themeFile: path.join(__dirname, 'static/css/theme.scss')
            ),
            includePaths: [path.join(__dirname, './static/css')]
        
    ),

    kit: 
        // hydrate the <div id="svelte"> element in src/app.html
        target: '#svelte',
        adapter: vercel(),
        vite: 
            optimizeDeps: 
                exclude: ['bcrypt']
            ,
            s-s-r: 
                external: ['mock-aws-s3', 'aws-sdk', 'nock', 'node-pre-gyp']
            ,
            resolve: 
                alias: 
                    $lib: resolve('src/lib'),
                    $components: resolve('src/components'),
                    $utils: resolve('src/utils')
                
            
        
    
;

export default config;

我开始研究它,似乎问题是由node-pre-gyp 引起的,所以我也在配置中将其标记为外部,但它仍然产生相同的错误。

问题似乎是当node-pre-gyp 试图解析 bcrypt 的 C++ 二进制文件时,它只会在构建时出错,当它被强制运行时,它运行得非常好。

【问题讨论】:

【参考方案1】:

我在使用 bcrypt 和 argon2 时遇到了同样的问题,因为它们都依赖于 node-pre-gyp 并进行了一些挖掘,并在纯 javascript 中找到了 bcrypt 的实现。

请注意,它很可能比 C 实现慢,但它确实可以在生产 Sveltekit 环境中工作,并在 Vercel 上进行了测试。

这是 bcryptjs 包:https://www.npmjs.com/package/bcryptjs

【讨论】:

我实际上已经看到了这个包并考虑使用它,但是较慢的警告让我决定走我走的路。当然,我的解决方案有一个警告,就是要使捆绑包的大小变大,但我希望(我自己没有检查过)捆绑包的大小不会因为这 3 个包而变得臃肿【参考方案2】:

我发现的一个解决方案是将这些依赖项 "nock", "mock-aws-s3", "aws-sdk" 包含在 package.json 中,这将解决问题但不是预期的方式,因为这意味着捆绑包会变得更大,因为有 3 个额外的客户端不需要的依赖项。

希望有更好的解决方案!

这个解决方案的警告是,捆绑包的大小当然会更大,我希望它不会太大。

【讨论】:

【参考方案3】:

我遇到了同样的问题,但使用了 @googlemaps/js-api-loader 包。我在 SvelteKit repo https://github.com/sveltejs/kit/issues/928

中找到了关于这个问题的讨论

我通过updating svelte.config.js 修复了它,如下所示:

vite: 
  s-s-r: 
    noExternal: ['@googlemaps/js-api-loader']
  

【讨论】:

以上是关于SvelteKit 无法解决依赖关系,即使它是外部的的主要内容,如果未能解决你的问题,请参考以下文章

无法从 sveltekit 循环中的 JSON 对象获取值

多对多 - “无法确定一对一关系的子/依赖方”

Ivy 无法解决依赖关系,无法找到原因

Flutter,无法解决依赖关系

无法解决依赖关系。?

Maven 无法解决依赖关系