You need to enable JavaScript to run this app. Node.js中使用require引入模块应放在全局还是局部作用域?
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中使用require引入模块应放在全局还是局部作用域?

Node.js 中 require 语句的放置规范与实际差异

核心基础事实

Node.js 的 CommonJS 模块加载机制自带全局模块缓存:同一模块无论被 require 多少次,仅在第一次调用时完整执行模块加载逻辑,后续调用直接返回缓存好的导出对象。
也就是说,哪怕把 require('dns') 写在函数内部、循环甚至条件分支里,只要命中缓存,执行性能和全局放置没有可测量的差异,不存在“局部 require 会拖慢代码速度”的问题。

两种放置方式的优劣势对比

模块顶层(全局作用域)声明

这是Node.js 生态全场景通用的默认开发规范,核心优势:

  • 可读性最优:所有依赖集中在文件顶部,协作开发者打开文件就能第一时间掌握当前文件的全部外部依赖,不需要逐行扫遍函数体找依赖引入逻辑,大幅降低跨人协作的理解成本。
  • 符合静态检查与社区通用规则:包括 Node.js 核心仓库代码风格、ESLint 主流导入规则在内的通用规范,都要求依赖声明放置在模块顶层,规避运行时依赖加载顺序不可控的问题。
  • 问题暴露更早:如果模块本身存在加载错误(比如路径错误、导出异常),顶层声明会在文件被加载的第一时间抛出错误,而非等到函数被调用时才触发,更方便排查依赖问题。

适用场景:所有在模块中被复用、或是核心逻辑强依赖的内置/第三方模块,统一放置在文件顶部。

函数内部(局部作用域)声明

这种写法不属于错误实现,但有明确的适用边界,没有全场景替代顶层声明的通用性:

  • 合理使用的场景:
    • 可选依赖:如果某个模块仅在特定分支逻辑下使用,且存在加载失败风险(比如原生编译模块、体积较大的可选工具包),放在局部可以避免核心逻辑被非必要的依赖加载阻塞。
    • 循环依赖链路节点:把 require 放在函数内部延迟加载,是解决 CommonJS 循环依赖导致导出对象为 undefined 的常用手段。
  • 不适用的场景:比如示例中的 dns 内置模块,属于函数核心依赖、加载零成本,此时放在局部的问题非常明显:
    • 阅读函数逻辑时,必须顺着执行流找到中间的 require 语句,才能知晓函数依赖的外部能力,额外增加理解成本。
    • 如果后续文件新增其他函数也要用到 dns,很容易出现重复引入的冗余代码,甚至引发局部变量名冲突的问题。

针对示例代码的优化建议

你给出的两个实现中,dns 是 lookup 函数的核心强依赖,完全没有理由放在函数内部:

  • 把 const dns = require('dns') 放在文件最顶部,和其他依赖集中放置,是符合所有通用规范的最优写法。
  • 可顺手把原来的 let 声明换成 const,因为模块导出对象是固定引用,不需要重新赋值,符合不可变优先的编码习惯。

内容的提问来源于stack exchange,提问作者Dshiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 18:36:03