Jsdom: Use jsdom in a browser

Created on 6 Nov 2015  Â·  24Comments  Â·  Source: jsdom/jsdom

It seems that jsdom can be run inside browsers, but the README does not really provide instructions on how to go about it.

Is there a browserified script I can just include in my page as a <script> tag? If not, how do I go about making one? Will update the README and send a PR with the instructions if someone clarifies them :)

documentation

Most helpful comment

@Slapbox Later I removed it form my app. But this commit fixed the issue for me. However I used webpack through Next.js, the config though should be the same. Hope it helps.

All 24 comments

Such a bundle is not distributed along with jsdom. If you use browserify, all you have to do is require it in your script:

const jsdom = require('jsdom');
// ... do stuff

Alternatively, you can instruct browserify to generate a bundle which automatically defines a window.require function. That way you can use require('jsdom') in an inline <script> or even in the browser console. browserify -r jsdom -o jsdom.js

Make sure that jsdom.js is served as utf-8, otherwise you will get errors.

Note that currently only chrome is supported because firefox is a missing a few features.

Ah I see. That's why I was getting syntax errors on Firefox. I was able to get it working with Chrome. I'll leave this issue open until I send a PR to update the README to make this clear.

@czardoz As an alternative you can use Babel tranform with Browserify to make jsdom work in older browsers. AFAIK, currently jsdom doesn't use anything what can't be transpiled to ES5.

@inikulin Great, I'll try that!

@czardoz Don't forget to use global transform since some jsdom deps require transpilation as well.

Wow it feels as if you're reading the errors on my terminal :-)

Thanks for saving an hour of my time!
On 06-Nov-2015 11:08 pm, "Ivan Nikulin" [email protected] wrote:

@czardoz https://github.com/czardoz Don't forget to use globalTransform
https://github.com/substack/module-deps/pull/21 since some jsdom deps
require transpilation as well.

—
Reply to this email directly or view it on GitHub
https://github.com/tmpvar/jsdom/issues/1284#issuecomment-154481358.

if i recall correctly, the only thing can not be transpiled correctly (in jsdom) is Symbol. It will work, however the polyfill will introduce small bugs. Firefox supports Symbol though.

Still no JSDOM for browsers? @czardoz did you succeed in compiling it or not? It would really help me if you shared your results.

@Darker yes, but I was only able to get it working in Chrome. It didn't work for me inside Firefox even when I used Babel (with the "global" option). This comment: https://github.com/tmpvar/jsdom/issues/1018#issuecomment-73269131 clearly shows how to browserify it. I haven't gotten around to updating the ReadMe yet, will do it sometime this week.

In simple words, just "require" jsdom in your script, and things should work fine in chrome. Specifying the "scripts" array containing URLs does not work due to #1285, but you can work around that by passing a custom resource loader. Hope this helps.

Fwiw, I just used this and it actually runs in Edge too, if you replace "for (const" by "for (let" in the script generated by browserify, but the performance is shockingly bad at least on the build of Edge I am using. I'll try to work on this with someone from the Chakra team to understand why.

I had less luck with Firefox which still lacks a lot of ES2015 features, or support them badly. I still got it running in Firefox after running babel and adding dirty hacks (like declaring globally some variables which were reported as reference errors which most certainly mean babel failed to work properly on the script). The performance was 2x slower than in Chrome, and the hacks I had to add mean that some things were not working properly; that could have worked well enough for my use case though, I believe.

Would love to hear about which WebKit prefixed APIs we are abusing. Too bad Edge has that for loop bug.

No, the spec has always behaved that way since the initial for-of design. It's just a bug.

And yeah, I wonder where browserify uses IDB... we should fix that so poor Edge doesn't have to keep adding webkit things.

Interesting! Does it run without the polyfill in Edge, with only the for loop change?

Hey, I'm back on this. I got JSDOM running my demo in Edge at a 3x-slower-than-chrome rate by removing Chakra's implementation of Symbol. That might have introduced subtle bugs but at least in my case it made JSDOM actually usable. I figured out I would share the info in case someone else hit the same stone ;-)

self.SymbolCounter = 0;
self.RealSymbol = self.Symbol;
self.Symbol = function Symbol(description) {
    return (description || 'Symbol')+'['+(SymbolCounter++)+']'; 
}
self.Symbol.iterator = self.RealSymbol.iterator;

NOTE: The issue I was facing may be related to what I'm actually doing in the worker with the JSDOM but in my case I choked heavily on SymbolTree and related Symbol usages, which made the script incredibly slow due to frequent object shapes variations and ultimately frequent bailout out of optimized codepaths.

Chakra is probably not be able to optimize objects containing symbols yet. It might fallback to a pure hashmap.

We try to initialize all properties that we need at construction of an object, which should help with optimizing objects (like v8's "fast properties"). From what I have seen, symbols in v8 only have a very minor performance impact (versus regular properties)

I was being told that the "for(const ... of ...)" issue has now been fixed in Edge. Should be part of the next Windows Preview build, hopefully. Enjoy the insight ;-)

Ahahah, how about you send a pull request ;-)
I mean, I already work in the Edge team :D
Not in the Chakra team, though...

hah I might

Any update on this issue? I'm facing the same problem with require on browserify. Tks!

Any update on this issue? I'm facing the same problem with require on browserify. Tks!

jsdom runs in chrome just fine (even within a web worker). We even have a CI script which tests that using karma for every pull request (using browserify!).

However last time I checked (few months ago) Firefox and Edge still lacked a few (standardized) features. You _might_ be able to transpile/polyfill those features. However a few of these features can not be polyfilled (such as ES6 Proxy). We really need those features, you can not implement DOM and HTML without them.

Anyway, is there a more specific problem that you are having?

I managed to get it running in browser (needed just document for parsing dom from string, modifying and serializing back in isomorphic code) via webpack with options child_process: 'empty', net: 'empty', tls: 'empty'.

@grissius Do you mean you used Webpack's aliasing feature? If not, can you share how you got this working?

@Slapbox Later I removed it form my app. But this commit fixed the issue for me. However I used webpack through Next.js, the config though should be the same. Hope it helps.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xlmnxp picture xlmnxp  Â·  21Comments

rgbkrk picture rgbkrk  Â·  31Comments

felipemsantana picture felipemsantana  Â·  26Comments

selam picture selam  Â·  41Comments

jimfb picture jimfb  Â·  89Comments