Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on May 10, 2021. It is now read-only.

Commit 8515dd7

Browse filesBrowse files
copy dynamic import chunks to functions dirs (#174)
1 parent 13ffd05 commit 8515dd7
Copy full SHA for 8515dd7

File tree

Expand file treeCollapse file tree

8 files changed

+277
-2
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+277
-2
lines changed
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const { join } = require("path");
2+
const { copySync, readdirSync } = require("fs-extra");
3+
const { logTitle } = require("../helpers/logger");
4+
const { NEXT_DIST_DIR } = require("../config");
5+
6+
// Check if there are dynamic import chunks and copy to the necessary function dir
7+
const copyDynamicImportChunks = (functionPath) => {
8+
const chunksPath = join(NEXT_DIST_DIR, "serverless");
9+
const files = readdirSync(chunksPath);
10+
const chunkRegex = new RegExp(/^(\.?[-_$~A-Z0-9a-z]+){1,}\.js$/g);
11+
const excludeFiles = ["init-server.js.js", "on-error-server.js.js"];
12+
files.forEach((file) => {
13+
if (!excludeFiles.includes(file) && chunkRegex.test(file)) {
14+
logTitle("💼 Copying dynamic import chunks to", functionPath);
15+
copySync(join(chunksPath, file), join(functionPath, file), {
16+
overwrite: false,
17+
errorOnExist: true,
18+
});
19+
}
20+
});
21+
};
22+
23+
module.exports = copyDynamicImportChunks;

‎lib/helpers/setupNetlifyFunctionForPage.js

Copy file name to clipboardExpand all lines: lib/helpers/setupNetlifyFunctionForPage.js
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const {
66
FUNCTION_TEMPLATE_PATH,
77
} = require("../config");
88
const getNetlifyFunctionName = require("./getNetlifyFunctionName");
9+
const copyDynamicImportChunks = require("./copyDynamicImportChunks");
910
const { logItem } = require("./logger");
1011

1112
// Create a Netlify Function for the page with the given file path
@@ -47,8 +48,11 @@ const setupNetlifyFunctionForPage = ({
4748
});
4849
});
4950

