Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add nextjs-8-serverless sample app (#1640)
- Loading branch information
1 parent
d3b9948
commit 5fc2df2
Showing
15 changed files
with
6,920 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
|
||
### Node ### | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# TypeScript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
.env.test | ||
|
||
# parcel-bundler cache (https://parceljs.org/) | ||
.cache | ||
|
||
# next.js build output | ||
.next | ||
|
||
# nuxt.js build output | ||
.nuxt | ||
|
||
# vuepress build output | ||
.vuepress/dist | ||
|
||
# Serverless directories | ||
.serverless/ | ||
|
||
# FuseBox cache | ||
.fusebox/ | ||
|
||
# DynamoDB Local files | ||
.dynamodb/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# nextjs-8-serverless | ||
|
||
> Boilerplate to get started with Next.js 8 Serverless Mode, Hasura GraphQL engine as CMS and postgres as database. | ||
# Tutorial | ||
|
||
- Deploy Postgres and GraphQL Engine on Heroku: | ||
|
||
[![Deploy to heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku) | ||
|
||
Please checkout our [docs](https://docs.hasura.io/1.0/graphql/manual/deployment/index.html) for other deployment methods | ||
|
||
- Get the Heroku app URL (say `my-app.herokuapp.com`) | ||
|
||
- Create `author` table: | ||
|
||
Open Hasura console: visit https://my-app.herokuapp.com on a browser | ||
Navigate to `Data` section in the top nav bar and create a table as follows: | ||
|
||
![Create author table](../gatsby-postgres-graphql/assets/add_table.jpg) | ||
|
||
- Insert sample data into `author` table: | ||
|
||
![Insert data into author table](../gatsby-postgres-graphql/assets/insert_data.jpg) | ||
|
||
Verify if the row is inserted successfully | ||
|
||
![Insert data into author table](../gatsby-postgres-graphql/assets/browse_rows.jpg) | ||
|
||
- Clone this repo: | ||
```bash | ||
git clone https://github.com/hasura/graphql-engine | ||
cd graphql-engine/community/sample-apps/nextjs-8-serverless | ||
``` | ||
|
||
- Install npm modules: | ||
```bash | ||
npm install | ||
``` | ||
|
||
- Open `lib/init-apollo.js` and configure Hasura's GraphQL Endpoint as follows: | ||
|
||
```js | ||
|
||
function create (initialState) { | ||
return new ApolloClient({ | ||
connectToDevTools: process.browser, | ||
ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once) | ||
link: new HttpLink({ | ||
uri: 'https://myapp.herokuapp.com/v1alpha1/graphql', // Server URL (must be absolute) | ||
credentials: 'same-origin' // Additional fetch() options like `credentials` or `headers` | ||
}), | ||
cache: new InMemoryCache().restore(initialState || {}) | ||
}) | ||
} | ||
|
||
``` | ||
Replace the `uri` with your own Hasura GraphQL endpoint. | ||
|
||
In this example, we integrate Apollo with Next by wrapping our *pages/_app.js* inside a higher-order component HOC. Using the HOC pattern we're able to pass down a central store of query result data created by Apollo into our React component hierarchy defined inside each page of our Next application. | ||
|
||
On initial page load, while on the server and inside `getInitialProps`, we invoke the Apollo method, [`getDataFromTree`](https://www.apollographql.com/docs/react/features/server-side-rendering.html#getDataFromTree). This method returns a promise; at the point in which the promise resolves, our Apollo Client store is completely initialized. | ||
|
||
- We have defined the graphql query in `components/AuthorList.js`. | ||
|
||
```graphql | ||
|
||
query author($skip: Int!) { | ||
author(offset: $skip, limit: 5) { | ||
id | ||
name | ||
} | ||
author_aggregate { | ||
aggregate { | ||
count | ||
} | ||
} | ||
} | ||
|
||
``` | ||
|
||
- Run the app: | ||
```bash | ||
npm run dev | ||
``` | ||
- Test the app | ||
Visit [http://localhost:3000](http://localhost:3000) to view the app | ||
|
||
# Serverless Mode | ||
|
||
With Next.js 8, each page in the `pages` directory becomes a serverless lambda. To enable `serverless` mode, we add the `serverless` build `target` in `next.config.js`. | ||
|
||
``` | ||
module.exports = { | ||
target: "serverless", | ||
}; | ||
``` | ||
|
||
That's it! Now build the serverless app by running the following command: | ||
|
||
``` | ||
npm run build | ||
``` | ||
|
||
In the `.next` folder, you will see a `serverless` folder generated after the build. Inside that there is a `pages` folder, which will have outputs of lambda per page. | ||
|
||
``` | ||
pages/index.js => .next/serverless/pages/index.js | ||
pages/about.js => .next/serverless/pages/about.js | ||
``` | ||
|
||
# Deploy to now.sh | ||
|
||
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)): | ||
|
||
```bash | ||
npm install -g now | ||
now | ||
``` | ||
Note: Older versions of now-cli doesn't support serverless mode. | ||
Once the deployment is successful, you will be able to navigate to pages `/` and `/about`, with each one internally being a lambda function which `now` manages. | ||
|
||
|
||
|
||
|
42 changes: 42 additions & 0 deletions
42
community/sample-apps/nextjs-8-serverless/components/App.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
export default ({ children }) => ( | ||
<main> | ||
{children} | ||
<style jsx global>{` | ||
* { | ||
font-family: Menlo, Monaco, 'Lucida Console', 'Liberation Mono', | ||
'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', | ||
monospace, serif; | ||
} | ||
body { | ||
margin: 0; | ||
padding: 25px 50px; | ||
} | ||
a { | ||
color: #22bad9; | ||
} | ||
p { | ||
font-size: 14px; | ||
line-height: 24px; | ||
} | ||
article { | ||
margin: 0 auto; | ||
max-width: 650px; | ||
} | ||
button { | ||
align-items: center; | ||
background-color: #22bad9; | ||
border: 0; | ||
color: white; | ||
display: flex; | ||
padding: 5px 7px; | ||
} | ||
button:active { | ||
background-color: #1b9db7; | ||
transition: background-color 0.3s; | ||
} | ||
button:focus { | ||
outline: none; | ||
} | ||
`}</style> | ||
</main> | ||
) |
109 changes: 109 additions & 0 deletions
109
community/sample-apps/nextjs-8-serverless/components/AuthorList.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { Query } from 'react-apollo' | ||
import gql from 'graphql-tag' | ||
|
||
export const authorQuery = gql` | ||
query author($skip: Int!) { | ||
author(offset: $skip, limit: 5) { | ||
id | ||
name | ||
} | ||
author_aggregate { | ||
aggregate { | ||
count | ||
} | ||
} | ||
} | ||
` | ||
export const authorQueryVars = { | ||
skip: 0, | ||
} | ||
|
||
export default function AuthorList () { | ||
return ( | ||
<Query query={authorQuery} variables={authorQueryVars}> | ||
{({ loading, error, data: { author, author_aggregate }, fetchMore }) => { | ||
if (error) return <ErrorMessage message='Error loading authors.' /> | ||
if (loading) return <div>Loading</div> | ||
|
||
const areMoreAuthors = author.length < author_aggregate.aggregate.count | ||
return ( | ||
<section> | ||
<ul> | ||
{author.map((a, index) => ( | ||
<li key={a.id}> | ||
<div> | ||
<span>{index + 1}. </span> | ||
<a>{a.name}</a> | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
{areMoreAuthors ? ( | ||
<button onClick={() => loadMoreAuthors(author, fetchMore)}> | ||
{' '} | ||
{loading ? 'Loading...' : 'Show More'}{' '} | ||
</button> | ||
) : ( | ||
'' | ||
)} | ||
<style jsx>{` | ||
section { | ||
padding-bottom: 20px; | ||
} | ||
li { | ||
display: block; | ||
margin-bottom: 10px; | ||
} | ||
div { | ||
align-items: center; | ||
display: flex; | ||
} | ||
a { | ||
font-size: 14px; | ||
margin-right: 10px; | ||
text-decoration: none; | ||
padding-bottom: 0; | ||
border: 0; | ||
} | ||
span { | ||
font-size: 14px; | ||
margin-right: 5px; | ||
} | ||
ul { | ||
margin: 0; | ||
padding: 0; | ||
} | ||
button:before { | ||
align-self: center; | ||
border-style: solid; | ||
border-width: 6px 4px 0 4px; | ||
border-color: #ffffff transparent transparent transparent; | ||
content: ''; | ||
height: 0; | ||
margin-right: 5px; | ||
width: 0; | ||
} | ||
`}</style> | ||
</section> | ||
) | ||
}} | ||
</Query> | ||
) | ||
} | ||
|
||
function loadMoreAuthors (author, fetchMore) { | ||
fetchMore({ | ||
variables: { | ||
skip: author.length | ||
}, | ||
updateQuery: (previousResult, { fetchMoreResult }) => { | ||
if (!fetchMoreResult) { | ||
return previousResult | ||
} | ||
return Object.assign({}, previousResult, { | ||
// Append the new results to the old one | ||
author: [...previousResult.author, ...fetchMoreResult.author] | ||
}) | ||
} | ||
}) | ||
} |
13 changes: 13 additions & 0 deletions
13
community/sample-apps/nextjs-8-serverless/components/ErrorMessage.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export default ({ message }) => ( | ||
<aside> | ||
{message} | ||
<style jsx>{` | ||
aside { | ||
padding: 1.5em; | ||
font-size: 14px; | ||
color: white; | ||
background-color: red; | ||
} | ||
`}</style> | ||
</aside> | ||
) |
Oops, something went wrong.