Chrome扩展报错Uncaught ReferenceError: $ is not defined求解决方案
解决Chrome扩展Manifest V3中“Uncaught ReferenceError: $ is not defined”错误
核心问题分析
- Manifest V3的content_scripts限制:不能直接在
content_scripts的js数组中使用外部CDN链接,必须使用本地资源。 - CSP配置格式错误:Manifest V3中
content_security_policy是对象格式,而非字符串,且对外部脚本的权限需要精准配置。 - 上下文混淆:你的
meals.js同时在content script(注入网页)和popup(扩展弹窗)中加载,两个环境完全独立,popup的$未定义问题和content script配置无关。
具体修复步骤
1. 下载本地资源
将需要的外部JS文件(jQuery、Popper、Bootstrap JS)下载到你的扩展目录中,例如:
- 下载jQuery 3.4.1并命名为
jquery.min.js - 下载Popper和Bootstrap JS到本地
2. 修正Manifest.json
{ "name": "cooking aid", "version": "1.0.0", "description": "this is a random meal generator", "permissions": ["storage", "tabs"], "host_permissions": ["https://www.google.com/", "https://www.themealdb.com/"], "manifest_version": 3, "action": { "default_icon": "extension logo.png", "default_title": "cooking aid", "default_popup": "index.html" }, "content_scripts": [ { "matches": ["*://*/*"], "js": ["jquery.min.js", "meals.js"], "css": ["styles.css"] } ], "content_security_policy": { "extension_pages": "script-src 'self' https://code.jquery.com https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com; object-src 'self'", "sandbox": "sandbox allow-scripts; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'self'" } }
- 新增
https://www.themealdb.com/到host_permissions,确保AJAX请求有权限跨域 - 修正
content_security_policy为对象格式,允许popup页面加载外部CDN脚本(如果保留外部引用) - 将content_scripts中的外部jQuery链接替换为本地文件
3. 调整Popup的HTML脚本引用
如果选择使用本地jQuery,修改index.html中的脚本引用:
<script src="jquery.min.js"></script> <script src="popper.min.js"></script> <script src="bootstrap.min.js"></script> <script src="meals.js"></script>
如果坚持使用CDN,确保Manifest的extension_pages CSP已经包含对应域名,且脚本加载顺序正确(jQuery必须在meals.js之前)。
4. 检查代码完整性
你提供的meals.js代码中createMeal函数未闭合,补全代码避免语法错误:
$(function(){ const button = $('.btn'); const recipeContainer = $('#recipe'); button.on('click', function(){ $.ajax({ url : "https://www.themealdb.com/api/json/v1/1/random.php", method : "GET", dataType : "json", }).done((res) => { createMeal(res.meals[0]); }) }) function createMeal(res){ const ingredients = []; for (let i = 1; i <= 20; i++) { if (res[`strIngredient${i}`]) { ingredients.push( `${res[`strIngredient${i}`]} - ${res[`strMeasure${i}`]}` ); } else { break; } } // 补全后续逻辑,比如渲染到页面 let html = `<h3>${res.strMeal}</h3>`; html += `<ul>${ingredients.map(item => `<li>${item}</li>`).join('')}</ul>`; recipeContainer.html(html); } });
额外提示
- 区分content script和popup脚本:content script运行在网页上下文,popup运行在扩展独立上下文,两者的变量和资源不共享。
- 测试时重新加载扩展:修改Manifest或核心文件后,务必在Chrome扩展管理页点击“重新加载”按钮生效。
内容的提问来源于stack exchange,提问作者maria xu
相关产品推荐
相关产品推荐