51+
// Copy any dynamic import chunks
52+
copyDynamicImportChunks(functionDirectory);
53+
5054
// Copy page
51-
const nextPageCopyPath = join(functionDirectory, "nextPage.js");
55+
const nextPageCopyPath = join(functionDirectory, "nextPage", "index.js");
5256
copySync(join(NEXT_DIST_DIR, "serverless", filePath), nextPageCopyPath, {
5357
overwrite: false,
5458
errorOnExist: true,

‎tests/configurableDirs.test.js

Copy file name to clipboardExpand all lines: tests/configurableDirs.test.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const FUNCTIONS_DIR = "my-functions";
1616
const PUBLISH_DIR = "my-publish";
1717

1818
// Capture the output to verify successful build
19-
let buildOutput;
19+
let runOutput;
2020

2121
beforeAll(
2222
async () => {

‎tests/dynamicImports.test.js

Copy file name to clipboard
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Test next-on-netlify when config is set from a function in next.config.js
2+
// See: https://github.com/netlify/next-on-netlify/issues/25
3+
4+
const { parse, join } = require("path");
5+
const { existsSync, readdirSync, readFileSync } = require("fs-extra");
6+
const buildNextApp = require("./helpers/buildNextApp");
7+
8+
// The name of this test file (without extension)
9+
const FILENAME = parse(__filename).name;
10+
11+
// The directory which will be used for testing.
12+
// We simulate a NextJS app within that directory, with pages, and a
13+
// package.json file.
14+
const PROJECT_PATH = join(__dirname, "builds", FILENAME);
15+
16+
// Capture the output to verify successful build
17+
let buildOutput;
18+
19+
beforeAll(
20+
async () => {
21+
buildOutput = await buildNextApp()
22+
.forTest(__filename)
23+
.withPages("pages-dynamic-imports")
24+
.withNextConfig("next.config.js-est")
25+
.withPackageJson("package.json")
26+
.withFile("components/Header.js", join("components", "Header.js"))
27+
.build();
28+
},
29+
// time out after 180 seconds
30+
180 * 1000
31+
);
32+
33+
describe("next-on-netlify", () => {
34+
const functionsDir = join(PROJECT_PATH, "out_functions");
35+
36+
test("builds successfully", () => {
37+
expect(buildOutput).toMatch("Next on Netlify");
38+
expect(buildOutput).toMatch("Success! All done!");
39+
});
40+
41+
test("copies chunk files to ", () => {
42+
const functionFiles = readdirSync(join(functionsDir, "next_index"));
43+
const chunkRegex = new RegExp(/(\.?[-_$~A-Z0-9a-z]+){1,}\.js$/g);
44+
let chunkFileExists;
45+
functionFiles.forEach((file) => {
46+
chunkFileExists = chunkRegex.test(file);
47+
});
48+
expect(chunkFileExists).toBe(true);
49+
});
50+
});

‎tests/fixtures/components/Header.js

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Header() {
2+
return <h1>header</h1>;
3+
}

‎tests/fixtures/next.config.js-est

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
target: "experimental-serverless-trace",
3+
};
+44Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Link from "next/link";
2+
import dynamic from "next/dynamic";
3+
const Header = dynamic(
4+
() => import(/* webpackChunkName: 'header' */ "../../components/Header"),
5+
{ ssr: true }
6+
);
7+
8+
const Show = ({ show }) => (
9+
<div>
10+
<Header />
11+
<p>
12+
This page uses getInitialProps() to fetch the show with the ID provided in
13+
the URL: /shows/:id
14+
<br />
15+
Refresh the page to see server-side rendering in action.
16+
<br />
17+
You can also try changing the ID to any other number between 1-10000.
18+
</p>
19+
20+
<hr />
21+
22+
<h1>Show #{show.id}</h1>
23+
<p>{show.name}</p>
24+
25+
<hr />
26+
27+
<Link href="/">
28+
<a>Go back home</a>
29+
</Link>
30+
</div>
31+
);
32+
33+
export const getServerSideProps = async ({ params }) => {
34+
const res = await fetch("https://api.tvmaze.com/shows/42");
35+
const data = await res.json();
36+
37+
return {
38+
props: {
39+
show: data,
40+
},
41+
};
42+
};
43+
44+
export default Show;
+148Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import Link from "next/link";
2+
import dynamic from "next/dynamic";
3+
const Header = dynamic(
4+
() => import(/* webpackChunkName: 'header' */ "../components/Header"),
5+
{ ssr: true }
6+
);
7+
8+
const Index = ({ shows }) => (
9+
<div>
10+
<img
11+
src="/next-on-netlify.png"
12+
alt="NextJS on Netlify Banner"
13+
style={{ maxWidth: "100%" }}
14+
/>
15+
16+
<Header />
17+
18+
<p>
19+
This is a demo of a NextJS application with Server-Side Rendering (SSR).
20+
<br />
21+
It is hosted on Netlify.
22+
<br />
23+
Server-side rendering is handled by Netlify Functions.
24+
<br />
25+
Minimal configuration is required.
26+
<br />
27+
Everything is handled by the{" "}
28+
<a href="https://www.npmjs.com/package/next-on-netlify">
29+
next-on-netlify
30+
</a>{" "}
31+
npm package.
32+
</p>
33+
34+
<h1>1. Server-Side Rendering Made Easy</h1>
35+
<p>
36+
This page is server-side rendered.
37+
<br />
38+
It fetches a random list of five TV shows from the TVmaze REST API.
39+
<br />
40+
Refresh this page to see it change.
41+
</p>
42+
43+
<ul>
44+
{shows.map(({ id, name }) => (
45+
<li key={id}>
46+
<Link href="/shows/[id]" as={`/shows/${id}`}>
47+
<a>
48+
#{id}: {name}
49+
</a>
50+
</Link>
51+
</li>
52+
))}
53+
</ul>
54+
55+
<h1>2. Full Support for Dynamic Pages</h1>
56+
<p>
57+
Dynamic pages, introduced in NextJS 9.2, are fully supported.
58+
<br />
59+
Click on a show to check out a server-side rendered page with dynamic
60+
routing (/shows/:id).
61+
</p>
62+
63+
<ul>
64+
{shows.slice(0, 3).map(({ id, name }) => (
65+
<li key={id}>
66+
<Link href="/shows/[id]" as={`/shows/${id}`}>
67+
<a>
68+
#{id}: {name}
69+
</a>
70+
</Link>
71+
</li>
72+
))}
73+
</ul>
74+
75+
<h1>3. Catch-All Routes? Included ✔</h1>
76+
<p>
77+
You can even take advantage of{" "}
78+
<a href="https://nextjs.org/docs/routing/dynamic-routes#catch-all-routes">
79+
NextJS' catch-all routes feature
80+
</a>
81+
.
82+
<br />
83+
Here are three examples:
84+
</p>
85+
<ul>
86+
<li>
87+
<Link href="/shows/[...params]" as={`/shows/73/whatever/path/you/want`}>
88+
<a>/shows/73/whatever/path/you/want</a>
89+
</Link>
90+
</li>
91+
<li>
92+
<Link href="/shows/[...params]" as={`/shows/94/whatever/path/you`}>
93+
<a>/shows/94/whatever/path/you</a>
94+
</Link>
95+
</li>
96+
<li>
97+
<Link href="/shows/[...params]" as={`/shows/106/whatever/path`}>
98+
<a>/shows/106/whatever/path</a>
99+
</Link>
100+
</li>
101+
</ul>
102+
103+
<h1>4. Static Pages Stay Static</h1>
104+
<p>
105+
next-on-netlify automatically determines which pages are dynamic and which
106+
ones are static.
107+
<br />
108+
Only dynamic pages are server-side rendered.
109+
<br />
110+
Static pages are pre-rendered and served directly by Netlify's CDN.
111+
</p>
112+
113+
<ul>
114+
<li>
115+
<Link href="/static">
116+
<a>Static NextJS page: /static</a>
117+
</Link>
118+
</li>
119+
<li>
120+
<Link href="/static/[id]" as="/static/123456789">
121+
<a>Static NextJS page with dynamic routing: /static/:id</a>
122+
</Link>
123+
</li>
124+
</ul>
125+
126+
<h1>Want to Learn More?</h1>
127+
<p>
128+
Check out the{" "}
129+
<a href="https://github.com/FinnWoelm/next-on-netlify-demo">
130+
source code on GitHub
131+
</a>
132+
.
133+
</p>
134+
</div>
135+
);
136+
137+
Index.getInitialProps = async function () {
138+
// Set a random page between 1 and 100
139+
const randomPage = Math.floor(Math.random() * 100) + 1;
140+
141+
// Get the data
142+
const res = await fetch(`https://api.tvmaze.com/shows?page=${randomPage}`);
143+
const data = await res.json();
144+
145+
return { shows: data.slice(0, 5) };
146+
};
147+
148+
export default Index;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.