﻿1
00:00:01,177 --> 00:00:03,870
‫We've talked a lot about optimizing

2
00:00:03,870 --> 00:00:07,710
‫wasted renders and overall app performance.

3
00:00:07,710 --> 00:00:10,800
‫However, probably the most important thing

4
00:00:10,800 --> 00:00:15,120
‫that we can and should optimize is the bundle size.

5
00:00:15,120 --> 00:00:17,643
‫And so let's now learn how to do that.

6
00:00:18,960 --> 00:00:21,480
‫But before we go check out the code,

7
00:00:21,480 --> 00:00:26,220
‫we first need to understand what that bundle actually is.

8
00:00:26,220 --> 00:00:29,610
‫And let's start at the very beginning.

9
00:00:29,610 --> 00:00:33,540
‫So whenever some user navigates to our application,

10
00:00:33,540 --> 00:00:35,610
‫they're basically visiting a website

11
00:00:35,610 --> 00:00:39,240
‫that is hosted on some server, right?

12
00:00:39,240 --> 00:00:41,940
‫So that's just how every single website

13
00:00:41,940 --> 00:00:44,100
‫and web application work.

14
00:00:44,100 --> 00:00:47,580
‫Now, once the user actually navigates to the app,

15
00:00:47,580 --> 00:00:51,120
‫the server will send back a huge JavaScript file

16
00:00:51,120 --> 00:00:54,210
‫to the client that is requesting it.

17
00:00:54,210 --> 00:00:57,630
‫And this file is the bundle.

18
00:00:57,630 --> 00:01:00,660
‫So the bundle is simply a JavaScript file

19
00:01:00,660 --> 00:01:04,650
‫that contains the entire code of the application.

20
00:01:04,650 --> 00:01:07,740
‫And it is called a bundle because a tool

21
00:01:07,740 --> 00:01:12,630
‫like Vite or Webpack has bundled all our development files

22
00:01:12,630 --> 00:01:15,690
‫into one huge bundle which, again,

23
00:01:15,690 --> 00:01:18,660
‫contains all the application code.

24
00:01:18,660 --> 00:01:22,200
‫This means that once the code has been downloaded,

25
00:01:22,200 --> 00:01:25,830
‫the entire React application is loaded at once,

26
00:01:25,830 --> 00:01:29,610
‫which essentially turns it into a single-page application

27
00:01:29,610 --> 00:01:33,060
‫that is running entirely on the client.

28
00:01:33,060 --> 00:01:36,360
‫So whenever the URL changes in the app,

29
00:01:36,360 --> 00:01:39,840
‫the client just renders a new React component

30
00:01:39,840 --> 00:01:43,860
‫but without loading any new files from the server

31
00:01:43,860 --> 00:01:47,310
‫because all the JavaScript code is already there

32
00:01:47,310 --> 00:01:48,990
‫in the bundle.

33
00:01:48,990 --> 00:01:51,840
‫Now, the bundle size is of course the amount

34
00:01:51,840 --> 00:01:55,830
‫of JavaScript code that every single user needs to download

35
00:01:55,830 --> 00:01:59,280
‫in order to start using the application.

36
00:01:59,280 --> 00:02:02,940
‫So if the bundle has, for example, 500 kilobytes,

37
00:02:02,940 --> 00:02:05,640
‫then all those bytes need to be downloaded

38
00:02:05,640 --> 00:02:08,580
‫before the app even starts working.

39
00:02:08,580 --> 00:02:11,100
‫And of course, the bigger the bundle,

40
00:02:11,100 --> 00:02:13,560
‫the longer it's gonna take to download

41
00:02:13,560 --> 00:02:16,680
‫which can become a huge problem.

42
00:02:16,680 --> 00:02:19,080
‫Therefore, bundle size is probably

43
00:02:19,080 --> 00:02:22,890
‫the most important thing that we need to optimize.

44
00:02:22,890 --> 00:02:26,430
‫And thankfully for us and for our users,

45
00:02:26,430 --> 00:02:28,470
‫it's not very hard to do.

46
00:02:28,470 --> 00:02:32,430
‫So we can just use a technique called code splitting.

