Commit 0ab82a8a authored by Jens's avatar Jens
Browse files

renderine done

parent 9a25a8ca
This diff is collapsed.
...@@ -21,6 +21,7 @@ export interface getAllArticlesQuery { ...@@ -21,6 +21,7 @@ export interface getAllArticlesQuery {
authorByAuthorId: { authorByAuthorId: {
__typename: "Author", __typename: "Author",
id: string, id: string,
name: string,
} | null, } | null,
} | null >, } | null >,
} | null, } | null,
...@@ -39,7 +40,6 @@ export interface getAllAuthorsQuery { ...@@ -39,7 +40,6 @@ export interface getAllAuthorsQuery {
nodeId: string, nodeId: string,
id: string, id: string,
name: string, name: string,
bornIn: string | null,
// Reads and enables pagination through a set of `Article`. // Reads and enables pagination through a set of `Article`.
articlesByAuthorId: { articlesByAuthorId: {
__typename: "ArticlesConnection", __typename: "ArticlesConnection",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"build-server": "webpack --config webpack.server.config.js --progress", "build-server": "webpack --config webpack.server.config.js --progress",
"build-client": "webpack --config webpack.client.config.js --progress", "build-client": "webpack --config webpack.client.config.js --progress",
"start": "node ./dist/server/server.js", "start": "node ./dist/server/server.js",
"introspect-graphql-schema": "./node_modules/.bin/apollo-codegen introspect-schema http://localhost:8080/graphql --output schema.json", "introspect-graphql-schema": "./node_modules/.bin/apollo-codegen introspect-schema http://localhost:8081/graphql --output schema.json",
"generate-graphql-ts": "./node_modules/.bin/apollo-codegen generate **/*.tsx --addTypename --schema schema.json --target typescript --output graphql-types.ts" "generate-graphql-ts": "./node_modules/.bin/apollo-codegen generate **/*.tsx --addTypename --schema schema.json --target typescript --output graphql-types.ts"
}, },
"author": "", "author": "",
...@@ -27,7 +27,10 @@ ...@@ -27,7 +27,10 @@
"postgraphile": "^4.0.0-alpha2.30", "postgraphile": "^4.0.0-alpha2.30",
"react": "^16.2.0", "react": "^16.2.0",
"react-apollo": "^2.0.4", "react-apollo": "^2.0.4",
"react-async-bootstrapper": "^1.1.2",
"react-async-component": "^1.0.2",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-render-image": "^1.1.1",
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"typescript": "^2.6.2", "typescript": "^2.6.2",
"whatwg-fetch": "^2.0.3" "whatwg-fetch": "^2.0.3"
......
...@@ -877,18 +877,6 @@ ...@@ -877,18 +877,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "bornIn",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "articlesByAuthorId", "name": "articlesByAuthorId",
"description": "Reads and enables pagination through a set of `Article`.", "description": "Reads and enables pagination through a set of `Article`.",
...@@ -1150,18 +1138,6 @@ ...@@ -1150,18 +1138,6 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "BORN_IN_ASC",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "BORN_IN_DESC",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "PRIMARY_KEY_ASC", "name": "PRIMARY_KEY_ASC",
"description": null, "description": null,
...@@ -1202,16 +1178,6 @@ ...@@ -1202,16 +1178,6 @@
"ofType": null "ofType": null
}, },
"defaultValue": null "defaultValue": null
},
{
"name": "bornIn",
"description": "Checks for equality with the object’s `bornIn` field.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
} }
], ],
"interfaces": null, "interfaces": null,
...@@ -1867,16 +1833,6 @@ ...@@ -1867,16 +1833,6 @@
} }
}, },
"defaultValue": null "defaultValue": null
},
{
"name": "bornIn",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
} }
], ],
"interfaces": null, "interfaces": null,
...@@ -2268,16 +2224,6 @@ ...@@ -2268,16 +2224,6 @@
"ofType": null "ofType": null
}, },
"defaultValue": null "defaultValue": null
},
{
"name": "bornIn",
"description": null,
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
} }
], ],
"interfaces": null, "interfaces": null,
......
import * as React from 'react' import * as React from 'react'
import {Component} from 'react' import { Component } from 'react'
import {hydrate} from 'react-dom' import { hydrate } from 'react-dom'
import {BrowserRouter as Router} from 'react-router-dom' import { BrowserRouter as Router } from 'react-router-dom'
import { ApolloProvider } from 'react-apollo'; import { ApolloProvider } from 'react-apollo';
import HttpLink from "apollo-link-http"; import HttpLink from "apollo-link-http";
import ApolloClient from "apollo-client"; import ApolloClient from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory"; import { InMemoryCache } from "apollo-cache-inmemory";
import { AsyncComponentProvider, createAsyncContext } from 'react-async-component'
declare let window: { import asyncBootstrapper from 'react-async-bootstrapper'
__APOLLO_STATE__: any
}
const apolloClient = new ApolloClient({
link: new HttpLink({ uri: "/graphql" }),
cache: new InMemoryCache().restore(window.__APOLLO_STATE__)
});
import Routes from '../common/routes' import Routes from '../common/routes'
const reactRoot: HTMLElement = document.getElementById('react-root'); declare let window: {
__APOLLO_STATE__: any,
__ASYNC_STATE__: any
}
declare let module: { declare let module: {
hot: { hot: {
accept: (path: any,fn: ()=>any) => any accept: (path: any, fn: () => any) => any
} }
} }
const apolloClient = new ApolloClient({
link: new HttpLink({ uri: "/graphql" }),
cache: new InMemoryCache().restore(window.__APOLLO_STATE__)
});
const reactRoot: HTMLElement = document.getElementById('react-root');
const render = (Routings: React.ComponentClass) => { const render = (Routings: React.ComponentClass) => {
return ( return (
<ApolloProvider client={apolloClient}> <AsyncComponentProvider rehydrateState={window.__ASYNC_STATE__} >
<Router> <ApolloProvider client={apolloClient}>
<Routings/> <Router>
</Router> <Routings />
</ApolloProvider> </Router>
</ApolloProvider>
</AsyncComponentProvider>
) )
} }
if (module.hot) { if (module.hot) {
module.hot.accept('../common/routes',() => { module.hot.accept('../common/routes', () => {
import('../common/routes').then((module:any) => { import('../common/routes').then((module: any) => {
hydrate(render(module.default),reactRoot) hydrate(render(module.default), reactRoot)
}) })
}) })
} }
hydrate(render(Routes),reactRoot) const App = render(Routes);
\ No newline at end of file asyncBootstrapper(App)
.then(() => hydrate(App, reactRoot));
//delete window.__APOLLO_STATE__;
//delete window.__ASYNC_STATE__;
\ No newline at end of file
...@@ -2,13 +2,13 @@ import * as React from 'react' ...@@ -2,13 +2,13 @@ import * as React from 'react'
import {Component} from 'react' import {Component} from 'react'
import gql from 'graphql-tag'; import gql from 'graphql-tag';
import {getAllArticlesQuery} from '../../../graphql-types' import {getAllArticlesQuery} from '../../../graphql-types'
import { graphql } from 'react-apollo'; import { graphql, QueryProps } from 'react-apollo';
const query = gql` const query = gql`
query getAllArticles { query getAllArticles {
allArticles { allArticles {
totalCount totalCount
nodes { nodes {
nodeId nodeId
id id
title title
...@@ -16,25 +16,40 @@ const query = gql` ...@@ -16,25 +16,40 @@ const query = gql`
content content
authorId authorId
authorByAuthorId { authorByAuthorId {
id id
name
} }
}
} }
} }
}
` `
interface Props { interface Props {
data: getAllArticlesQuery data: QueryProps & getAllArticlesQuery
} }
class AllArticles extends Component<Props> { class AllArticles extends Component<Props> {
render() { render() {
if (this.props.data.loading){
return <div>Loading...</div>
} else if (this.props.data.error){
return <div>Error: {this.props.data.error.message}</div>
}
return ( return (
<div> <ul>
{JSON.stringify(this.props)} {
</div> this.props.data.allArticles.nodes.map(article => (
<div key={article.nodeId}>
<h4>{article.title}</h4>
<p>{article.description}</p>
<div>Written by: {article.authorByAuthorId.name}</div>
</div>
))
}
</ul>
); );
} }
} }
export default graphql<getAllArticlesQuery,{},Props>(query)(AllArticles); export default graphql<getAllArticlesQuery,Props,{}>(query)(AllArticles);
\ No newline at end of file \ No newline at end of file
...@@ -11,7 +11,6 @@ const query = gql` ...@@ -11,7 +11,6 @@ const query = gql`
nodeId nodeId
id id
name name
bornIn
articlesByAuthorId { articlesByAuthorId {
totalCount totalCount
} }
...@@ -21,18 +20,34 @@ const query = gql` ...@@ -21,18 +20,34 @@ const query = gql`
`; `;
interface Props { interface Props {
data: getAllAuthorsQuery data: QueryProps & getAllAuthorsQuery
} }
class AllAuthors extends React.Component<Props> { class AllAuthors extends React.Component<Props> {
render() { render() {
if (this.props.data.loading){
return <div>Loading...</div>
} else if (this.props.data.error){
return <div>Error: {this.props.data.error.message}</div>
}
return ( return (
<div> <div>
<p>{JSON.stringify(this.props)}</p> <h2>Authors</h2>
<ul>
{
this.props.data.allAuthors.nodes.map(author => (
<li key={author.nodeId}>
<div>Name: {author.name}</div>
<div>NumberOfArticles: {author.articlesByAuthorId.totalCount}</div>
</li>
))
}
</ul>
</div> </div>
) )
} }
} }
export default graphql<getAllAuthorsQuery,{},Props>(query)(AllAuthors); export default graphql<getAllAuthorsQuery,Props,{}>(query)(AllAuthors);
\ No newline at end of file \ No newline at end of file
import * as React from 'react';
import { asyncComponent } from 'react-async-component';
export default asyncComponent({
resolve: () => System.import('./allAuthors.tsx')
});
\ No newline at end of file
import * as React from 'react';
import { asyncComponent } from 'react-async-component';
export default asyncComponent({
resolve: () => System.import('./fatComponent.tsx')
});
\ No newline at end of file
This diff is collapsed.
...@@ -17,6 +17,9 @@ class Header extends Component { ...@@ -17,6 +17,9 @@ class Header extends Component {
<li> <li>
<Link to="/articles">Articles</Link> <Link to="/articles">Articles</Link>
</li> </li>
<li>
<Link to="/fatComponent">Fat Component</Link>
</li>
</ul> </ul>
</div> </div>
) )
......
...@@ -4,8 +4,9 @@ import {Route} from 'react-router-dom' ...@@ -4,8 +4,9 @@ import {Route} from 'react-router-dom'
import Header from './components/header' import Header from './components/header'
import Main from './components/home' import Main from './components/home'
import AllAuthors from './components/allAuthors' import AllAuthors from './components/asyncAuthors'
import AllArticles from './components/allArticles' import AllArticles from './components/allArticles'
import FatComponent from './components/asyncFatComponent'
class Routes extends Component { class Routes extends Component {
render(){ render(){
...@@ -14,6 +15,7 @@ class Routes extends Component { ...@@ -14,6 +15,7 @@ class Routes extends Component {
<Route exact path="/" component={Main} /> <Route exact path="/" component={Main} />
<Route exact path="/authors" component={AllAuthors}/> <Route exact path="/authors" component={AllAuthors}/>
<Route exact path="/articles" component={AllArticles}/> <Route exact path="/articles" component={AllArticles}/>
<Route exact path="/fatComponent" component={FatComponent}/>
</div> </div>
} }
} }
......
...@@ -3,7 +3,7 @@ import {postgraphile} from 'postgraphile' ...@@ -3,7 +3,7 @@ import {postgraphile} from 'postgraphile'
import render from './serverRender' import render from './serverRender'
const IS_PRODUCTION: boolean = process.env.NODE_ENV === 'production'; const IS_PRODUCTION: boolean = process.env.NODE_ENV === 'production';
const PORT: number = parseInt(process.env.PORT) || 8080; const PORT: number = parseInt(process.env.PORT) || 8081;
const HOST: string = 'localhost'; const HOST: string = 'localhost';
const server = express(); const server = express();
......
import * as React from "react"; import * as React from "react";
import Routes from '../common/routes'
import ApolloClient from "apollo-client"; import ApolloClient from "apollo-client";
import * as fetch from 'node-fetch' import * as fetch from 'node-fetch'
import { ApolloProvider, renderToStringWithData} from 'react-apollo'; import { ApolloProvider, renderToStringWithData } from 'react-apollo';
import HttpLink from 'apollo-link-http'; import HttpLink from 'apollo-link-http';
import { StaticRouter } from 'react-router'; import { StaticRouter } from 'react-router';
import { InMemoryCache } from "apollo-cache-inmemory"; import { InMemoryCache } from "apollo-cache-inmemory";
import {renderToString} from 'react-dom/server' import { renderToString } from 'react-dom/server';
import { AsyncComponentProvider, createAsyncContext } from 'react-async-component';
import asyncBootstrapper from 'react-async-bootstrapper';
export default function(url: string) : Promise<string> { import Routes from '../common/routes';
export default function (url: string): Promise<string> {
const link = new HttpLink({ const link = new HttpLink({
uri: 'http://localhost:8080/graphql' uri: 'http://localhost:8081/graphql'
}); });
const client = new ApolloClient({ const client = new ApolloClient({
...@@ -20,26 +23,29 @@ export default function(url: string) : Promise<string> { ...@@ -20,26 +23,29 @@ export default function(url: string) : Promise<string> {
cache: new InMemoryCache() cache: new InMemoryCache()
}); });
const context = {}; const routerContext = {};
const asyncContext = createAsyncContext();
const App = ( const App = (
<ApolloProvider client={client}> <AsyncComponentProvider asyncContext={asyncContext} >
<StaticRouter location={url} context={context}> <ApolloProvider client={client}>
<Routes/> <StaticRouter location={url} context={routerContext}>
</StaticRouter> <Routes />
</ApolloProvider> </StaticRouter>
</ApolloProvider>
</AsyncComponentProvider>
); );
console.log(context); return new Promise((resolve: (result: any) => void, reject: (error: any) => void) => {
return new Promise((resolve: (result:any )=> void,reject: (error:any) => void ) => { asyncBootstrapper(App).then(() =>
renderToStringWithData(App)
renderToStringWithData(App) .then((reactHtmlContent) => {
.then((reactHtmlContent) => {
const initialState = JSON.stringify(client.extract()).replace(/</g, '\\u003c'); const asyncState = JSON.stringify(asyncContext.getState());
const initialState = JSON.stringify(client.extract()).replace(/</g, '\\u003c');
resolve(`<!DOCTYPE html> resolve(`<!DOCTYPE html>
<html> <html>
<head> <head>
<link rel="apple-touch-icon" sizes="57x57" href="/icon.png" /> <link rel="apple-touch-icon" sizes="57x57" href="/icon.png" />
...@@ -47,14 +53,15 @@ export default function(url: string) : Promise<string> { ...@@ -47,14 +53,15 @@ export default function(url: string) : Promise<string> {
<body> <body>
<div id="react-root">${reactHtmlContent}</div> <div id="react-root">${reactHtmlContent}</div>
<script>window.__APOLLO_STATE__=${initialState}</script> <script>window.__APOLLO_STATE__=${initialState}</script>
<script>window.__ASYNC_STATE__=${asyncState}</script>
<script type="text/javascript" src="/vendor.js"></script> <script type="text/javascript" src="/vendor.js"></script>
<script type="text/javascript" src="/client.js"></script> <script type="text/javascript" src="/client.js"></script>
</body> </body>
</html>`);