react-simple-universal
react-simple-universal copied to clipboard
Examples Folder
First of all this is a great boilerplate, one of the best I found in terms of simplicity. However since I'm pretty new with all these modern JS frameworks I find a bit confusing having an examples folder because its running its own server (devServer.js) and is not using a layout like in the root folder (render-layout.js)
Wouldn't it be easier that the examples use the same files that the app located in root? Or maybe not having an example folder at all and adding examples as 'tags' in the repository branch instead.
What we do in the examples
folder is requiring the react-simple-universal
module itself, so devServer.js
will be used, although we don't explicitly import it at the top. We do this so you can just git clone
this repository and run the example.
You can even copy the example if you want to use it as a starting point in your next project.
I can see that now. DevServer is like a wrapper for react-simple-universal boilerplate. What caused the confusion originally is that I modified render-layout.js and then restart the app but it didn't change. Even I checked in dist folder that the layout file was modified correctly with the changes, but somehow when I go to localhost:3000 I see the old layout.
Did you use the booklist example?
Yes, didn't have time to check the code in depth so maybe is just me making a silly mistake. I will check tomorrow.
@enbits In #21 I've added the ability to pass your own layout to render. As default we use render-layout.js
, but now you can pass your own layout with extra scripts etc to the server.
Example:
const createLayout = ({ rootMarkup, initialState }) => {
return `
<!doctype html>
<html>
<head>
<title>My really cool React App!</title>
<script src="./my/script.js"></script>
</head>
<body>
<div id='root'>${rootMarkup}</div>
<script>
window.BOOTSTRAP_CLIENT_STATE = ${JSON.stringify(initialState)}
</script>
<script src="/static/index.js"></script>
</body>
</html>
`;
};
universal({ routes, reducers, app: expressDevServer(config), layout: createLayout });
I'm not sure yet if this will be a good solution, because the code below always have to be present in your layout to be able to render everything properly.
<div id='root'>${rootMarkup}</div>
<script>
window.BOOTSTRAP_CLIENT_STATE = ${JSON.stringify(initialState)}
</script>
<script src="/static/index.js"></script>
Maybe just two functions to add code in the head
and below the body as footer
will be better.
For example:
const header = `
<link rel="stylesheet" href="my/styles.css">
<script src="my/script.js"></script>
`;
const footer = `
<script src="my/other-script.js"></script>
`;
const includes = { header, footer };
universal({ routes, reducers, app: expressDevServer(config), includes });
What do guys think of this API? Other suggestions?
cc @liamhubers @jackfranklin
I don't like the idea of allowing a header
and footer
, I'd rather give full control as you have with the layout: createLayout
option.
Potentially you could provide a function to provide the boilerplate:
function boilerplate(rootMarkup) {
return `
<div id='root'>${rootMarkup}</div>
<script>
window.BOOTSTRAP_CLIENT_STATE = ${JSON.stringify(initialState)}
</script>
<script src="/static/index.js"></script>
`;
}
So it's easier for people making custom layouts to do this. Also then if you need to change what is required in the template you can update the above function and you don't suddenly get loads of broken usages. WDYT?
It's indeed better to give full control, but there are some things that are currently not configurable like the /static/index.js
part, the window variable name (BOOTSTRAP_CLIENT_STATE
) and the id of the root div.
So if we want to give full control I guess we should be able to pass some kind of config or options object to make sure things don't break or don't work like they should. Right?
Can't we give "full control" with the exception of the bit of boilerplate above?
Else I agree a full config option is the way to go but that feels a bit excessive at the moment perhaps?
Well then we must document that the root always need to have an id of root
, the window variable name has to be BOOTSTRAP_CLIENT_STATE
and the script must be /static/index.js
. If not, things won't work.