47
00:02:32,430 --> 00:02:35,340
‫And code splitting basically takes the bundle

48
00:02:35,340 --> 00:02:39,930
‫and, as the name says, splits it into multiple parts.

49
00:02:39,930 --> 00:02:44,220
‫So instead of just having one huge JavaScript file,

50
00:02:44,220 --> 00:02:47,040
‫we will have multiple smaller files

51
00:02:47,040 --> 00:02:49,710
‫which can then be downloaded over time

52
00:02:49,710 --> 00:02:53,820
‫as they become necessary for the application.

53
00:02:53,820 --> 00:02:57,150
‫And this process of loading code sequentially

54
00:02:57,150 --> 00:02:59,790
‫is called lazy loading.

55
00:02:59,790 --> 00:03:03,750
‫And this really is one of the biggest performance gains

56
00:03:03,750 --> 00:03:06,630
‫that you can achieve for your users.

57
00:03:06,630 --> 00:03:09,963
‫And so let me now show you how it's done in practice.

58
00:03:10,980 --> 00:03:14,580
‫Now, there are many ways in which we can split the bundle,

59
00:03:14,580 --> 00:03:18,540
‫so in which we can lazily load our components.

60
00:03:18,540 --> 00:03:21,420
‫But the most common one is to split the bundle

61
00:03:21,420 --> 00:03:26,420
‫at the route level or, in other words, at the page level.

62
00:03:26,640 --> 00:03:29,220
‫So basically what we're gonna do is to take

63
00:03:29,220 --> 00:03:32,310
‫all the components that represent a page

64
00:03:32,310 --> 00:03:36,240
‫and load each of them separately, okay?

65
00:03:36,240 --> 00:03:39,450
‫So again, that's what most applications do,

66
00:03:39,450 --> 00:03:42,180
‫but of course we don't have to do it this way

67
00:03:42,180 --> 00:03:45,480
‫because this feature that I'm about to tell you

68
00:03:45,480 --> 00:03:49,770
‫and to show you has really nothing to do with React Router.

69
00:03:49,770 --> 00:03:52,620
‫So any component can be lazy loaded

70
00:03:52,620 --> 00:03:55,170
‫in the way that I'm gonna show you.

71
00:03:55,170 --> 00:03:57,960
‫So let's actually do that.

72
00:03:57,960 --> 00:04:01,050
‫First, let's remove these imports from here

73
00:04:01,050 --> 00:04:03,630
‫and place them here.

74
00:04:03,630 --> 00:04:07,800
‫And so now let's first identify our pages.

75
00:04:07,800 --> 00:04:11,973
‫So it's the Homepage, the Product, the Pricing, the Login,

76
00:04:12,840 --> 00:04:17,220
‫then here the application itself, which is an AppLayout.

77
00:04:17,220 --> 00:04:19,950
‫And finally, PageNotFound.

78
00:04:19,950 --> 00:04:22,593
‫So those are our six pages.

79
00:04:24,420 --> 00:04:28,530
‫So that are basically these six right here.

80
00:04:28,530 --> 00:04:32,130
‫And so let's comment them out.

81
00:04:32,130 --> 00:04:35,253
‫And again, we will now lazy load these.

82
00:04:38,130 --> 00:04:42,360
‫So instead of writing import, let's now write just the name

83
00:04:42,360 --> 00:04:45,753
‫of the component, for example, Homepage.

84
00:04:47,340 --> 00:04:50,553
‫And then we use React's lazy function.

85
00:04:52,230 --> 00:04:55,080
‫And you see here it has been successfully imported

86
00:04:55,080 --> 00:04:56,670
‫from React.

87
00:04:56,670 --> 00:05:00,453
‫Let's just place that at the top where I like it most.

88
00:05:01,470 --> 00:05:04,530
‫So this lazy function here is actually a feature

89
00:05:04,530 --> 00:05:06,690
‫that is built into React.

90
00:05:06,690 --> 00:05:10,860
‫And then Vite or Webpack, they will automatically split

91
00:05:10,860 --> 00:05:14,820
‫the bundle when they see this lazy function.

92
00:05:14,820 --> 00:05:19,110
‫Alright, now actually thinking of these bundlers,

