segment-boneyard/nightmare

v2 proposal

Closed this issue · 24 comments

we're starting to consider major improvements that could be made in v2 of nightmare. the proposal is to move from phantomjs to electron, and move the api to use generators.

speed

some of the most vexing issues with nightmare (e.g. #199 and #192) seem to boil down to underlying issues in phantomjs. @matthewmueller has done some experimentation with atom/electron and sees 2-3x speed improvements loading and getting the title of the page:

Site Phantom Electron Speedup
Google 2064ms 866ms 2.4x
Yahoo 4059ms 1862ms 2.2x
CNN 8658ms 2729ms 3.2x

generators

one of nightmare's original goals was to eliminate the callback hell of raw phantomjs. with generators now on node stable, it makes sense to take the api one step closer to eliminating callbacks using generators. this should also make the execution more linear, understandable and controllable. ideally this is a solution to requests like #177, #176, #160 and #59.

var nightmare = new Nightmare();

// generators allow us to get the value back synchronously
var title = yield nightmare
    .goto('http://facebook.com')
    .evaluate(function() {
      return document.title;
    });

// continue with the same instance of nightmare + page state
var titleSearch = yield nightmare
    .click('#search')
    .evaluate(function(){
      return document.title;
    });

// tear down the page state
yield nightmare.close();

if you have other feedback or frustrations at this deeper level, please let us know!

Awesome stuff! I wonder how soon will that be :)

I'm glad that this is getting some generator love too. 👍

Just pushed up a branch for v2. I could use some help finishing up some of the remaining tasks:

  • port over the remaining actions
  • add some examples
  • write some tests

Unfortunately, I cannot create a PR because the commit history is completely different. I could just write on top of all the old files though.

cc/ @reinpk @amillet89

awesome @matthewmueller just pushed some updates with a structure for testing based on the old tests, as well as circleci setup, and adding the .back() action... will push it a bit further this afternoon

ported over a bunch more actions (with tests)... remaining ones are things like pdf, screenshot, some variants of wait, the event handlers, and initial options. the readme is mostly updated as well.

Nice work @reinpk! Can't wait to see this release in the wild.

todos:

  • add support for .wait(selector)
  • add support for .wait(fn, val, [delay])
  • add support for .screenshot(path)
  • add support for .pdf(path)
  • add support for page events
  • add support for initial browser window options
  • update readme for page events and initial options
  • update landing page description and example at https://nightmarejs.org
  • read through open issues, create test cases and see what we can fix now

Getting close... will pick this up next week when I'm back from vacation.

Nice! can't wait for v2

Excited for this! Thank you :D

@reinpk Interested to hear your thoughts on this. One thing I'd like to change is the ability to wait for click events to be fulfilled. Unless I'm missing something, right now you need to basically know what's coming (on the next page) and wait for it.

yield Nightmare()
  .click('a')
  .wait('.some-selector-on-the-next-page')

It'd be nice to be able to say something like:

yield Nightmare()
  .click('a')

And detect that the page is transitioning (maybe using window.beforeunload) and wait.

ah, that's a very interesting idea yeah. in v1 you could just call .wait() without any arguments... do you think omitting the .wait() altogether is the right solution, or just making it so that the complexity of finding a relevant selector is unnecessary?

I think when you are on html pages with wait method is enough but on
angular or pages that inject and load content on some elements on page you
need to point exactly the selector you want to wait for

El miércoles, 2 de septiembre de 2015, Peter Reinhardt <
notifications@github.com> escribió:

ah, that's a very interesting idea yeah. in v1 you could just call .wait()
without any arguments... do you think omitting the .wait() altogether is
the right solution, or just making it so that the complexity of finding a
relevant selector is unnecessary?


Reply to this email directly or view it on GitHub
#200 (comment)
.

Yah, I think it's definitely dependent on the use case. Personally, I think click() should handle it because for the case when you actually navigate to another page, it's sort of like the action is "half-complete" (page still in transition) before the next action is triggered.

Plus the next action is almost never going to be what you expect (unless it's a wait()).

We could probably tap into this event: http://electron.atom.io/docs/v0.31.0/api/browser-window/#event-39-will-navigate-39 if we go this route.

Update:

Ended up pushing something up for this: 06eb663

Came up with a solution that I think is pretty solid without using timeouts or anything. Personally, I think this makes a lot more sense:

     var title = yield nightmare
        .goto(fixture('navigation'))
        .click('a')
        .title() // A
        .click('.b')
        .title() // B
        .back()
        .title() // A

Than:

     var title = yield nightmare
        .goto(fixture('navigation'))
        .click('a')
        .wait()
        .title() // A
        .click('.b')
        .wait()
        .title() // B
        .back()
        .wait()
        .title() // A

The nice thing is that it won't wait if the click doesn't actually cause navigation.

👍 i'm cool with that, thanks @matthewmueller!

a bit stuck on getting screenshot to work, but pdf is working and the landing page is ready to go segmentio/nightmarejs.org#1

alrighty.... this is pretty much ready to go! thanks @matthewmueller!

will take another look in the morning, review issues, fix the commit history and release v2.0.0

released :)

I use nightmare for electron and my opinion nightmare for phantomjs was better.

Would it make sense to have 2 projects? nightmare/phantom and proton/electron, with the same api? (note, I'm not part of the dev team, I'm only a user.)

Why not?

@myrubapa gotcha, you can always continue pulling 1.x or fork from that commit. phantomjs had SO many weird issues upstream that we had constant reliability problems with it. we opted for a smaller feature set that worked reliably in our testing.

@myrubapa can you give an example of how phantom was better for you?

In my opinion, electron works much better. I use to get all sorts of node-gyp errors, but I don't get them anymore with the electron release.