airbnb / hypernova

A service for server-side rendering your JavaScript views
MIT License
5.82k stars 208 forks source link

devMode does not reload the components / invalidate the require cache #87

Closed Inkdpixels closed 6 years ago

Inkdpixels commented 7 years ago

I just tried out the hypernova stack and found that the devMode does not reload the component on each request as documented.

Example

hypernova.js

const hypernova = require('hypernova/server');

hypernova({
  devMode: true,
  port: 3030,
  getComponent: name => require(`./${name}.js`)
});

app.js

const React = require('react');
const {renderReact} = require('hypernova-react');

function App(props) {
  return React.createElement('div', null, `Hello ${props.name}`);
}

module.exports = renderReact('app', App);

server.js

const express = require('express');
const Renderer = require('hypernova-client');
const devModePlugin = require('hypernova-client/plugins/devModePlugin');

const app = express();

const renderer = new Renderer({
  url: 'http://localhost:3030/batch',
  plugins: [
    devModePlugin,
  ],
});

app.get('/', (req, res) => {
  const jobs = {
    app: { name: req.query.name || 'Stranger' }
  };

  renderer.render(jobs).then(html => res.send(html));
});

app.listen(8080, () => console.log('Now listening'));

What happens

When requesting localhost:8080 you will be greeted as configured by Hello Stranger but when changing the returned string of the App, e.g. into Hello foo bar ${props.name} the supernova server still renders the old cached component and returns Hello stranger again.

What should happen

When passing a truthy devMode option to hypernova, the server should invalidate the Node caches on each request.

I also searched for references of devMode in the server code, but haven't found anything except for the cluster setup.

Maybe I just missed something, but to me it seems this functionality isn't implemented or was removed in a recent commit?

tanraya commented 7 years ago

Same question

liang3404814 commented 6 years ago

Modules are cached after the first time they are loaded in node. The documentation states this explicitly:

The simplest getComponent would be to use require. One drawback here is that your components would be cached between requests and thus could leak memory and/or data. Another drawback is that the files would have to exist relative to where this require is being used.

Inkdpixels commented 6 years ago

@liang3404814 Sure but the docs also state that devMode: true disables cluster mode and reloads each component every time it is requested. As I said, maybe I got it all wrong and there is a solution built in (maybe without using require as you stated), but AFAIK devMode is not used besides the cluster setup, so either

  1. The docs need to be updated
  2. The devMode should handle clearing the require cache or provide an example on how to do this properly?

:)

goatslacker commented 6 years ago

Whoops! This is carried over from before this library was open sourced when we had a feature like that. This is no longer useful because you can define your own custom behavior in getComponent and even return a Promise from it if you need to asynchronously fetch the file from somewhere. Hypernova also ships with a VM you can use to load remote code.