93
00:05:19,110 --> 00:05:21,780
‫I had the idea that I should even show you

94
00:05:21,780 --> 00:05:24,060
‫how the bundle looks like right now

95
00:05:24,060 --> 00:05:26,580
‫before we do any of this.

96
00:05:26,580 --> 00:05:30,273
‫So let's for a second just bring this back.

97
00:05:31,350 --> 00:05:35,250
‫So just that everything works the same way as before.

98
00:05:35,250 --> 00:05:38,493
‫And then here I want to open up a new terminal.

99
00:05:39,840 --> 00:05:42,060
‫So again, in our project folder,

100
00:05:42,060 --> 00:05:46,613
‫and then here let's run npm run build,

101
00:05:47,880 --> 00:05:51,210
‫which will then create our JavaScript bundle.

102
00:05:51,210 --> 00:05:53,520
‫And so we can then take this bundle

103
00:05:53,520 --> 00:05:56,073
‫and actually deploy it on a web server.

104
00:05:57,090 --> 00:06:00,090
‫So a bit later in the course when I show you deployment,

105
00:06:00,090 --> 00:06:01,950
‫this is how we will export

106
00:06:01,950 --> 00:06:05,133
‫basically our final application for production.

107
00:06:06,060 --> 00:06:07,620
‫But anyway, we see here

108
00:06:07,620 --> 00:06:11,700
‫that we just have this one huge JavaScript bundle.

109
00:06:11,700 --> 00:06:14,550
‫So it's this almost 600 kilobytes.

110
00:06:14,550 --> 00:06:17,730
‫And so Vite even warns us here

111
00:06:17,730 --> 00:06:20,100
‫that some chunks are really large

112
00:06:20,100 --> 00:06:23,160
‫and that we should use this dynamic import.

113
00:06:23,160 --> 00:06:26,430
‫So that's exactly what we're gonna do next.

114
00:06:26,430 --> 00:06:29,430
‫So for now, I just want, just for the fun of it,

115
00:06:29,430 --> 00:06:33,900
‫copy these two lines and paste them here as comments,

116
00:06:33,900 --> 00:06:36,540
‫just so that we can later compare

117
00:06:36,540 --> 00:06:39,243
‫what we get after the lazy loading.

118
00:06:40,380 --> 00:06:44,460
‫So let's clean this, make it a bit smaller,

119
00:06:44,460 --> 00:06:48,690
‫and then let's actually implement the lazy loading.

120
00:06:48,690 --> 00:06:51,720
‫And so in here, we now need a callback function

121
00:06:51,720 --> 00:06:56,040
‫which will then call the dynamic import function

122
00:06:56,040 --> 00:07:00,180
‫which is actually part of JavaScript.

123
00:07:00,180 --> 00:07:03,270
‫And so here we then need again the path

124
00:07:03,270 --> 00:07:05,640
‫to the component itself.

125
00:07:05,640 --> 00:07:10,200
‫So pages/Homepage.

126
00:07:10,200 --> 00:07:13,470
‫And here we actually need these

127
00:07:13,470 --> 00:07:16,263
‫to come before the dynamic imports.

128
00:07:19,140 --> 00:07:20,400
‫So just like this.

129
00:07:20,400 --> 00:07:22,200
‫And of course, we still have some errors

130
00:07:22,200 --> 00:07:25,203
‫because now all of these are not defined.

131
00:07:26,400 --> 00:07:29,490
‫So I'm just gonna duplicate this a few times now

132
00:07:29,490 --> 00:07:31,353
‫and then implement all of them.

133
00:07:33,390 --> 00:07:37,623
‫So the Product, we have our Pricing page,

134
00:07:40,560 --> 00:07:42,780
‫again with the capital P.

135
00:07:42,780 --> 00:07:45,663
‫Then we have our Login,

136
00:07:46,560 --> 00:07:48,873
‫we have the AppLayout,

137
00:07:50,220 --> 00:07:53,523
‫and we have finally PageNotFound.

138
00:07:56,370 --> 00:07:58,563
‫Okay, that should be it.

139
00:07:59,940 --> 00:08:02,313
‫Let's reload this at the root.

