Webpack打包后出现Uncaught ReferenceError: $ is not defined问题求助
我来帮你拆解这两个问题,都是Webpack处理全局依赖时常见的坑:
一、用glob批量打包时$ is not defined的原因
你猜的没错,这完全是打包顺序的问题。Webpack确实会处理模块依赖,但当你用glob.sync("./src/js/*.js")把所有JS文件都作为入口时,Webpack会把这些文件当成独立的模块并行处理,不会自动识别谁依赖谁——也就是说,如果你的业务代码或者插件在jQuery之前被打包执行,那自然会找不到$。
解决这个问题的核心是强制让jQuery先被加载,有两种简单的方式:
- 手动指定jQuery在glob数组的最前面,避免它被排在后面:
这样能确保jQuery最先被打包,后面的文件就能拿到全局的entry: { bundle: ["./src/js/jquery.js", ...glob.sync("./src/js/*.js").filter(file => file !== "./src/js/jquery.js")] }$了。 - 改用单入口文件(也就是你后来尝试的方式),通过
import明确依赖顺序,这其实是Webpack推荐的模块化写法,比glob批量引入更可控。
二、单入口import $ from './jquery'后插件找不到jQuery的原因
很多老的jQuery插件(比如某些弹窗、表单插件)是基于全局jQuery/$变量开发的,它们不会主动去导入jQuery模块,而是直接在全局作用域找这个变量。但Webpack的import默认是把模块封装在局部作用域里的,不会自动把$挂载到window上,所以插件就会报错。
这里有几种靠谱的解决方案,按推荐程度排序:
1. 使用Webpack的ProvidePlugin(最推荐)
这个插件的作用是自动给所有模块注入指定的依赖,不用手动import就能用。在你的webpack.config.js里配置:
const webpack = require('webpack'); const path = require('path'); module.exports = { entry: "./src/js/entry_file.js", output: { filename: "bundle.js", path: path.resolve(__dirname, "dist/js") }, plugins: [ new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', // 有些插件只认jQuery,所以两个都写上 'window.jQuery': 'jquery' // 确保window全局对象上也有这个变量 }) ] };
配置后,你甚至可以在入口文件里删掉import $ from './jquery',Webpack会自动把jQuery注入到所有用到$或jQuery的模块里,插件也能在全局找到它了。
2. 手动把jQuery挂载到window上
如果你不想改Webpack配置,也可以在入口文件里手动把$挂到全局:
import $ from './jquery'; // 先挂载全局变量 window.$ = $; window.jQuery = $; // 再导入依赖jQuery的插件 import hljs from './highlight'; // 其他插件...
这种方式简单直接,但缺点是需要确保挂载操作在所有插件导入之前执行。
3. 使用expose-loader(适合老项目兼容)
这个loader可以把模块暴露到全局作用域里,先安装它:
npm install expose-loader --save-dev
然后在Webpack配置里添加规则:
module.exports = { // ...其他配置 module: { rules: [ { test: require.resolve('jquery'), // 匹配jquery模块 loader: 'expose-loader', options: { exposes: ['$', 'jQuery'] } } ] } };
或者在入口文件里用内联loader的方式:
import $ from 'expose-loader?$!expose-loader?jQuery!./jquery';
这种方式也能让jQuery成为全局变量,但现在ProvidePlugin是更主流的方案。
总结
- 批量引入文件时一定要注意依赖顺序,Webpack不会自动猜测谁先谁后;
- 老插件依赖全局变量时,用
ProvidePlugin是最优雅的解决方式,既能保持模块化,又能满足插件的全局依赖需求。
内容的提问来源于stack exchange,提问作者user1063287

