Skip to content

Server-Side Rendering with PHP V8Js (without node.js) #4101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lerouxju opened this issue Nov 3, 2016 · 17 comments
Closed

Server-Side Rendering with PHP V8Js (without node.js) #4101

lerouxju opened this issue Nov 3, 2016 · 17 comments

Comments

@lerouxju
Copy link

lerouxju commented Nov 3, 2016

Feature description

PHP V8Js allows to execute JS server side. It is some sort of alternative to node.js.

Currently it is not possible to execute Vue.js this way. It complains that "setTimeout" & "document" are not defined.

As Vue.js is running fine server side with node.js it should be possible to run it with PHP V8Js.

Code sample

`<?php

$vueSource = file_get_contents('https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js');
$v8 = new V8Js();
$result = $v8->executeString($vueSource);
?>`

Result

V8Js::executeString():5628: ReferenceError: document is not defined"

@yyx990803
Copy link
Member

The file you are importing is the standalone build that assumes browser environment. But regardless, I don't think it's possible (or involves non-trivial effort) to do Vue SSR in PHP V8js because:

  1. The vue-server-renderer package has other Node package dependencies, e.g. he and de-indent. This can be solved by bundling the whole package and these dependencies into one file;
  2. Some features rely on Node.js native modules like vm and stream. So even if you can get normal SSR working, you wouldn't be able to use stream mode or the bundleRenderer.

Basically, this is not something we are planning to work on, but we are definitely open to community contributions if anyone wants to make it work.

@bratao
Copy link

bratao commented Dec 5, 2016

This is also a major decision blocker between React and Vuejs. The react have a v8js plugin and works perfectly.
I can allocate sometime next week to look if I can get any workaround. But if anyone have any progress in this use case, please inform here in this topic

@nirazul
Copy link

nirazul commented Dec 5, 2016

Sever-side rendering without a node dependency would be a huge improvement for us as our backend heavily depends on a python stack. A V8 plugin would come in very handy.

@7ammer
Copy link

7ammer commented Jan 29, 2017

Has any progress been made in this area? The Laravel community really needs something like this where Vuejs is concerned.

@muthu32
Copy link

muthu32 commented Feb 11, 2017

If vue has to be used with php(Laravel), Then we have to sacrifice SEO for app.
If you need SEO (Serverside Rendering), Then you have to rely on node.js.If v8js is supported in vue, then that will be huge help to laravel community.

@ghost
Copy link

ghost commented Mar 17, 2017

Has any progress been made in this area?

@youssef-lr
Copy link

How cool would it be to have a blade directive @render_vue('my-vue-component', ['prop' => 1]) ?

@rohmanhm
Copy link
Contributor

rohmanhm commented Mar 18, 2017

Maybe you can try this package https://github.com/lukechilds/browser-env if you had document not defined
I'm not sure yet

@rjvim
Copy link

rjvim commented Apr 3, 2017

+1

@martinsotirov
Copy link

We definitely need a workaround for setTimeout and the other missing things in non-Node V8 implementations.

I was trying to render my Vue.js app with some Go-based JS environments the other day and it didn't work for the same reason – setTimeout missing.

@neronmoon
Copy link

+1

@bratao
Copy link

bratao commented Apr 22, 2017

@yyx990803 Could you please revisit this issue ?

@acidjazz
Copy link

acidjazz commented Apr 30, 2017

@yyx990803 would be really awesome to have this! +9001

@posva
Copy link
Member

posva commented Apr 30, 2017

Please, do not spam. The answer below is clear
We are open to community contributions, so if you have something to share, please, do it by commenting here. But do not comment to say +1 or Any updates? or any equivalent phrase
This issue may also be interesting: #5415

@jkoudys
Copy link

jkoudys commented Sep 28, 2017

It looks like (nearly?) all the calls to setTimeout are using it to either defer a function call immediately (so they'll be called next pass in the event loop, ie 4ms), or for transition effects (which would be irrelevant for server side rendering).

A vue solution would be to implement your own stack to push functions to run on the next tick to instead of using setTimeout's stack. Shouldn't be too hard to write, but personally I rather like the pattern of using setTimeout to push await things I don't want blocking me.

This could be solved outside of vue by using an event loop implementation in your V8js. It does support a sleep() function already, which is all you'd really need to create your own loop with setTimeout & setInterval implemented. For it to work with php, ultimately your code will need to resolve at some point (ie resume synchronous execution), so doing events more advanced than that could be tricky (and some may argue, not very valuable).

let timeouts = [];
window.setTimeout = (cb, delay = 0, ...args) => {
  timeouts = timeouts.concat({ cb, args, end: Date.now() + delay });
};

/* require your actual code..., then: */


const endTimeCompare = ({ end: a }, { end: b }) => a - b;
timeouts = timeouts.sort(endTimeCompare);
while (timeouts.length > 0) {
  sleep(0.004);
  const runNow = timeouts.filter(({ end }) => end <= Date.now());
  for (const { cb, args } of runNow) cb(...args);
  timeouts = timeouts.filter(timeout => !runNow.includes(timeout)).sort(endTimeCompare);
}

I'm writing this from bed at midnight, haven't run any of this, am sure there's some es7 I'll need to make less-pretty so it works on older engines, and am very sleepy, but you can get the general idea from this. Please let me know if this idea solves what everyone's looking for here, and I'll make a repo and put this in with something that includes setInterval too.

@sevenecks
Copy link

This may be of interest to those finding this thread in the future: Server-Side Rendering With Laravel and Vue.js 2.5

@ghost
Copy link

ghost commented Apr 9, 2018

@sevenecks Legendary! 🎉 Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests