JSDOM 未加载包含在 <script> 标签中的 JavaScript
JSDOM is not loading JavaScript included with <script> tag
注意:这个问题不是其他现有问题的重复,因为这个问题不使用 jsdom.env()
旧版本 JSDOM 使用的函数调用。
文件bar.js
:
console.log('bar says: hello')
文件foo.js
:
var jsdom = require('jsdom')
var html = '<!DOCTYPE html><head><script src="bar.js"></script></head><body><div>Foo</div></body>'
var window = new jsdom.JSDOM(html).window
window.onload = function () {
console.log('window loaded')
}
当我 运行 foo.js
时,我得到了这个输出。
$ node foo.js
window loaded
为什么bar says: hello
输出没有来?看起来 bar.js
没有加载。如何让 jsdom
加载 script
标签中的文件?
[EDIT/SOLUTION]: 按照 Quentin 的回答中的建议解决了问题。此代码有效:
var jsdom = require('jsdom')
var html = '<!DOCTYPE html><head><script src="bar.js"></script></head><body><div>Foo</div></body>'
var window = new jsdom.JSDOM(html, { runScripts: "dangerously", resources: "usable" }).window
window.onload = function () {
console.log('window loaded')
}
浏览标题,直到找到标有 Executing scripts
的标题
To enable executing scripts inside the page, you can use the
runScripts: "dangerously"
option:
const dom = new JSDOM(`<body>
<script>document.body.appendChild(document.createElement("hr"));</script>
</body>`, { runScripts: "dangerously" });
// The script will be executed and modify the DOM:
dom.window.document.body.children.length === 2;
Again we emphasize to only use this when feeding jsdom code you know
is safe. If you use it on arbitrary user-supplied code, or code from
the Internet, you are effectively running untrusted Node.js code, and
your machine could be compromised.
If you want to execute external scripts, included via <script
src="">
, you'll also need to ensure that they load them. To do this,
add the option resources: "usable"
as described below.
鉴于我无法从上面的代码中重现基于 url
的解决方案...
残酷的捆绑替代方案:全部内联!
读取各种 .js
文件,将它们作为字符串注入 html 页面。然后像在普通导航器中一样等待页面加载。
这些库已加载到 _window = new JSDOM(html, { options }).window;
中,因此可用于您的节点脚本。
这可能会阻止您进行 xhr 调用,因此只能部分解决问题。
say-hello.js
// fired when loaded
console.log("say-hello.js says: hello!")
// defined and needing a call
var sayBye = function(name) {
var name = name ||'Hero!';
console.log("say-hello.js says: Good bye! "+name)
}
main.js:
const fs = require("fs");
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
var NAME = process.env.NAME; // variable from terminal
var html = '<!DOCTYPE html><head></head><body><div>Foo</div></body>'
var _window = new JSDOM(html, {
runScripts: "dangerously",
resources: "usable" }).window;
/* ************************************************************************* */
/* Add scripts to head ***************************************************** */
var jsFiles = [
'say-hello.js'
];
var scriptsContent = ``;
for(var i =0; i< jsFiles.length;i++){
console.log(__dirname + '/'+ jsFiles[i])
let scriptContent = fs.readFileSync( jsFiles[i], 'utf8');
scriptsContent = scriptsContent + `
/* ******************************************************************************************* */
/* `+jsFiles[i]+` **************************************************************************** */
`+scriptContent;
};
let scriptElement = _window.document.createElement('script');
scriptElement.textContent = scriptsContent;
_window.document.head.appendChild(scriptElement);
/* ************************************************************************* */
/* Run page **************************************************************** */
_window.document.addEventListener('DOMContentLoaded', () => {
console.log('main says: DOMContentLoaded')
// We need to delay one extra turn because we are the first DOMContentLoaded listener,
// but we want to execute this code only after the second DOMContentLoaded listener
// (added by external.js) fires.
_window.sayBye(NAME); // prints "say-hello.js says: Good bye!"
});
运行它:
NAME=John node main.js # expects hello and good bye to john messages
来源:
根据 source,使用 JSDOM 选项 url : file://${__dirname}/index.html
可能有效。如果您测试它,请在此处报告结果。
注意:这个问题不是其他现有问题的重复,因为这个问题不使用 jsdom.env()
旧版本 JSDOM 使用的函数调用。
文件bar.js
:
console.log('bar says: hello')
文件foo.js
:
var jsdom = require('jsdom')
var html = '<!DOCTYPE html><head><script src="bar.js"></script></head><body><div>Foo</div></body>'
var window = new jsdom.JSDOM(html).window
window.onload = function () {
console.log('window loaded')
}
当我 运行 foo.js
时,我得到了这个输出。
$ node foo.js
window loaded
为什么bar says: hello
输出没有来?看起来 bar.js
没有加载。如何让 jsdom
加载 script
标签中的文件?
[EDIT/SOLUTION]: 按照 Quentin 的回答中的建议解决了问题。此代码有效:
var jsdom = require('jsdom')
var html = '<!DOCTYPE html><head><script src="bar.js"></script></head><body><div>Foo</div></body>'
var window = new jsdom.JSDOM(html, { runScripts: "dangerously", resources: "usable" }).window
window.onload = function () {
console.log('window loaded')
}
浏览标题,直到找到标有 Executing scripts
的标题To enable executing scripts inside the page, you can use the
runScripts: "dangerously"
option:const dom = new JSDOM(`<body> <script>document.body.appendChild(document.createElement("hr"));</script> </body>`, { runScripts: "dangerously" }); // The script will be executed and modify the DOM: dom.window.document.body.children.length === 2;
Again we emphasize to only use this when feeding jsdom code you know is safe. If you use it on arbitrary user-supplied code, or code from the Internet, you are effectively running untrusted Node.js code, and your machine could be compromised.
If you want to execute external scripts, included via
<script src="">
, you'll also need to ensure that they load them. To do this, add the optionresources: "usable"
as described below.
鉴于我无法从上面的代码中重现基于 url
的解决方案...
残酷的捆绑替代方案:全部内联!
读取各种 .js
文件,将它们作为字符串注入 html 页面。然后像在普通导航器中一样等待页面加载。
这些库已加载到 _window = new JSDOM(html, { options }).window;
中,因此可用于您的节点脚本。
这可能会阻止您进行 xhr 调用,因此只能部分解决问题。
say-hello.js
// fired when loaded
console.log("say-hello.js says: hello!")
// defined and needing a call
var sayBye = function(name) {
var name = name ||'Hero!';
console.log("say-hello.js says: Good bye! "+name)
}
main.js:
const fs = require("fs");
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
var NAME = process.env.NAME; // variable from terminal
var html = '<!DOCTYPE html><head></head><body><div>Foo</div></body>'
var _window = new JSDOM(html, {
runScripts: "dangerously",
resources: "usable" }).window;
/* ************************************************************************* */
/* Add scripts to head ***************************************************** */
var jsFiles = [
'say-hello.js'
];
var scriptsContent = ``;
for(var i =0; i< jsFiles.length;i++){
console.log(__dirname + '/'+ jsFiles[i])
let scriptContent = fs.readFileSync( jsFiles[i], 'utf8');
scriptsContent = scriptsContent + `
/* ******************************************************************************************* */
/* `+jsFiles[i]+` **************************************************************************** */
`+scriptContent;
};
let scriptElement = _window.document.createElement('script');
scriptElement.textContent = scriptsContent;
_window.document.head.appendChild(scriptElement);
/* ************************************************************************* */
/* Run page **************************************************************** */
_window.document.addEventListener('DOMContentLoaded', () => {
console.log('main says: DOMContentLoaded')
// We need to delay one extra turn because we are the first DOMContentLoaded listener,
// but we want to execute this code only after the second DOMContentLoaded listener
// (added by external.js) fires.
_window.sayBye(NAME); // prints "say-hello.js says: Good bye!"
});
运行它:
NAME=John node main.js # expects hello and good bye to john messages
来源:
根据 source,使用 JSDOM 选项 url : file://${__dirname}/index.html
可能有效。如果您测试它,请在此处报告结果。