Skip to content
This repository was archived by the owner on Sep 28, 2025. It is now read-only.

Commit 62773a0

Browse files
committed
Allow using custom nodemon config for dev mode
Addresses #8
1 parent 7b5cb9d commit 62773a0

File tree

6 files changed

+263
-4
lines changed

6 files changed

+263
-4
lines changed

docs/Advanced.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,15 @@ exports.compose = ({ schemaComposer, typedef }) => {
114114
Property `model` your `resolvers` function will receive here is a [Mongoose model](https://mongoosejs.com/docs/models.html) generated from schema definition in current file.
115115

116116
Property `schemaComposer` passed to `compose` function is instance of [SchemaCompose from graphql-compose](https://graphql-compose.github.io/docs/api/SchemaComposer.html), while `typedef` is a [graphql-compose type](https://graphql-compose.github.io/docs/basics/understanding-types.html) generated from Mongoose model created in current file.
117+
118+
## Ignoring files and folders to prevent reloads during development mode
119+
120+
By default Graffiti will use [nodemon](https://github.com/remy/nodemon) in development mode to auto-restart server on file changes.
121+
This can lead to undesirable reloads (e.g. when working with Next.js).
122+
To change that behaviour you can create a custom `nodemon.json` config that ignores specific files or folders (e.g. `pages/` in case of Next.js):
123+
124+
```json
125+
{
126+
"ignore": [".git", "node_modules", "pages/**/*"]
127+
}
128+
```

docs/TutorialNotesNext.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,219 @@
11
# Build a simple note-taking app with Graffiti and Next
2+
3+
## Prerequisites
4+
5+
- Node.js v14
6+
- MongoDB:
7+
- install it locally
8+
- start via docker (e.g. `docker run --name mongodb -p 27017:27017 -d mongo`)
9+
10+
## Step 1: Create new project
11+
12+
```sh
13+
mkdir graffiti-notes && cd graffiti-notes
14+
npm init -y
15+
```
16+
17+
## Step 2: Install Graffiti
18+
19+
```sh
20+
npm install graffiti
21+
```
22+
23+
## Step 3: Add Graffiti start and dev scripts to package.json
24+
25+
```json
26+
{
27+
// rest of your package.json
28+
"scripts": {
29+
"start": "NODE_ENV=production graffiti",
30+
"develop": "graffiti dev"
31+
}
32+
// rest of your package.json
33+
}
34+
```
35+
36+
## Step 4: Define notes schema
37+
38+
First, create new schema folder:
39+
40+
```sh
41+
mkdir schema
42+
```
43+
44+
Then, create new `note.js` file in it and describe our notes schema:
45+
46+
```js
47+
// schema/note.js
48+
exports.schema = {
49+
name: String,
50+
body: String,
51+
};
52+
```
53+
54+
## Step 5: Test in playground
55+
56+
Make sure your MongoDB is running.
57+
Once it is - execute `npm run develop` to start your Graffiti app in dev mode
58+
and navigate to [http://localhost:3000/playground](http://localhost:3000/playground).
59+
60+
Playground should now allow you to execute variety of queries and mutations for notes.
61+
62+
## Step 6: Add Next.js plugin
63+
64+
First, install the plugin using npm:
65+
66+
```sh
67+
npm install graffiti-plugin-next
68+
```
69+
70+
Then, create new file `graffiti.config.js` and add the following:
71+
72+
```js
73+
const nextPlugin = require('graffiti-plugin-next');
74+
75+
module.exports = {
76+
mongoUrl: 'mongodb://localhost/graffiti',
77+
plugins: [nextPlugin()],
78+
};
79+
```
80+
81+
## Step 7: Add new page
82+
83+
First, create `pages/` folder for Next.js to use:
84+
85+
```sh
86+
mkdir pages
87+
```
88+
89+
Then, create new `index.js` file and create your page using React (as you normally would using Next.js):
90+
91+
```js
92+
export default () => <h1>Hello Graffiti + Next.js!</h1>;
93+
```
94+
95+
## Step 8: Test in browser
96+
97+
Execute `npm run develop` to start your Graffiti app in dev mode
98+
and navigate to [http://localhost:3000/](http://localhost:3000/).
99+
100+
You should see your newly created React page.
101+
102+
## Step 9: Add notes creation and browsing
103+
104+
First, let's add simplest GraphQL client for us to use - we'll use [graphql-request](https://github.com/prisma-labs/graphql-request):
105+
106+
```sh
107+
npm install graphql-request graphql
108+
```
109+
110+
Edit your `pages/index.js` and create new form for notes creation and new list of current notes, e.g.:
111+
112+
```js
113+
import { gql, GraphQLClient } from 'graphql-request';
114+
import { useState } from 'react';
115+
116+
// create a GraphQL client instance to send requests
117+
const client = new GraphQLClient('http://localhost:3000/graphql', {
118+
headers: {},
119+
});
120+
121+
// define notes query
122+
const notesQuery = gql`
123+
{
124+
noteMany {
125+
_id
126+
name
127+
body
128+
}
129+
}
130+
`;
131+
132+
// define create note mutation
133+
const createNoteQuery = gql`
134+
mutation AddNote($name: String!, $body: String!) {
135+
noteCreate(record: { name: $name, body: $body }) {
136+
record {
137+
_id
138+
name
139+
body
140+
}
141+
}
142+
}
143+
`;
144+
145+
// define simple create note function that returns new note
146+
const createNote = async ({ name, body }) => {
147+
const variables = {
148+
name,
149+
body,
150+
};
151+
const data = await client.request(createNoteQuery, variables);
152+
return data?.noteCreate?.record;
153+
};
154+
155+
// define our page
156+
export default ({ notes }) => {
157+
const [allNotes, setAllNotes] = useState(notes);
158+
const [name, setName] = useState();
159+
const [body, setBody] = useState();
160+
161+
// add button handler
162+
const handleAdd = async () => {
163+
const newNote = await createNote({ name, body });
164+
if (newNote) {
165+
// add new note to render list
166+
setAllNotes(allNotes.concat(newNote));
167+
}
168+
// reset old values
169+
setName('');
170+
setBody('');
171+
};
172+
173+
return (
174+
<div>
175+
<div style={{ marginBottom: 20 }}>
176+
<div>
177+
<input
178+
type="text"
179+
placeholder="Note name"
180+
value={name}
181+
onChange={(e) => setName(e.target.value)}
182+
/>
183+
</div>
184+
<div>
185+
<textarea
186+
placeholder="Note body"
187+
value={body}
188+
onChange={(e) => setBody(e.target.value)}
189+
/>
190+
</div>
191+
<div>
192+
<button onClick={handleAdd}>Add note</button>
193+
</div>
194+
</div>
195+
{allNotes.map((note) => (
196+
<div key={note._id} style={{ marginBottom: 10 }}>
197+
<strong>{note.name}</strong>
198+
<p>{note.body}</p>
199+
</div>
200+
))}
201+
</div>
202+
);
203+
};
204+
205+
// define server-side props that load initial list of notes
206+
export async function getServerSideProps(context) {
207+
const data = await client.request(notesQuery);
208+
return {
209+
props: { notes: data?.noteMany ?? [] }, // will be passed to the page component as props
210+
};
211+
}
212+
```
213+
214+
## Step 10: Try it out!
215+
216+
Execute `npm run develop` to start your Graffiti app in dev mode
217+
and navigate to [http://localhost:3000/](http://localhost:3000/).
218+
219+
You should see your newly created page with form that should create notes and add them to page.

packages/graffiti-plugin-next/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ module.exports = {
2121
};
2222
```
2323

24+
## Development mode
25+
26+
By default Graffiti will use [nodemon](https://github.com/remy/nodemon) in development mode to auto-restart server on file changes.
27+
This makes Next.js development experience suboptimal. If you wish to use hot reload provided by Next.js, you'll need to create custom `nodemon.json` config that ignores changes to `pages/` folder, e.g.:
28+
29+
```json
30+
{
31+
"ignore": [".git", "node_modules", "pages/**/*"]
32+
}
33+
```
34+
2435
## Building for production
2536

2637
To create Next.js build for production you can either:

packages/graffiti/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.8.0 / 2020-09-10
2+
3+
- Allow providing custom nodemon config
4+
15
# 0.7.0 / 2020-09-08
26

37
- Add plugins support

packages/graffiti/bin/graffiti.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,25 @@ const main = () => {
2121
// get current workdir
2222
const currentPath = process.cwd();
2323

24-
// start nodemon
25-
nodemon({
24+
// create default nodemon config
25+
let nodemonConfig = {
2626
script: entrypointPath,
27+
ignore: ['.git', 'node_modules'],
2728
ext: 'js',
28-
});
29+
};
30+
// try to read local nodemon config if present
31+
const fs = require('fs');
32+
const localConfigPath = path.join(currentPath, 'nodemon.json');
33+
// if it is present - merge it with default config
34+
if (fs.existsSync(localConfigPath)) {
35+
nodemonConfig = {
36+
...nodemonConfig,
37+
...require(localConfigPath),
38+
};
39+
}
40+
41+
// start nodemon
42+
nodemon(nodemonConfig);
2943

3044
// report changes
3145
nodemon

packages/graffiti/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graffiti",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"description": "Minimalistic GraphQL framework",
55
"repository": "yamalight/graffiti",
66
"bugs": "https://github.com/yamalight/graffiti/issues",

0 commit comments

Comments
 (0)