gabrielbull / react-router-server Goto Github PK
View Code? Open in Web Editor NEWServer Side Rendering library for React Router v4.
License: MIT License
Server Side Rendering library for React Router v4.
License: MIT License
In my project I have all JavaScript files in a js-Folder so I have publicPath: '/js/'
in my webpack config. But when I use react-router-server
for code splitting it assumes that all modules are located in the top level.
Hey, I like the library a lot, but I have rails as my server bundled by webpack provided by react_on_rails gem, not express. IS there any way you can facilitate that with an example?
Hi @gabrielbull, thank you for creating this library! I am looking to try it in a library which uses the libraries mentioned for 'asynccomponents for code-splitting. I noticed that this library has an export called
` as well.
So, I am curious if you think this library would be compatible alongside those libraries if I don't use the <Module />
component or would the <Module />
component need to replace those libraries? And if replace, I'd love to understand the differences between these set of libraries and <Module />
components from you - pros/cons/tradeoffs?
Thank you!
Hi,
I upgraded from v0.4.0 to v1.1.1. If I try to render a component without @fetchState decorator, the rendering seems to work fine. However, when I wrap even a simple component in @fetchState decorator, calling the function this.props.done doesn't work.
For example -
This works:
import React from 'react';
class ServerRootContainer extends React.PureComponent {
render() {
return <h1>Rendered</h1>
}
}
export default ServerRootContainer;
But this doesn't:
import React from 'react';
import { fetchState } from 'react-router-server';
@fetchState(
state => ({}),
actions => ({ done: actions.done })
)
class ServerRootContainer extends React.PureComponent {
componentWillMount() {
this.props.done({});
}
render() {
return <h1>Rendered</h1>
}
}
export default ServerRootContainer;
I see in your example that you're building the server code as well, is this necessary? I can live without the code splitting.
My .babelrc file:
{
"presets": ["es2015", "stage-0", "react"],
"plugins": [
"transform-decorators-legacy",
"add-module-exports",
["transform-runtime", {
"polyfill": false,
"regenerator": true
}]
]
}
Hi, could you provide an example of how to use your package alongside Redux?
Hi,
How to handle multiple nested actions ??
my code is like this.
var _this = this;
this.props.fetchStateId(this.props.match.params.name,function(err,res){
_this.props.done();
if(res && res.data && res.data.states_id){
_this.props.fetchStateInfo(res.data.states_id,function(err,res){
_this.props.done();
});
}
})
i tried to call multiple done() but not worked. worked first time only.
Since renderToString
could directly return the result
without calling the resolve()
, the return of renderPass
could be never resolved.
Hi
this is awesome project, but it definitely needs redux support.
Is this on the road-map?
Hi, great job with the project!
I'm trying to set up hot reloading with your example project, but without any luck so far. Have you tried getting it running?
Hi, i'm looking forward to use this library for a big project but i'm waiting for the api to stabilise a little bit. According to this ctrlplusb/react-universally#356 , it seems the react router api should now be stable. Is there any plan to upgrade react-router-server to react-router beta ? Many thanks.
I'm getting an endless loop when using the async
option on CommonChunksPlugin.
This config will create a chunk file for common pieces spread throughout split code. If you use the same common components on multiple split pages, it will place the goods in this chunk file.
It seems that the module loading never completes and it goes into an endless loop with modulesLoading
always set to 1. This can be seen by making the following changes to react-router-server-complex-example
:
diff --git a/src/components/About.jsx b/src/components/About.jsx
index d7bae53..a1a902b 100644
--- a/src/components/About.jsx
+++ b/src/components/About.jsx
@@ -1,4 +1,7 @@
import * as React from 'react';
+import hello from './Common';
+
+hello()
const Component = (props) => (
<div>
diff --git a/src/components/Common.js b/src/components/Common.js
new file mode 100644
index 0000000..f08ec80
--- /dev/null
+++ b/src/components/Common.js
@@ -0,0 +1,4 @@
+
+export default () => {
+ console.log('hello world!')
+}
diff --git a/src/components/Home.jsx b/src/components/Home.jsx
index 0ad06d4..a3fe950 100644
--- a/src/components/Home.jsx
+++ b/src/components/Home.jsx
@@ -1,6 +1,9 @@
import React, { Component, PropTypes } from 'react';
import { fetchState } from 'react-router-server';
import '../styles/home.css';
+import hello from './Common';
+
+hello()
@fetchState(
state => ({
diff --git a/src/components/Images.jsx b/src/components/Images.jsx
index a97e338..9ca0563 100644
--- a/src/components/Images.jsx
+++ b/src/components/Images.jsx
@@ -1,4 +1,7 @@
import * as React from 'react';
+import hello from './Common';
+
+hello()
const Images = (props) => (
<div>
diff --git a/webpack.config.js b/webpack.config.js
index d367e06..a9bef18 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -2,6 +2,7 @@ import path from 'path';
import StatsPlugin from 'stats-webpack-plugin';
import fs from 'fs';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
+import webpack from 'webpack'
const nodeModules = {};
fs.readdirSync(path.join(__dirname, 'node_modules'))
@@ -47,6 +48,10 @@ const config = server => ({
},
plugins: [
+ new webpack.optimize.CommonsChunkPlugin({
+ async: 'common',
+ minChunks: 2
+ }),
new StatsPlugin('stats.json', {
chunkModules: true,
exclude: [/node_modules/]
Visiting any page that references the common chunk will spin indefinitely.
Hi
this is awesome project and targeted at high performance apps it would be great if it would support preact.
Is this on the road-map?
Hi there !
First of all, thanks for your work !
I got an issue with it though and I was wondering how you would like to solve it.
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the _class component.
The faulty setState is in fact caused by:
https://github.com/gabrielbull/react-router-server/blob/master/src/fetchState.js#L60
I guess we should follow what's in here: https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html
What do you think ?
It looks like the transpile is slightly different when the preset-env picks up that the node environment supports arrow functions. The regular expressions aren't matching properly and things go haywire.
The imports before --
// unminified
function () {
return __webpack_require__.e/* import() */(6).then(__webpack_require__.bind(null, 73));
}
// minified
function (){return l.e(6).then(l.bind(null,73))}
And after --
// unminified
() => __webpack_require__.e/* import() */(6).then(__webpack_require__.bind(null, 73))
// minified
()=>t.e(6).then(t.bind(null,73))
In the unminified case, the first loadFunc still matches but the second does not - meaning we'll keep trying to re-render indefinitely (endless loop). In the minified case, neither matches so there's no endless loop but modules
comes back as empty.
Unless I'm missing something here, I think the regular expression could be greatly simplified by just matching the number inside a parenthetical before .then
... i.e., /\(([0-9]*)\).then/
Then again, there's not a lot of tests describing what the expected values are going for this loadFunc
.... in my limited testing, I wasn't able to get the block commented as system import
or system import minimized
to hit, despite the un-transpiled code looking something like....
<Switch>
{asyncRoute('/', () => System.import('./home'))}
</Switch>
This might be the result of doing stupid things and using react-router
in unexpected ways, but I found a mysterious crash that wound up being max callstack exceeded. You can see this if you take the react-router-server-complex-example
project and make the following changes:
<Switch />
element from ./components/App.jsx
NoMatch
to use async loading like the other routes.If you visit one route, it works fine... but visit another and hit refresh
you'll get a server crash.
On my machine, Windows10 there is no actual error returned from the process.... but you can inspect %ERRORLEVEL%
to see what the exit code is... here is the output from the shell,
D:\Code\react-router-server-complex-example>node_modules\.bin\babel-node.cmd --plugins system-import-transformer -- src/server.js
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
Example site listening on 3000!
^--- server crashes :(
D:\Code\react-router-server-complex-example>echo %ERRORLEVEL%
-1073741571
-1073741571
is a stack overflow exception.
I put a debugger on it in my own project where I found this initially, and I found that context.callback
kept getting called, and went into another renderPass
which ended up calling context.callback
again.
I noticed the then
callback in load was never fired, so add never gets called and the exists check never passes and the modules array kept getting the same module added over & over again.
I encountered this serendipitously while using react-helmet
with a <FormattedMessage/>
from react-intl.... react-helmet
doesn't like this at all, and will throw back an error if it doesn't get a simple string.
Anyway, using react-router-server
there is an unhandled promise rejection logged to the console. I attempted to add a catch
block to the renderToString
call, but this has no effect.
It appears there needs to be a try{}catch{}
wrapping renderToString
here -- https://github.com/gabrielbull/react-router-server/blob/master/src/renderer/renderPass.js#L36-L40 -- and if an error occurs, call into context.reject
with the error.
This might also crop up with things like invariant errors or who knows what else. When it happens, the browser is left hanging with a pending request.
Hello,
Great project! Thanks!
How can we render output with React.renderToStaticMarkup ?
I'm using react-router-server
with redux and that's working like a charm. Thank you very much for this package.
But I always need to write this on my containers:
fetchState(null, actions => actions)(
connect(mapStateToProps, mapDispatchToProps)(Container)
)
Since I'm rehydrating state through redux, if I got it right, the only thing I need is the done
action so I can pass it to my redux actions and fetch data on server properly.
For that case, I was wondering if could be there something like withDone
decorator, which just passes the done
action to props:
import { withDone } from 'react-router-server'
...
withDone(connect(mapStateToProps, mapDispatchToProps)(Container))
I'm working on a higher order component that wraps fetchState
. You can see it here:
The idea here is to load localization values a component needs in addition to any promises that need to be resolved prior to rendering.... I noticed a problem with this approach - I would sometimes get ready
set to true without firing done, and no locale key found
would show up.
(Initially, I tried to fix this by adding some kind of uniqueness to the component, so instead of a generic ready
I actually used the name
of the component as the key for done and for checking. This seemed to work initially, but has a flaw if multiples of the same component are in use - only the first is rendered.... (see this revision))
Anyway, inspecting the props
of the component at the time of componentWillMount I found that I was getting the wrong data context the done
was fired with. I tested this by including the name
of the component with the ready
boolean - and in some cases, the name as completely different than what should have been loading. This results in the component thinking it's already loaded and not going further.
I had a line to test this inside the componentWillMount
if (this.props.isDone && name !== this.props.name) {
console.log('wtf?!')
}
So, I went to randomly digging around the react-router-server
code and I came across this line:
Here's the thing, this.idx
is undefined always here. There is a this.index
property. I tried toggling it to test it out and... everything works properly.
Is this a typo?
https://github.com/gabrielbull/react-router-server#server-side
it should be
renderToString(
<ServerRouter
location={'/current/path/' /* provide the request url */}
context={context}
>
<App/>
</ServerRouter>,
context
).then(html => console.log(html)); // send html
the 2nd parameter 'context' is missing
FYI: codes in example seems fine
I tried using react-router-server
in a project that uses react-intl
. In some components I need to use the intl context that is provided by react-intl
but if I declare contextTypes for that component fetchState doesn't work.
I added console.log statements to the callback of my data fetch method and the callback of renderToString and it seems like the component just ignores that it should fetch data and renders immediately.
Hi @gabrielbull!
Great project. :)
I had similar needs to you in needing code splitting on my react-router v4 routes. I created a library to help with this. I would appreciate it if you could have a look and let me know if there are any issues that I may have overlooked.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.