Javascript 如何在Chrome扩展的内容脚本中导入ES6模块
在Chrome 61中,添加了对JavaScript模块的支持。现在我正在运行Chrome63 我试图在Chrome扩展内容脚本中使用Javascript 如何在Chrome扩展的内容脚本中导入ES6模块,javascript,google-chrome,google-chrome-extension,ecmascript-6,Javascript,Google Chrome,Google Chrome Extension,Ecmascript 6,在Chrome 61中,添加了对JavaScript模块的支持。现在我正在运行Chrome63 我试图在Chrome扩展内容脚本中使用导入/导出语法来使用模块 在manifest.json中: "content_scripts": [ { "js": [ "content.js" ], } ] 'use strict'; const injectFunction = () => window.alert('hell
导入
/导出
语法来使用模块
在manifest.json中:
"content_scripts": [
{
"js": [
"content.js"
],
}
]
'use strict';
const injectFunction = () => window.alert('hello world');
export default injectFunction;
'use strict';
import injectFunction from './my-script.js';
injectFunction();
"content_scripts": [ {
"js": [
"content.js"
]
}],
"web_accessible_resources": [
"main.js",
"my-script.js"
]
在my script.js
中(与content.js
目录相同):
在content.js
中:
"content_scripts": [
{
"js": [
"content.js"
],
}
]
'use strict';
const injectFunction = () => window.alert('hello world');
export default injectFunction;
'use strict';
import injectFunction from './my-script.js';
injectFunction();
"content_scripts": [ {
"js": [
"content.js"
]
}],
"web_accessible_resources": [
"main.js",
"my-script.js"
]
我收到此错误:未捕获的语法错误:意外标识符
如果我将导入语法从“/myscript.js”更改为import{injectFunction}代码>我收到此错误:未捕获的语法错误:意外标记{
在Chrome extension中的content.js
中使用此语法是否有问题(因为在HTML中您必须使用
语法),或者我做错了什么?谷歌会忽略对扩展的支持,这似乎很奇怪。将模块作为对象导出:
'use strict';
const injectFunction = () => window.alert('hello world');
export {injectFunction};
然后可以导入其属性:
'use strict';
import {injectFunction} from './my-script.js';
我设法找到了一个解决办法
免责声明
首先,很重要的一点是,内容脚本从2018年1月起不支持模块。这一解决方案通过将模块script
标记嵌入到返回到扩展的页面中来规避限制
变通办法
这是我的清单。json
:
"content_scripts": [
{
"js": [
"content.js"
],
}
]
'use strict';
const injectFunction = () => window.alert('hello world');
export default injectFunction;
'use strict';
import injectFunction from './my-script.js';
injectFunction();
"content_scripts": [ {
"js": [
"content.js"
]
}],
"web_accessible_resources": [
"main.js",
"my-script.js"
]
请注意,我在web\u可访问的\u资源中有两个脚本
这是我的content.js
:
"content_scripts": [
{
"js": [
"content.js"
],
}
]
'use strict';
const injectFunction = () => window.alert('hello world');
export default injectFunction;
'use strict';
import injectFunction from './my-script.js';
injectFunction();
"content_scripts": [ {
"js": [
"content.js"
]
}],
"web_accessible_resources": [
"main.js",
"my-script.js"
]
“严格使用”;
const script=document.createElement('script');
script.setAttribute(“类型”、“模块”);
script.setAttribute(“src”、chrome.extension.getURL(“main.js”);
const head=document.head | | document.getElementsByTagName(“head”)[0]| | document.documentElement;
head.insertBefore(脚本,head.lastChild);
这将把main.js
作为模块脚本插入网页
我所有的业务逻辑现在都在main.js
中
要使此方法正常工作,main.js
(以及我将导入的所有脚本)必须位于清单中的web\u accessible\u资源中
用法示例:myscript.js
“严格使用”;
const injectFunction=()=>window.alert('hello world');
导出{injectFunction};
在main.js
中,这是一个导入脚本的示例:
“严格使用”;
从“/myscript.js”导入{injectFunction};
注入函数();
这是有效的!不会抛出错误,我很高兴。我只是在自己尝试解决同样的问题时偶然发现了这个问题
无论如何,我认为有一个更简单的解决方案可以将您自己的自定义模块注入到内容脚本中。我正在研究Jquery是如何注入的,我突然想到,您可以通过创建iLife(立即调用的函数表达式)来做同样的事情,并在manifest.json中声明它
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": [
"content-scripts/globals.js",
"content-scripts/script1.js",
"content-scripts/script2.js"
]
}
],
事情是这样的:
exportVars({ var1, var2, var3 }).from('my-utility');
const { var1, var3: newNameForVar3 } = importVarsFrom('my-utility');
在manifest.json中:
"content_scripts": [
{
"matches": ["https://*"],
"css": ["css/popup.css"],
"js": ["helpers/helpers.js"]
}],
然后在helpers/helpers.js中创建一个iLife:
var Helpers = (function() {
var getRandomArbitrary = function(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
return {
getRandomArbitrary: getRandomArbitrary
}
})()
现在,您可以在内容脚本中自由使用助手函数:
Helpers.getRandomArbitrary(0, 10) // voila!
我认为,如果您使用此方法重构一些通用函数,那将非常棒。希望这能有所帮助!简短回答:
通过创建以下文件并在manifest.json的前面列出它,您可以在浏览器扩展中模拟一些功能并获得导入
/导出
的一些好处:
let exportVars, importVarsFrom;
{
const modules = {};
exportVars = varsObj => ({
from(nameSpace) {
modules[nameSpace] || (modules[nameSpace] = {});
for (let [k,v] of Object.entries(varsObj)) {
modules[nameSpace][k] = v;
}
}
});
importVarsFrom = nameSpace => modules[nameSpace];
}
然后,从一个文件/模块导出,如下所示:
exportVars({ var1, var2, var3 }).from('my-utility');
const { var1, var3: newNameForVar3 } = importVarsFrom('my-utility');
导入到另一个文件/模块,如下所示:
exportVars({ var1, var2, var3 }).from('my-utility');
const { var1, var3: newNameForVar3 } = importVarsFrom('my-utility');
讨论:
这一战略:
- 允许在浏览器扩展名中使用模块化代码
,这样可以将代码拆分为多个文件,但不会因不同文件之间共享全局范围而产生变量冲突
仍然允许您从不同的JavaScript文件/模块中导出和导入变量
只引入两个全局变量,即导出函数和导入函数
在每个文件(例如,chrome.runtime
等)中维护完整的浏览器扩展功能,该功能通过使用模块脚本标记嵌入的另一个答案(当前接受的答案)中的方法消除
使用与JavaScript中的trueimport
和export
函数类似的简明语法
导入
和导出
命令的工作方式,但不必是(即名称空间名称可以是您想要的任何名称),以及导入{fn as myFn}…
的工作方式manifest.json
需要按如下方式加载JavaScript:
- 首先建立导出/导入函数的文件(在下面的示例中名为
)modules start.js
- 下一步是导出文件,然后
- 最后一次导入文件
modules start.j中的第一行