SSR React with Symfonyfor the Strong of Spirit Workshop

Speed

Theory
Let's talk about having an external renderer.
Add this node renderer into node-renderer.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
var net = require("net");
var fs = require("fs");
var path = require("path");

var bundlePath = "./var/webpack/";
var bundleFileName = "app.js";

var currentArg;

function Handler() {
  this.queue = [];
  this.initialized = false;
}


Handler.prototype.handle = function(connection) {

  var callback = function () {
      connection.setEncoding('utf8');
  
      let data = [];
      let lastChar;
      connection.on('data', (chunk)=> {
          data.push(chunk);
          lastChar = chunk.substr(chunk.length - 1);
  
          if(lastChar === '\0') {
            data = data.join('');
            let result = eval(data.slice(0, -1));
            connection.write(result);
            console.log("Request processed");
            connection.end();
          }
      });
  };
  if (this.initialized) {
    callback();
  } else {
    this.queue.push(callback);
  }
};

Handler.prototype.initialize = function() {
  console.log("Processing " + this.queue.length + " pending requests");
  var callback = this.queue.pop();
  while (callback) {
    callback();
    callback = this.queue.pop();
  }

  this.initialized = true;
};

var handler = new Handler();

process.argv.forEach(val => {
  if (val[0] == "-") {
    currentArg = val.slice(1);
    return;
  }

  if (currentArg == "s") {
    bundleFileName = val;
  }
});

try {
  fs.mkdirSync(bundlePath);
} catch (e) {
  if (e.code != "EEXIST") throw e;
}

require(bundlePath + bundleFileName);
console.log("Loaded server bundle: " + bundlePath + bundleFileName);
handler.initialize();

fs.watchFile(bundlePath + bundleFileName, curr => {
  if (curr && curr.blocks && curr.blocks > 0) {
    if (handler.initialized) {
      console.log(
        "Reloading server bundle must be implemented by restarting the node process!"
      );
      return;
    }

    require(bundlePath + bundleFileName);
    console.log("Loaded server bundle: " + bundlePath + bundleFileName);
    handler.initialize();
  }
});

var unixServer = net.createServer(function(connection) {
  handler.handle(connection);
});

unixServer.listen("var/node.sock");

process.on("SIGINT", () => {
  unixServer.close();
  process.exit();
});
And change the configuration of React Bundle to use it in config/packages/limenius-react.yaml:
1
2
3
4
5
6
7
8
9
limenius_react:
    default_rendering: "both"

    serverside_rendering:
        trace: true
        fail-loud: true
        mode: "external_server"
        server_bundle_path: "%kernel.project_dir%/var/webpack/app.js"
        server_socket_path: "%kernel.project_dir%/var/node.sock"
And run it in a new terminal:
node node-renderer.js
Discuss
Can you notice the difference in speed?
Change from external_server to phpexecjs back and forth and check the debug toolbar of Symfony.
Got lost?
The code up to this point is in the tag 07-speed of the repository https://github.com/Limenius/workshop-symfony-react.git
This means:
git reset HEAD --hard
(To discard your changes)
And then:
git checkout 07-speed