140
00:08:03,840 --> 00:08:06,480
‫And for now, everything is working fine,

141
00:08:06,480 --> 00:08:10,050
‫but this is actually not yet the end of the story.

142
00:08:10,050 --> 00:08:12,240
‫So this is only the first part.

143
00:08:12,240 --> 00:08:15,240
‫But now we also want to display a loading spinner

144
00:08:15,240 --> 00:08:18,390
‫while we go from one page to the other one.

145
00:08:18,390 --> 00:08:21,390
‫So basically, while these pages are gonna be loaded

146
00:08:21,390 --> 00:08:22,713
‫in the background.

147
00:08:24,120 --> 00:08:26,310
‫Now here I see I have a problem,

148
00:08:26,310 --> 00:08:28,200
‫so it needs to be like this.

149
00:08:28,200 --> 00:08:32,640
‫But anyway, this is now where the React's Suspense API

150
00:08:32,640 --> 00:08:35,400
‫comes into play for the first time.

151
00:08:35,400 --> 00:08:39,360
‫So I've mentioned the Suspense API a few times already,

152
00:08:39,360 --> 00:08:42,030
‫I believe, but now we're actually gonna use it

153
00:08:42,030 --> 00:08:44,100
‫for the very first time.

154
00:08:44,100 --> 00:08:47,790
‫So I will not go really deep into what it is right now

155
00:08:47,790 --> 00:08:51,240
‫because I will leave that for some later point.

156
00:08:51,240 --> 00:08:54,750
‫But for now, what you need to know is that Suspense

157
00:08:54,750 --> 00:08:59,340
‫is a concurrent feature that is part of modern React,

158
00:08:59,340 --> 00:09:03,090
‫and that allows certain components to suspend,

159
00:09:03,090 --> 00:09:06,540
‫which basically means that it allows them to wait

160
00:09:06,540 --> 00:09:08,370
‫for something to happen.

161
00:09:08,370 --> 00:09:10,650
‫And in our case right here,

162
00:09:10,650 --> 00:09:14,370
‫basically these lazy components are gonna be suspended

163
00:09:14,370 --> 00:09:16,080
‫while they're loading.

164
00:09:16,080 --> 00:09:19,770
‫And so we can then use the built-in Suspense component

165
00:09:19,770 --> 00:09:22,590
‫to show a fallback, which, in our case,

166
00:09:22,590 --> 00:09:25,893
‫is gonna be that loading indicator that I just mentioned.

167
00:09:26,880 --> 00:09:30,090
‫So let's come here into our tree,

168
00:09:30,090 --> 00:09:34,923
‫and above the routes, let's then include Suspense.

169
00:09:36,240 --> 00:09:40,713
‫So making sure that component has been included from React.

170
00:09:42,016 --> 00:09:45,933
‫And then here is where we specify the fallback prop.

171
00:09:47,820 --> 00:09:50,760
‫So here, this then takes a React element,

172
00:09:50,760 --> 00:09:54,813
‫which is going to be our full page spinner component.

173
00:09:55,800 --> 00:09:58,350
‫So we have here the regular spinner,

174
00:09:58,350 --> 00:10:01,350
‫and we also have a SpinnerFullPage,

175
00:10:01,350 --> 00:10:04,950
‫which is basically just a spinner but inside one element

176
00:10:04,950 --> 00:10:06,753
‫that takes up the entire page.

177
00:10:09,242 --> 00:10:10,825
‫So SpinnerFullPage.

178
00:10:15,120 --> 00:10:18,780
‫So it looks like we're gonna have to manually import that,

179
00:10:18,780 --> 00:10:19,953
‫but that's no problem.

180
00:10:21,330 --> 00:10:23,640
‫So we open the Suspense,

181
00:10:23,640 --> 00:10:28,083
‫and then we need to close it here after the Routes.

182
00:10:29,310 --> 00:10:32,980
‫Okay, now let's then import this spinner

183
00:10:35,130 --> 00:10:37,247
‫from SpinnerFullPage.

184
00:10:42,990 --> 00:10:46,023
‫And with this, we should be good to go.

185
00:10:46,890 --> 00:10:49,560
‫So let's just very shortly recap here

