如何在 esbuild 中正确暴露 jQuery 给依赖脚本使用

作者:袖梨 2026-07-10

esbuild 默认将导入的模块封装在独立作用域中,导致通过 import 加载的 jQuery 无法被全局依赖脚本(如传统 UMD/AMD 或无模块声明的 JS 文件)访问;需通过 inject、banner 或全局挂载等机制显式暴露全局变量。

esbuild 默认将导入的模块封装在独立作用域中,导致通过 import 加载的 jquery 无法被全局依赖脚本(如传统 umd/amd 或无模块声明的 js 文件)访问;需通过 `inject`、`banner` 或全局挂载等机制显式暴露全局变量。

在 esbuild 中,import 语句引入的模块默认处于严格模块作用域——即使你 import jQuery from './jquery-3.7.1.js',该 jQuery 变量也仅在当前模块内有效,不会自动挂载到 window 上。而像 otherFile.js 这类传统脚本(通常直接使用 jQuery.fn.xxx 或 $()),其运行时依赖的是全局 window.jQuery 和 window.$,因此会报错 "jQuery is not defined"。

✅ 正确解决方案不是“先 import 再手动赋值”,因为 ES 模块的执行顺序和作用域隔离可能导致 window.jQuery = jQuery 在 otherFile.js 执行前尚未生效(尤其当 otherFile.js 是非模块脚本且被动态加载或异步执行时)。推荐以下三种生产级方案:

✅ 方案一:使用 inject 选项(推荐|最可靠)

inject 允许你将一个导出全局变量的模块“注入”到每个入口文件顶部,确保 jQuery 在任何依赖代码执行前已就绪:

// inject-jquery.jsimport jQuery from './jquery-3.7.1.js';window.jQuery = window.$ = jQuery;

构建命令:

esbuild src/index.js   --bundle   --inject:./inject-jquery.js   --outfile=dist/bundle.js

此时 esbuild 会自动将 inject-jquery.js 的内容前置插入,等效于:

// 自动生成的 bundle 开头var jQuery = (() => { /* jquery source */ })();window.jQuery = window.$ = jQuery;// 后续你的其他 import...import './otherFile.js'; // ✅ 此时 window.jQuery 已存在

✅ 方案二:使用 banner 注入全局声明(轻量简洁)

适用于 jQuery 已通过 CDN 引入,或你只需声明全局变量名(配合 --external:jquery):

esbuild src/index.js   --bundle   --banner:js="import jQuery from './jquery-3.7.1.js'; window.jQuery = window.$ = jQuery;"   --outfile=dist/bundle.js

⚠️ 注意:banner 中的代码在 bundle 最顶端执行,但需确保 jquery-3.7.1.js 是可解析的本地模块(非外部 CDN)。

✅ 方案三:改用 <script> 外部加载(兼容性最强)

如项目允许混合加载,直接在 HTML 中优先加载 jQuery:

<script src="jquery-3.7.1.min.js"></script><script src="dist/bundle.js"></script> <!-- 此 bundle 中不再 import jQuery -->

并在 index.js 中移除 import jQuery,改为声明类型(避免 TS 报错):

// @ts-ignoredeclare const jQuery: any;// 或使用 declare global(TypeScript 环境)

⚠️ 注意事项

  • ❌ 避免 import jQuery from '...'; window.jQuery = jQuery; import './otherFile.js'; —— 因 ES 模块静态分析与执行时机,otherFile.js 若为 CommonJS/UMD 格式,仍可能在 window.jQuery 赋值前执行;
  • ✅ inject 是 esbuild 官方支持的标准化方案,适用于所有需全局暴露的库(如 Lodash、Moment.js);
  • ? 检查 otherFile.js 是否含 'use strict' 或 export/import —— 若是现代模块,应改用 import $ from 'jquery' 并统一模块化管理;
  • ? 若使用 --minify,确保 jQuery 构建版本已压缩且保留 window 挂载逻辑(官方 dist 版本默认支持)。

总结:esbuild 的模块封闭性是设计使然,而非缺陷。要桥接传统脚本生态,必须主动、提前、可靠地暴露全局变量——inject 是最符合工程规范的解法。

相关文章

精彩推荐