Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/475.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Chrome扩展的内容脚本中导入ES6模块_Javascript_Google Chrome_Google Chrome Extension_Ecmascript 6 - Fatal编程技术网

Javascript 如何在Chrome扩展的内容脚本中导入ES6模块

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

在Chrome 61中,添加了对JavaScript模块的支持。现在我正在运行Chrome63

我试图在Chrome扩展内容脚本中使用
导入
/
导出
语法来使用模块

在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中的true
    import
    export
    函数类似的简明语法
  • 允许名称间隔,可以是导出模块的文件名,其方式类似于JavaScript中的true
    导入
    导出
    命令的工作方式,但不必是(即名称空间名称可以是您想要的任何名称),以及
  • 允许导入时变量重命名,类似于
    导入{fn as myFn}…
    的工作方式
为此,您的
manifest.json
需要按如下方式加载JavaScript:

  • 首先建立导出/导入函数的文件(在下面的示例中名为
    modules start.js
  • 下一步是导出文件,然后
  • 最后一次导入文件
当然,您可能有一个同时导入和导出的文件。在这种情况下,只需确保该文件列在其导入的文件之后,但列在其导出到的文件之前

工作示例

下面的代码演示了此策略

需要注意的是,每个模块/文件中的所有代码都包含在大括号中。唯一的例外是
modules start.j中的第一行