186
00:10:49,560 --> 00:10:52,230
‫before we actually try this out.

187
00:10:52,230 --> 00:10:56,430
‫So here with this lazy loading, we will now load

188
00:10:56,430 --> 00:10:59,670
‫each of these components here as we need them,

189
00:10:59,670 --> 00:11:02,520
‫which will basically automatically split

190
00:11:02,520 --> 00:11:05,670
‫our bundle into separate chunks.

191
00:11:05,670 --> 00:11:07,800
‫And it is Vite, in our case here,

192
00:11:07,800 --> 00:11:10,260
‫that's gonna take care of that.

193
00:11:10,260 --> 00:11:13,860
‫And so then, of course, there will be a time

194
00:11:13,860 --> 00:11:16,830
‫while we navigate from one page to the other

195
00:11:16,830 --> 00:11:19,860
‫where that chunk has not been downloaded yet.

196
00:11:19,860 --> 00:11:21,840
‫So for example, if we go to Login,

197
00:11:21,840 --> 00:11:25,080
‫then that page has not been downloaded.

198
00:11:25,080 --> 00:11:27,570
‫And so then this entire thing,

199
00:11:27,570 --> 00:11:32,570
‫so this lazy functionality is powered by the Suspense API.

200
00:11:32,940 --> 00:11:36,450
‫And so that will make the component basically suspended

201
00:11:36,450 --> 00:11:39,180
‫in the meantime which will then display

202
00:11:39,180 --> 00:11:40,620
‫this loading spinner.

203
00:11:40,620 --> 00:11:42,570
‫And then once that has arrived,

204
00:11:42,570 --> 00:11:44,700
‫it will no longer be suspended.

205
00:11:44,700 --> 00:11:49,140
‫And then the content here, so the children of the Suspense,

206
00:11:49,140 --> 00:11:53,310
‫is gonna be displayed, so it's gonna be rendered.

207
00:11:53,310 --> 00:11:54,753
‫So let's see if that works.

208
00:11:55,680 --> 00:11:58,530
‫And let's actually do some throttling here

209
00:11:58,530 --> 00:12:02,823
‫like a Slow 3G so that we can actually see this happening.

210
00:12:03,960 --> 00:12:06,390
‫So let's click on Pricing.

211
00:12:06,390 --> 00:12:09,693
‫Let's even clear our network requests.

212
00:12:11,010 --> 00:12:16,010
‫And it is working, so it's now loading that chunk.

213
00:12:16,140 --> 00:12:20,850
‫And so now that arrived, and so now the page has loaded.

214
00:12:20,850 --> 00:12:23,520
‫And you see that some additional kilobytes

215
00:12:23,520 --> 00:12:26,490
‫were transferred in the meantime.

216
00:12:26,490 --> 00:12:29,790
‫And the same thing is gonna happen with the Product page

217
00:12:29,790 --> 00:12:32,160
‫and with all the other pages.

218
00:12:32,160 --> 00:12:34,110
‫But of course, if I go back now,

219
00:12:34,110 --> 00:12:37,020
‫then that chunk has already been loaded before,

220
00:12:37,020 --> 00:12:39,630
‫and so it's not gonna be loaded again.

221
00:12:39,630 --> 00:12:43,200
‫So it will nicely be integrated into the application

222
00:12:43,200 --> 00:12:44,283
‫that we already have.

223
00:12:45,990 --> 00:12:49,470
‫All right, so let's load up our next page,

224
00:12:49,470 --> 00:12:51,150
‫and it looks already slow,

225
00:12:51,150 --> 00:12:52,560
‫but that's just because we have

226
00:12:52,560 --> 00:12:54,813
‫this throttling here activated.

227
00:12:56,520 --> 00:12:58,953
‫So loading now the next thing,

228
00:13:01,860 --> 00:13:05,280
‫a store app layout, which is the main part of the app,

229
00:13:05,280 --> 00:13:07,863
‫and so that's why that takes a bit longer.

230
00:13:09,360 --> 00:13:11,430
‫Okay, great.

231
00:13:11,430 --> 00:13:14,730
‫And of course, now if we go back, so the second time,

