Make app SSR aware

This commit is contained in:
Amit Jakubowicz 2019-08-06 10:05:35 +02:00
parent 06e8b0c2b9
commit 6b69090789
10 changed files with 64 additions and 26 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ yarn-error.log
.DS_Store
lib
.env
bin

View File

@ -9,10 +9,7 @@ RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update
RUN apt-get install -y nodejs yarn
# Node
RUN apt-get install -y nodejs
RUN apt-get install -y nodejs yarn nginx
# application
RUN mkdir /opt/client
@ -21,8 +18,12 @@ COPY ./dist ./opt/client
COPY ./package.json /opt/client
COPY ./yarn.lock /opt/client
RUN (cd /opt/client; yarn)
COPY ./client.nginx /etc/nginx/sites-available/default
RUN mkdir /var/www/qpa
COPY ./bin /var/www/qpa
RUN (cd /opt/client; yarn install --production)
WORKDIR /opt/client
CMD node SSR/index.js
ENTRYPOINT service nginx start; node SSR/index.js

18
client.nginx Normal file
View File

@ -0,0 +1,18 @@
server {
listen 8080 default_server;
listen [::]:8080 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location ~* \.(js|jpg|png|css)$ {
root /var/www/qpa;
}
location / {
proxy_pass http://localhost:5000/;
try_files $uri $uri/ =404;
}
}

View File

@ -5,6 +5,7 @@
"license": "private",
"private": true,
"scripts": {
"build": "yarn client-build; yarn ssr-build",
"client-build": "webpack --config ./webpack.config.ts",
"ssr-build": "tsc; cp src/SSR/*.mustache dist/SSR/",
"start": "NODE_ENV=development webpack-dev-server --config ./webpack.config.ts --hot --progress",

View File

@ -1,6 +1,7 @@
import styled from "@emotion/styled"
import * as React from "react"
import { RouteComponentProps, withRouter } from "react-router"
import {useAppContext} from "../Context/AppContext";
interface RouteParams {
hash: string
@ -10,21 +11,24 @@ interface Props extends RouteComponentProps<{ hash: string }> {}
const InitializeSession = (props: Props) => {
const [responseCode, setResponseCode] = React.useState(0)
const [loading, setLoading] = React.useState(true)
React.useEffect(() => {
fetch(`/api/init-session`, {
method: "post",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ hash: props.match.params.hash }),
}).then((res) => {
setResponseCode(res.status)
setLoading(false)
if (res.status === 200) {
props.history.replace("/my-events")
}
const { isSSR } = useAppContext()
if (!isSSR) {
React.useEffect(() => {
fetch(`/api/init-session`, {
method: "post",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ hash: props.match.params.hash }),
}).then((res) => {
setResponseCode(res.status)
setLoading(false)
if (res.status === 200) {
props.history.replace("/my-events")
}
})
})
})
}
return (
<Root>

View File

@ -1,17 +1,27 @@
import * as React from "react"
import MeQuery, { UserData } from "./MeQuery"
import App from "../App";
interface IAppContext {
me: UserData
isSSR: boolean
}
const { Provider, Consumer } = React.createContext<IAppContext>({ me: null })
interface Props {
isSSR: boolean
children: React.ReactChild
}
const AppContextProvider = (props) => (
const AppContext = React.createContext<IAppContext>({ me: null, isSSR: false })
const { Provider, Consumer } = AppContext
const AppContextProvider = (props: Props) => (
<MeQuery>
{({ data, loading, error }) => {
return (
<Provider value={data}>
<Provider value={{
me: data.me,
isSSR: props.isSSR,
}}>
{
props.children
}
@ -21,4 +31,5 @@ const AppContextProvider = (props) => (
</MeQuery>
)
export const useAppContext = () => React.useContext<IAppContext>(AppContext)
export { AppContextProvider, Consumer as AppContext }

View File

@ -24,7 +24,7 @@ const graphqlClient = new ApolloClient({
const Providers = (props: Props) => (
<ApolloProvider client={graphqlClient}>
<AppContextProvider>
<AppContextProvider isSSR={false}>
<Router>
{ props.children }
</Router>

View File

@ -8,5 +8,5 @@ ReactDOM.render(
<Providers>
<App />
</Providers>,
container
container,
)

View File

@ -13,7 +13,7 @@ interface Props {
const SSRProviders = (props: Props) => (
<ApolloProvider client={props.graphqlClient}>
<AppContextProvider>
<AppContextProvider isSSR={true}>
<StaticRouter location={props.location}>
{ props.children }
</StaticRouter>

View File

@ -16,6 +16,8 @@ import App from "../App/App"
import SSRProviders from "./SSRProviders"
export const httpSSRHandler = async (req: Request, res: Response) => {
res.status(200)
console.log("Cookie header", req.header("Cookie"))
const httpLink = new HttpLink({
uri: process.env.API_URL || "http://localhost:4000/graphql",
fetch,