Skip to content
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit 89295e8

Browse files
committed
Add support for statically routed SSG pages
Copy pre-rendered pages with SSG to Netlify publish directory and copy SSG page JSON data to _next/data/ directory. See: #7
1 parent 87e4057 commit 89295e8

File tree

14 files changed

+461
-214
lines changed

14 files changed

+461
-214
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Link from 'next/link'
2+
3+
const Show = ({ show }) => (
4+
<div>
5+
<p>
6+
This page uses getStaticProps() to pre-fetch a TV show.
7+
</p>
8+
9+
<hr/>
10+
11+
<h1>Show #{show.id}</h1>
12+
<p>
13+
{show.name}
14+
</p>
15+
16+
<hr/>
17+
18+
<Link href="/">
19+
<a>Go back home</a>
20+
</Link>
21+
</div>
22+
)
23+
24+
export async function getStaticProps(context) {
25+
26+
const res = await fetch(`https://api.tvmaze.com/shows/71`);
27+
const data = await res.json();
28+
29+
return {
30+
props: {
31+
show: data
32+
}
33+
}
34+
}
35+
36+
export default Show

cypress/fixtures/pages/index.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,20 @@ const Index = ({ shows }) => (
8989
</li>
9090
</ul>
9191

92-
<h1>4. Static Pages Stay Static</h1>
92+
<h1>4. getStaticProps? Yes!</h1>
93+
<p>
94+
next-on-netlify supports getStaticProps.
95+
</p>
96+
97+
<ul>
98+
<li>
99+
<Link href="/getStaticProps/static">
100+
<a>getStaticProps/static</a>
101+
</Link>
102+
</li>
103+
</ul>
104+
105+
<h1>5. Static Pages Stay Static</h1>
93106
<p>
94107
next-on-netlify automatically determines which pages are dynamic and
95108
which ones are static.

cypress/integration/default_spec.js

+130-100
Original file line numberDiff line numberDiff line change
@@ -52,151 +52,181 @@ after(() => {
5252
cy.task('clearDeployment')
5353
})
5454

55-
describe('SSR page', () => {
56-
it('loads TV shows', () => {
57-
cy.visit('/')
55+
describe('getInitialProps', () => {
56+
context('with static route', () => {
57+
it('loads TV shows', () => {
58+
cy.visit('/')
5859

59-
cy.get('ul').first().children().should('have.length', 5)
60-
})
60+
cy.get('ul').first().children().should('have.length', 5)
61+
})
6162

62-
it('loads TV shows when SSR-ing', () => {
63-
cy.ssr('/')
63+
it('loads TV shows when SSR-ing', () => {
64+
cy.ssr('/')
6465

65-
cy.get('ul').first().children().should('have.length', 5)
66+
cy.get('ul').first().children().should('have.length', 5)
67+
})
6668
})
67-
})
6869

69-
describe('dynamic SSR page', () => {
70-
it('loads TV show', () => {
71-
cy.visit('/shows/24251')
70+
context('with dynamic route', () => {
71+
it('loads TV show', () => {
72+
cy.visit('/shows/24251')
7273

73-
cy.get('h1').should('contain', 'Show #24251')
74-
cy.get('p').should('contain', 'Animal Science')
75-
})
74+
cy.get('h1').should('contain', 'Show #24251')
75+
cy.get('p').should('contain', 'Animal Science')
76+
})
7677

77-
it('loads TV show when SSR-ing', () => {
78-
cy.ssr('/shows/24251')
78+
it('loads TV show when SSR-ing', () => {
79+
cy.ssr('/shows/24251')
7980

80-
cy.get('h1').should('contain', 'Show #24251')
81-
cy.get('p').should('contain', 'Animal Science')
81+
cy.get('h1').should('contain', 'Show #24251')
82+
cy.get('p').should('contain', 'Animal Science')
83+
})
8284
})
83-
})
8485

85-
describe('dynamic catch-all SSR page', () => {
86-
it('displays all URL parameters, including query string parameters', () => {
87-
cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat')
86+
context('with catch-all route', () => {
87+
it('displays all URL parameters, including query string parameters', () => {
88+
cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat')
8889

89-
// path parameters
90-
cy.get('p').should('contain', '[0]: 94')
91-
cy.get('p').should('contain', '[1]: this-is-all')
92-
cy.get('p').should('contain', '[2]: being')
93-
cy.get('p').should('contain', '[3]: captured')
94-
cy.get('p').should('contain', '[4]: yay')
90+
// path parameters
91+
cy.get('p').should('contain', '[0]: 94')
92+
cy.get('p').should('contain', '[1]: this-is-all')
93+
cy.get('p').should('contain', '[2]: being')
94+
cy.get('p').should('contain', '[3]: captured')
95+
cy.get('p').should('contain', '[4]: yay')
9596

96-
// query string parameters
97-
cy.get('p').should('contain', '[search]: dog')
98-
cy.get('p').should('contain', '[custom-param]: cat')
97+
// query string parameters
98+
cy.get('p').should('contain', '[search]: dog')
99+
cy.get('p').should('contain', '[custom-param]: cat')
99100

100-
cy.get('h1').should('contain', 'Show #94')
101-
cy.get('p').should('contain', 'Defiance')
102-
})
101+
cy.get('h1').should('contain', 'Show #94')
102+
cy.get('p').should('contain', 'Defiance')
103+
})
103104

104-
it('displays all URL parameters when SSR-ing, including query string parameters', () => {
105-
cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat')
105+
it('displays all URL parameters when SSR-ing, including query string parameters', () => {
106+
cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat')
106107

107-
// path parameters
108-
cy.get('p').should('contain', '[0]: 94')
109-
cy.get('p').should('contain', '[1]: this-is-all')
110-
cy.get('p').should('contain', '[2]: being')
111-
cy.get('p').should('contain', '[3]: captured')
112-
cy.get('p').should('contain', '[4]: yay')
108+
// path parameters
109+
cy.get('p').should('contain', '[0]: 94')
110+
cy.get('p').should('contain', '[1]: this-is-all')
111+
cy.get('p').should('contain', '[2]: being')
112+
cy.get('p').should('contain', '[3]: captured')
113+
cy.get('p').should('contain', '[4]: yay')
113114

114-
// query string parameters
115-
cy.get('p').should('contain', '[search]: dog')
116-
cy.get('p').should('contain', '[custom-param]: cat')
115+
// query string parameters
116+
cy.get('p').should('contain', '[search]: dog')
117+
cy.get('p').should('contain', '[custom-param]: cat')
117118

118-
cy.get('h1').should('contain', 'Show #94')
119-
cy.get('p').should('contain', 'Defiance')
119+
cy.get('h1').should('contain', 'Show #94')
120+
cy.get('p').should('contain', 'Defiance')
121+
})
120122
})
121123
})
122124

123-
describe('API endpoint', () => {
124-
it('returns hello world, with all response headers', () => {
125-
cy.request('/api/static').then(response => {
126-
expect(response.headers['content-type']).to.include('application/json')
127-
expect(response.headers['my-custom-header']).to.include('header123')
125+
describe('getStaticProps', () => {
126+
context('with static route', () => {
127+
it('loads TV show', () => {
128+
cy.visit('/getStaticProps/static')
128129

129-
expect(response.body).to.have.property('message', 'hello world :)')
130+
cy.get('h1').should('contain', 'Show #71')
131+
cy.get('p').should('contain', 'Dancing with the Stars')
130132
})
131-
})
132-
})
133133

134-
describe('dynamic API endpoint', () => {
135-
it('returns TV show', () => {
136-
cy.request('/api/shows/305').then(response => {
137-
expect(response.headers['content-type']).to.include('application/json')
134+
it('loads page props from data .json file when navigating to it', () => {
135+
cy.visit('/')
136+
cy.window().then(w => w.noReload = true)
138137

139-
expect(response.body).to.have.property('show')
140-
expect(response.body.show).to.have.property('id', 305)
141-
expect(response.body.show).to.have.property('name', 'Black Mirror')
138+
// Navigate to page and test that no reload is performed
139+
// See: https://glebbahmutov.com/blog/detect-page-reload/
140+
cy.contains('getStaticProps/static').click()
141+
cy.window().should('have.property', 'noReload', true)
142+
143+
cy.get('h1').should('contain', 'Show #71')
144+
cy.get('p').should('contain', 'Dancing with the Stars')
142145
})
143146
})
144147
})
145148

146-
describe('catch-all API endpoint', () => {
147-
it('returns all URL paremeters, including query string parameters', () => {
148-
cy.request('/api/shows/590/this/path/is/captured?metric=dog&p2=cat')
149-
.then(response => {
149+
describe('API endpoint', () => {
150+
context('with static route', () => {
151+
it('returns hello world, with all response headers', () => {
152+
cy.request('/api/static').then(response => {
150153
expect(response.headers['content-type']).to.include('application/json')
154+
expect(response.headers['my-custom-header']).to.include('header123')
151155

152-
// Params
153-
expect(response.body).to.have.property('params')
154-
expect(response.body.params).to.deep.eq([
155-
'590', 'this', 'path', 'is', 'captured'
156-
])
156+
expect(response.body).to.have.property('message', 'hello world :)')
157+
})
158+
})
159+
})
157160

158-
// Query string parameters
159-
expect(response.body).to.have.property('queryStringParams')
160-
expect(response.body.queryStringParams).to.deep.eq({
161-
metric: 'dog',
162-
p2: 'cat'
163-
})
161+
context('with dynamic route', () => {
162+
it('returns TV show', () => {
163+
cy.request('/api/shows/305').then(response => {
164+
expect(response.headers['content-type']).to.include('application/json')
164165

165-
// Show
166166
expect(response.body).to.have.property('show')
167-
expect(response.body.show).to.have.property('id', 590)
168-
expect(response.body.show).to.have.property('name', 'Pokémon')
167+
expect(response.body.show).to.have.property('id', 305)
168+
expect(response.body.show).to.have.property('name', 'Black Mirror')
169+
})
170+
})
171+
})
172+
173+
context('with catch-all route', () => {
174+
it('returns all URL paremeters, including query string parameters', () => {
175+
cy.request('/api/shows/590/this/path/is/captured?metric=dog&p2=cat')
176+
.then(response => {
177+
expect(response.headers['content-type']).to.include('application/json')
178+
179+
// Params
180+
expect(response.body).to.have.property('params')
181+
expect(response.body.params).to.deep.eq([
182+
'590', 'this', 'path', 'is', 'captured'
183+
])
184+
185+
// Query string parameters
186+
expect(response.body).to.have.property('queryStringParams')
187+
expect(response.body.queryStringParams).to.deep.eq({
188+
metric: 'dog',
189+
p2: 'cat'
190+
})
191+
192+
// Show
193+
expect(response.body).to.have.property('show')
194+
expect(response.body.show).to.have.property('id', 590)
195+
expect(response.body.show).to.have.property('name', 'Pokémon')
196+
})
169197
})
170198
})
171199
})
172200

173-
describe('static page', () => {
174-
it('renders', () => {
175-
cy.visit('/static')
201+
describe('pre-rendered HTML pages', () => {
202+
context('with static route', () => {
203+
it('renders', () => {
204+
cy.visit('/static')
176205

177-
cy.get('p').should('contain', 'It is a static page.')
178-
})
206+
cy.get('p').should('contain', 'It is a static page.')
207+
})
179208

180-
it('renders when SSR-ing', () => {
181-
cy.visit('/static')
209+
it('renders when SSR-ing', () => {
210+
cy.visit('/static')
182211

183-
cy.get('p').should('contain', 'It is a static page.')
212+
cy.get('p').should('contain', 'It is a static page.')
213+
})
184214
})
185-
})
186215

187-
describe('dynamic static page', () => {
188-
it('renders', () => {
189-
cy.visit('/static/superdynamic')
216+
context('with dynamic route', () => {
217+
it('renders', () => {
218+
cy.visit('/static/superdynamic')
190219

191-
cy.get('p').should('contain', 'It is a static page.')
192-
cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.')
193-
})
220+
cy.get('p').should('contain', 'It is a static page.')
221+
cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.')
222+
})
194223

195-
it('renders when SSR-ing', () => {
196-
cy.visit('/static/superdynamic')
224+
it('renders when SSR-ing', () => {
225+
cy.visit('/static/superdynamic')
197226

198-
cy.get('p').should('contain', 'It is a static page.')
199-
cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.')
227+
cy.get('p').should('contain', 'It is a static page.')
228+
cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.')
229+
})
200230
})
201231
})
202232

0 commit comments

Comments
 (0)