232
00:13:14,730 --> 00:13:17,283
‫everything is gonna work really fluidly.

233
00:13:18,210 --> 00:13:19,410
‫Beautiful.

234
00:13:19,410 --> 00:13:23,550
‫So this really is the most important feature, I would say,

235
00:13:23,550 --> 00:13:25,560
‫that we should always implement

236
00:13:25,560 --> 00:13:29,010
‫in any React application that we're building.

237
00:13:29,010 --> 00:13:32,280
‫And now to finish, let's just see the actual chunks

238
00:13:32,280 --> 00:13:34,443
‫that Vite has created for us.

239
00:13:35,640 --> 00:13:38,493
‫So npm run build.

240
00:13:39,660 --> 00:13:43,320
‫So these chunks here are not gonna be exactly the same ones

241
00:13:43,320 --> 00:13:46,170
‫as in development, because in development,

242
00:13:46,170 --> 00:13:48,000
‫everything is a bit different.

243
00:13:48,000 --> 00:13:51,183
‫So this year is already optimized for production.

244
00:13:52,170 --> 00:13:57,170
‫And so we see that it all is very different.

245
00:13:57,510 --> 00:14:00,430
‫So we have lots of different chunks now here

246
00:14:01,560 --> 00:14:05,010
‫which are then all lazy loaded.

247
00:14:05,010 --> 00:14:08,760
‫So you see that we still have a huge one right here,

248
00:14:08,760 --> 00:14:11,100
‫but probably all of them added together

249
00:14:11,100 --> 00:14:14,823
‫will be these 572 kilobytes.

250
00:14:17,040 --> 00:14:22,040
‫Alright, so this 415 is not a lot less

251
00:14:22,290 --> 00:14:25,500
‫than this one, but that's already good enough.

252
00:14:25,500 --> 00:14:29,820
‫So we could now try to lazy load some other components here.

253
00:14:29,820 --> 00:14:32,940
‫So remember that it doesn't only work with routes,

254
00:14:32,940 --> 00:14:35,310
‫but I think that this is good enough.

255
00:14:35,310 --> 00:14:37,650
‫So for example, the AppLayout itself

256
00:14:37,650 --> 00:14:41,250
‫was apparently 156 kilobytes.

257
00:14:41,250 --> 00:14:43,320
‫And so it's really nice that we got that

258
00:14:43,320 --> 00:14:45,930
‫out of the main bundle.

259
00:14:45,930 --> 00:14:49,230
‫And notice how even the CSS is also split

260
00:14:49,230 --> 00:14:50,613
‫into multiple parts.

261
00:14:51,927 --> 00:14:55,080
‫All right, so really nice feature.

262
00:14:55,080 --> 00:15:00,080
‫And yeah, again, powered by both the bundler,

263
00:15:00,810 --> 00:15:02,280
‫so Vite or Webpack,

264
00:15:02,280 --> 00:15:05,670
‫and the lazy function provided by React

265
00:15:05,670 --> 00:15:09,090
‫plus the import function provided by JavaScript,

266
00:15:09,090 --> 00:15:12,630
‫and then also this Suspense component.

267
00:15:12,630 --> 00:15:15,030
‫So hopefully you found this easy enough

268
00:15:15,030 --> 00:15:16,560
‫that you're going to implement this

269
00:15:16,560 --> 00:15:19,380
‫in all your future applications.

270
00:15:19,380 --> 00:15:23,160
‫And with this, we have now actually finally

271
00:15:23,160 --> 00:15:27,270
‫really completed this WorldWise application.

272
00:15:27,270 --> 00:15:30,540
‫So this was the last video in which we worked

273
00:15:30,540 --> 00:15:32,010
‫on this project.

274
00:15:32,010 --> 00:15:36,030
‫And so once again, congratulations for finishing

275
00:15:36,030 --> 00:15:39,870
‫this big project where we learned so many new things

276
00:15:39,870 --> 00:15:42,330
‫and covered so much ground.

277
00:15:42,330 --> 00:15:44,190
‫So I hope that you liked it

278
00:15:44,190 --> 00:15:47,550
‫and that I see you for another small project

279
00:15:47,550 --> 00:15:49,863
‫with which we will finish this section.

