【问题标题】:SyntaxError: Cannot use import statement outside a module (from dependency)SyntaxError:无法在模块外部使用导入语句(来自依赖项)
【发布时间】:2021-09-03 11:13:53
【问题描述】:

当依赖项未声明为模块时,如何从依赖项中解决“无法在模块外使用 import 语句”?


我想使用 Svelte/kit 中的 validator 来验证电子邮件。但是,在导入 ESM 版本时,我收到“无法在模块外使用 import 语句”错误。我使用的是 pnpm 而不是 npm 或 yarn。

import isEmail from 'validator/es/lib/isEmail'
/node_modules/.pnpm/validator@13.6.0/node_modules/validator/es/lib/isEmail.js:1
import assertString from './util/assertString';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:355:18)
    at wrapSafe (node:internal/modules/cjs/loader:1039:15)
    at Module._compile (node:internal/modules/cjs/loader:1073:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1138:10)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at nodeRequire 

验证器似乎正在尝试使用 import 语句,但它的 package.json 没有指定 "type": "module"。我的猜测是这是错误的根本原因。

调试步骤

  • package.json 有"type": "module"
  • 升级到最新版本的节点
  • 尝试使用非 esm 版本的验证器 'validator/lib/isEmail',但这会导致与此线程无关的其他错误。

相关

元数据

  • 节点:v16.2.0
  • Sveltekit:v1.0.0-next.115
  • 验证器:13.6.0

【问题讨论】:

  • 您在 package.json 中将type 属性设置为 "type": "module" 后是否重新启动了编辑器?如果您不重新加载项目,intellisense 不会启动它,所以事情可以正常工作,但 intellisense 不会,所以看起来好像您做错了什么,而实际上您并没有。
  • 刚试过,好像没用。这似乎也不是智能感知问题。尝试启动 Sveltekit 时发生错误。
  • 你看过类似的post吗?

标签: javascript node.js node-modules package.json npm-package


【解决方案1】:

尝试像这样导入

import { isEmail } from "validator"

【讨论】:

  • 这似乎没有帮助,因为我的代码已经是一个 ESM 模块。
  • 非esm版本会出现什么错误?
【解决方案2】:

如果没有更多信息,如果您的问题仅在于您所依赖的代码有问题,请考虑在短期内使用 patch-package 之类的东西进行必要的调整,从长远来看,请在 @987654322 上打开 PR @!

对于补丁包,只需将"type": "module" 添加到node_modules/validator 的package.json,然后运行npx patch-package validator。然后,您可以对输出的 diff 文件进行版本控制,并且假设 patch-package 是(开发)依赖项,则使用 npm 挂钩自动进行更改。

这里的库的行为或缺陷可能来自开发人员,更要记住 webpack 之类的东西是按照自己的条件进行 esm 导入,而不是看起来 svelte 正在使用的节点模块解析模式。或者至少问题是如何走到这一步的。(这可能是错误的!)。

【讨论】:

    【解决方案3】:

    尝试像下面这样导入

    const {isEmail} = require('validator');
    

    【讨论】:

    • 好主意,但 SvelteKit 无法访问 require
    【解决方案4】:

    你试过这样导入吗?

    import validator from 'validator'
    

    我尝试使用最新的 SvelteKit 重现您的问题。这工作正常:

    // index.svelte
    <script>
        import validator from 'validator';
        let result = validator.isEmail('foo@bar.com');
        console.log(result);
    </script>
    

    当我将导入语句更改为:

    import validator from 'validator/es/lib/isEmail'
    

    我从你的问题中得到了错误(不能在模块外使用 import 语句)。

    导入validator/es/lib/isEmail 应该只导入库的一个子集。我不确定它会有多大的不同。它可能没有任何区别。稍大的构建击败了不起作用的构建。我建议先让它工作,然后如果你真的需要优化构建大小。

    【讨论】:

    • 那行得通。有趣的是,使用更新版本的 Svelte/kit,我也可以使用 validator/lib/isEmail
    【解决方案5】:

    在阅读了他们的文档:https://github.com/validatorjs/validator.js#es6 之后,看起来导入中的 es 部分是,所以它可以是 treeshakable。您可以通过正常导入来修复此错误:

    import isURL from 'validator/lib/isURL';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-08
      • 2022-09-28
      • 2021-10-02
      • 2020-03-15
      • 2021-03-16
      • 1970-01-01
      • 2021-02-21
      • 2021-07-08
      相关资源
      最近更新 更多