Skip to content

Commit c021662

Browse files
author
Jens Meindertsma
authored
Fix with-msw example (#17695)
When using the `with-msw` example I noticed it increased my bundle size in production, even through MSW is meant to be used in development only. **Build size before implementing MSW** ``` Page Size First Load JS ┌ λ / 479 B 58.9 kB ├ /_app 0 B 58.4 kB └ ○ /404 3.44 kB 61.9 kB + First Load JS shared by all 58.4 kB ├ chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.b1b405.js 10.3 kB ├ chunks/framework.cb05d5.js 39.9 kB ├ chunks/main.a140d5.js 7.28 kB ├ chunks/pages/_app.b90a57.js 277 B └ chunks/webpack.e06743.js 751 B λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps) (ISR) incremental static regeneration (uses revalidate in getStaticProps) ``` **Build size after implementing MSW according to the `with-msw` example** ``` Page Size First Load JS ┌ λ / 479 B 71.6 kB ├ /_app 0 B 71.1 kB └ ○ /404 3.44 kB 74.6 kB + First Load JS shared by all 71.1 kB ├ chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.b1b405.js 10.3 kB ├ chunks/framework.cb05d5.js 39.9 kB ├ chunks/main.a140d5.js 7.28 kB ├ chunks/pages/_app.c58a6f.js 13 kB └ chunks/webpack.e06743.js 751 B λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps) (ISR) incremental static regeneration (uses revalidate in getStaticProps) ``` There was a 12.7 kB large increase in the `_app` First Load JS which increased the pages' First Load JS size. I tracked the problem down to the following code: ```js if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') { require('../mocks') } ``` Removing this reduces the `_app` First Load JS to what it was previously. The `NEXT_PUBLIC_API_MOCKING` environment variable is defined in the `.env.development` file, as this means that Next.js will only activate MSW during development/testing, which is what MSW is intended for. After discussing with @kettanaito, the author of MSW, I did some investigation. This dynamic require statement is intended to allow tree-shaking of the MSW package for production. Unfortunately this did not seem to be working. To fix this, I changed the code to the following: ```js if (process.env.NODE_ENV !== 'production') { require('../mocks') } ``` This means I could remove the `NEXT_PUBLIC_API_MOCKING` environment variable from `.env.development`, as it is no longer used. It is important to note that this still achieves the same functionality as before: MSW runs in development / testing, and not in production. If MSW must be enabled in production for some reason, the following code can be used to run MSW regardless of the environment: ```js if (true) { require('../mocks') } ``` If possible, I'd love to hear from the Next.js maintainers regarding the tree-shaking process when using environment variables. Lastly, I made the necessary changes to have the example work in production mode as well, because there is no real backend. Of course there is a comment explaining what should be changed in a real world app.
1 parent bbc1a21 commit c021662

File tree

4 files changed

+32
-13
lines changed

4 files changed

+32
-13
lines changed

examples/with-msw/.env

-4
This file was deleted.

examples/with-msw/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
},
99
"license": "MIT",
1010
"dependencies": {
11-
"msw": "^0.21.0",
11+
"msw": "^0.21.2",
1212
"next": "latest",
1313
"react": "^16.13.1",
1414
"react-dom": "^16.13.1"

examples/with-msw/pages/_app.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
1+
// Enable API mocking in all environments except production.
2+
// This is recommended for real-world apps.
3+
if (process.env.NODE_ENV !== 'production') {
24
require('../mocks')
35
}
46

examples/with-msw/pages/index.js

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState } from 'react'
22

3-
export default function Home({ book }) {
3+
export default function Home({ book, inProduction }) {
44
const [reviews, setReviews] = useState(null)
55

66
const handleGetReviews = () => {
@@ -10,6 +10,18 @@ export default function Home({ book }) {
1010
.then(setReviews)
1111
}
1212

13+
if (inProduction) {
14+
return (
15+
<div>
16+
<p>
17+
This example does not work in production, as MSW is not intended for
18+
use in production. In a real-world app, your request will hit the
19+
actual backend instead.
20+
</p>
21+
</div>
22+
)
23+
}
24+
1325
return (
1426
<div>
1527
<img src={book.imageUrl} alt={book.title} width="250" />
@@ -32,12 +44,21 @@ export default function Home({ book }) {
3244

3345
export async function getServerSideProps() {
3446
// Server-side requests are mocked by `mocks/server.js`.
35-
const res = await fetch('https://my.backend/book')
36-
const book = await res.json()
47+
// In a real-world app this request would hit the actual backend.
48+
try {
49+
const res = await fetch('https://my.backend/book')
50+
const book = await res.json()
3751

38-
return {
39-
props: {
40-
book,
41-
},
52+
return {
53+
props: {
54+
book,
55+
},
56+
}
57+
} catch (error) {
58+
return {
59+
props: {
60+
inProduction: true,
61+
},
62+
}
4263
}
4364
}

0 commit comments

Comments
 (0)