升级至Angular 6后jQuery失效,报$(...).func is not a function错误
我之前升级Angular和Webpack的时候也踩过这个坑,明明ProvidePlugin配置没改,但就是全局jQuery失效了。其实是Webpack 4对模块加载和全局变量暴露的逻辑有了一些细节变化,给你几个亲测有效的修复思路:
1. 先检查jQuery插件的加载顺序
Webpack 4的模块解析优先级调整了,很可能你的jQuery插件是在jQuery被全局暴露之前就加载了。如果插件是通过npm安装的,去插件的入口文件看看,确认它是用require('jquery')或者import $ from 'jquery'来引入依赖,而不是直接依赖全局的$;如果是自定义的脚本,要确保它在jQuery之后被导入。
2. 调整ProvidePlugin配置,补全全局映射
虽然官方文档说配置没变,但实际测试下来,给ProvidePlugin加上global对象的映射能解决不少场景下的问题,修改后的配置如下:
plugins: [ new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", jquery: "jquery", "window.$": "jquery", "window.jQuery": "jquery", global: "global" // 新增这行,确保全局环境能正确识别jQuery }), ]
3. 用expose-loader强制暴露jQuery到全局
如果ProvidePlugin在Angular的环境下被CLI内部配置覆盖了(尤其是用Angular CLI升级的项目),可以试试用expose-loader直接把jQuery挂载到window上:
- 先安装依赖:
npm install expose-loader --save-dev - 在webpack的module规则里添加:
module: { rules: [ { test: require.resolve('jquery'), use: [ { loader: 'expose-loader', options: '$' }, { loader: 'expose-loader', options: 'jQuery' } ] } ] }
或者更直接的,在项目的polyfills.ts里手动挂载:
import * as $ from 'jquery'; window.$ = $; window.jQuery = $;
这个方法虽然简单粗暴,但在紧急情况下能快速解决问题。
4. 检查Angular CLI的配置(CLI升级的项目必看)
如果你是通过Angular CLI升级到6.x的,CLI的内置webpack配置可能会覆盖你自定义的ProvidePlugin。这时候直接在angular.json的scripts数组里按顺序添加jQuery和插件的路径:
"scripts": [ "./node_modules/jquery/dist/jquery.min.js", "./src/assets/js/your-jquery-plugin.js" // 插件要放在jQuery后面 ]
CLI会把这些脚本作为全局资源注入,确保jQuery先被加载,插件能找到全局的$。
5. 排查jQuery重复加载的问题
有时候Webpack 4会因为模块依赖的问题,导致jQuery被加载了多次(比如某个第三方插件自己也依赖了不同版本的jQuery),这时候全局的$和插件里的$不是同一个实例,自然会出现func is not a function的错误。可以用resolve.alias强制所有模块使用同一个jQuery版本:
resolve: { alias: { 'jquery': path.resolve(__dirname, 'node_modules/jquery/dist/jquery.min.js') } }
这样不管哪个模块导入jQuery,都会指向同一个文件,避免多实例冲突。
内容的提问来源于stack exchange,提问作者Nicolas

