Jsdom: 外部スクリプトをどのようにロードしますか?

作成日 2017年07月07日  ·  3コメント  ·  ソース: jsdom/jsdom

jsdomは、ドキュメントの<head>タグ内でインラインのスクリプトを実行できますが、 <script src="">を介してドキュメントヘッドにリンクされているスクリプトを実行するにはどうすればよいですか?

私が使用しているオプションの場合:

{
    url: url,
    resources: 'usable',
    runScripts: 'dangerously',
}

基本情報:

  • Node.jsバージョン:8.1.2
  • jsdomバージョン:11.1.0

最小限の複製の場合:

// index.js
const request = require('request')
const jsdom = require('jsdom')
const {JSDOM} = jsdom
const url = 'http://localhost:8000'

request(url, (error, response, body) => {
  const options = {
    url: url,
    resources: 'usable',
    runScripts: 'dangerously',
  }

  const dom = new JSDOM(body, options)

  console.log(dom.window.document.body.children.length) // Expecting to see `1`
  console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
})
// external.js
document.addEventListener('DOMContentLoaded', () => {
  document.write('<h1>Hello world!</h1>')
})
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>JSDOM test</title>
    <script src="external.js"></script>
  </head>
  <body>
  </body>
</html>

最小限の作業例を完了する: https ://github.com/cg433n/jsdom-test

最も参考になるコメント

ここでの問題は、 DOMContentLoadedが非同期イベントであるということです。 発生する前にログに記録しています。 あなたはそれが発火するのを待つ必要があります。 そうして初めて、あなたのdocument.write()が起こります。

このようなものはおそらく機能するはずです:

const dom = new JSDOM(body, options)

dom.window.document.addEventListener('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.
  setImmediate(() => {
    console.log(dom.window.document.body.children.length) // Expecting to see `1`
    console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
  });
});

全てのコメント3件

ここでの問題は、 DOMContentLoadedが非同期イベントであるということです。 発生する前にログに記録しています。 あなたはそれが発火するのを待つ必要があります。 そうして初めて、あなたのdocument.write()が起こります。

このようなものはおそらく機能するはずです:

const dom = new JSDOM(body, options)

dom.window.document.addEventListener('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.
  setImmediate(() => {
    console.log(dom.window.document.body.children.length) // Expecting to see `1`
    console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
  });
});

そうか! あなたたちは素晴らしいです-良い仕事を続けてください!

注意:上記のデモの2つの機能にはリスクが伴います。

  • npm requestは減価償却されます。 npm install requestの結果:
    >npm警告非推奨[email protected] :リクエストは非推奨になりました。https ://github.com/request/request/issues/3142を参照してください
  • setImmediateは長期的には危険です。
    Screenshot_2020-09-02_18-46-34

FSハック

または、 fsを使用してファイルからjsコードを読み取り、読み込むことをお勧めします。#3023の@EricRickettsFS.read()アプローチと@DomenicaddEventListener()に基づくStackoverflowを参照してください。 #1914。 私が提案する作業デモには次のものが含まれます。

  • fs.readFileSyncを使用して、外部jsを文字列としてhtmlにロードします
  • いくつかの外部jsファイルを処理するためのループ
  • 外部jsの関数を起動するユースケース
  • 端末変数をノードに渡し、次に外部js関数に渡すユースケース

これにより、xhr / API呼び出しを実行できなくなる可能性があり、したがって問題は部分的にしか解決されません。

URL

URLを機能させる方法がわかりませんでした。
理想的には、 URL作業デモを介してexternal.jsファイルをロードする更新された最小限のJSDOMが歓迎されます。 :心臓:

このページは役に立ちましたか?
0 / 5 - 0 評価