Current Server-Side-Rendering implementation is bond to Node.js, makes it hard to use in Nashorn (lightweight high-performance JavaScript runtime in Java with a native JVM) or other JavaScript runtime.
Foundations needed by Vue like vm
and fs
modules may be passed into renderer or runner as parameter which implements some interfaces.
Added a note about Nashorn
I would love to see that happen.
I'm trying to use Vue.js with nashorn too.
It will be great if Vue.js SSR added interfaces such a FileSystem or Engine to externalize
some functionalities that are bind to node.js
I've made some research:
path
in all places can be abstracted
currently used path.extname
, path.join
, path.isAbsolute
, path.dirname
fs
in all places can be abstracted too
currently used fs.existsSync
, fs.readFileSync
module
only one usage NativeModule.wrap
According to docs and soruce code this only wrap script code with
(function (exports, require, module, __filename, __dirname) {
// Your module code actually lives in here
});
so this is can be replaced with function if we are not on node.js
resolve
, vm
used in create-bundle-runner.js
This file can be somehow abstracted :) not sure how and what interface could look
stream
, source-map-support
TODO :)
I made small modifications in source code to get rid of stream
and path
my entry:
//import 'core-js/modules/es6.array.find.js';
//import 'core-js/modules/es6.object.assign.js';
//import 'nashorn-polyfill'
//import 'event-loop'
import Vue from './web-runtime-with-compiler'
export { Vue }
export { createRenderer/*, createBundleRenderer*/} from './web-server-renderer'
result sizes:
@wojtask9 suprised to see you go further! Would you mind share us a demo code?
Yes of course. I can share my code. But you must be patient (because of Easter Holiday)
JS part I'll try share tomorrow evening and java part probably on Tuesday.
@wojtask9 Thanks! I will also try to design and implement some helper for Nashorn, to see how it will be going.
@wojtask9 Hey, we're interested in seeing your solution as well. Can you post it somewhere?
yeah. I'm finishing it. have been busy for the last days.
Currently trying to run ssr tests on nashorn to be sure if everything is OK.
Please be patient :)
You can find "my" code here:
https://github.com/wojtask9/vue
packages/vue-server-renderer-nashorn/vue-nashorn.js -> complete JS file with all required dependencies and polyfills for Nashorn.
I tried to do modify Vue sources as less as possible.
People can build Vue for Nashorn typing npm run build:ssr-nashorn
For jasmine tests in Nashorn type npm run test:ssr-nashorn
(on windows you must change path to jjs.exe in package.json)
Currently only renderToString
works.
renderToStream
have some issues with threads but should be resolved soon.
createBundleRenderer
is currently commented because first I must resolve issues with Streams
but on my TODO :)
If you have any questions I'll try answer :)
Ok i fixed streams and other issues.
There is only one left issue that I'm aware of ( read -> everything works)
For big data (like benchmark/ssr/common.js
) renderToString
and renderToStream
doesn't return output.
If I change rows and columns in generateGrid
to 10,10 from 1000, 10 everything is OK.
Not sure where the problem is :/
Another thing that make me wonder is event-loop
. Currently setTimeout is invoked in thread that is different from main-thread
. This is difference between node.js and nashorn.
I'll made implementation that behaves like node.js but currently it is more complicated.
But first I'll focus on issue mentioned above.
Now everything is solved.
MAX_STACK_DEPTH
was too big for nashorn (original 1000 and currently on nashorn 190).
Performance (on the same linux machine)
nashorn full version 1.8.0_121-b13
--- renderToString ---
Complete time: 20982.00ms
--- renderToStream ---
first chunk: 1202.00ms
complete: 28488.00ms
node.js v6.10.0
--- renderToString ---
Complete time: 2164.08ms
--- renderToStream ---
first chunk: 90.15ms
complete: 2005.17ms
so it is rather slow :/ but why?
The result is consistent to what i tried using React. repo
Benchmark using JMH framework shows that typically nashorn version server side render is 1000% slower than Node.js version. I thought of wasting time in create
/destroy
nashorn context.
Since Vue.js use vm
module and React.js not, I expected better performance ssr using Vue.js.
Run SSR in Nashorn is more robust than in Node.js. Thread-control, ability to terminate render at any time, cache across thread.
@wojtask9 how about share your benchmark code to see if something can be optimized?
I honestly think this is simply because V8 produces much better optimized machine code than Nashorn... not much can be done in Vue/React to solve that :/
Nashorn directly map js to JVM bytecode, implementation now may not great enough as V8. I believe things will get better. It's valuable to make Vue.js SSR not bond to a specific JavaScript Runtime. Nashorn (etc. Browser's Service-Worker, Embedded JavaScript Engine)
Define some abstract interface and provide Node.js implementation as default will be great.
@denghongcai yeah, that's probably what we will do in the future - but for now we want to focus on providing a good, stable and performant Node-based SSR solution first.
@denghongcai
benchmarks added (to my fork of Vue.js)
javac NashornVue.java && java NashornVue
or use script ./benchmarks/nashorn/nashorn-benchmark.js
Vue with my packackage doesn't use vm
or any external modules (only bundled process
and utils
but without process
there isn't any difference ).
I think nashorn doesn't optimize recursive calls at beginning and doesn't like huge stacks.
After 5 iterations performance is good (probably JIT goes in).
results (nashorn)
--- renderToString ---
0 Complete time: 13288.00ms
1 Complete time: 9400.00ms
2 Complete time: 8476.00ms
3 Complete time: 6587.00ms
4 Complete time: 6690.00ms
5 Complete time: 2805.00ms
6 Complete time: 2318.00ms
7 Complete time: 5442.00ms
8 Complete time: 2382.00ms
9 Complete time: 2859.00ms
Maybe there is room for improvements in Vue. For example instead of recursion use iterate version?
I removed recursion from next() function (some async test are falling but benchrmarks don't use asyncComponents and currently it's out of my scope). Now StackTraces looks nicer and I see performance improvement (sadly no difference using node.js)
Some results (btw i generate dynamic data on every loop to be sure that nashorn don't optimize whole scripts).
After 5th loop I see results are better than with node.js :)
Not sure if my benchmarks are correct or simply nashorn optimizes code very well.
Loading benchmarks
--- renderToString ---
#0 Complete time: 11637.00ms
#1 Complete time: 7140.00ms
#2 Complete time: 1692.00ms
#3 Complete time: 1419.00ms
#4 Complete time: 1481.00ms
#5 Complete time: 781.00ms
#6 Complete time: 889.00ms
#7 Complete time: 937.00ms
#8 Complete time: 556.00ms
#9 Complete time: 323.00ms
#8 Complete time: 654.00ms
#9 Complete time: 1021.00ms
#10 Complete time: 604.00ms
#11 Complete time: 576.00ms
#12 Complete time: 554.00ms
#13 Complete time: 1119.00ms
#14 Complete time: 572.00ms
#15 Complete time: 561.00ms
#16 Complete time: 630.00ms
#17 Complete time: 1083.00ms
#18 Complete time: 500.00ms
#19 Complete time: 470.00ms
#20 Complete time: 519.00ms
#21 Complete time: 1330.00ms
#22 Complete time: 455.00ms
#23 Complete time: 457.00ms
#24 Complete time: 524.00ms
#25 Complete time: 444.00ms
#26 Complete time: 507.00ms
#27 Complete time: 446.00ms
#28 Complete time: 491.00ms
#29 Complete time: 535.00ms
#30 Complete time: 474.00ms
#31 Complete time: 454.00ms
#32 Complete time: 593.00ms
#33 Complete time: 284.00ms
#34 Complete time: 249.00ms
#35 Complete time: 315.00ms
#36 Complete time: 272.00ms
#37 Complete time: 287.00ms
#38 Complete time: 269.00ms
#39 Complete time: 292.00ms
@wojtask9 I can't find your optimized code in your repo...
I just get a hint that you're definitely from alibaba. hahah
@denghongcai
I forgot about your last comment. I'll push my changes probably next weekend because currently I'm very busy.
I have also other small improvements (bundle size reduction), working Buffers/Streams with java API and working on bundleRenderer
in nashorn
FYI: in 2.4 we already shipped a pure js build of vue-server-renderer
, but we haven't announced it yet. It only supports the base renderer, but is decoupled from Node.js APIs. Feel free to try integrating it in other contexts.
@yyx990803,
Given your comment above, if I were to write something simple like this:
const renderer = require('vue-server-renderer').createRenderer();
and run it through webpack, I shouldn't be getting messages like:
Module not found: Error: Can't resolve 'fs'
, correct?
@sowhatdoido fs
a native Node module. You can't just webpack it. Use vue-server-renderer/basic
instead.
@yyx990803 Ah! Sorry, I thought when you said the base renderer, you meant createRenderer
vs createBundleRenderer
. Thanks for your help!
Most helpful comment
FYI: in 2.4 we already shipped a pure js build of
vue-server-renderer
, but we haven't announced it yet. It only supports the base renderer, but is decoupled from Node.js APIs. Feel free to try integrating it in other contexts.