Skip to content

Commit 6604fb0

Browse files
committed
implemented code splitting for chapter 17 project
1 parent 6724d1a commit 6604fb0

File tree

7 files changed

+101
-21
lines changed

7 files changed

+101
-21
lines changed

17/react-router-tutorial/config/webpack.config.dev.js

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,17 @@ module.exports = {
3232
// These are the "entry points" to our application.
3333
// This means they will be the "root" imports that are included in JS bundle.
3434
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
35-
entry: [
36-
// We ship a few polyfills by default:
37-
require.resolve('./polyfills'),
38-
// Include an alternative client for WebpackDevServer. A client's job is to
39-
// connect to WebpackDevServer by a socket and get notified about changes.
40-
// When you save a file, the client will either apply hot updates (in case
41-
// of CSS changes), or refresh the page (in case of JS changes). When you
42-
// make a syntax error, this client will display a syntax error overlay.
43-
// Note: instead of the default WebpackDevServer client, we use a custom one
44-
// to bring better experience for Create React App users. You can replace
45-
// the line below with these two lines if you prefer the stock client:
46-
// require.resolve('webpack-dev-server/client') + '?/',
47-
// require.resolve('webpack/hot/dev-server'),
48-
require.resolve('react-dev-utils/webpackHotDevClient'),
49-
// Finally, this is your app's code:
50-
paths.appIndexJs,
51-
// We include the app code last so that if there is a runtime error during
52-
// initialization, it doesn't blow up the WebpackDevServer client, and
53-
// changing JS code would still trigger a refresh.
54-
],
35+
entry: {
36+
app: [
37+
require.resolve('react-dev-utils/webpackHotDevClient'), paths.appIndexJs,
38+
],
39+
vendor: [
40+
require.resolve('./polyfills'),
41+
'react',
42+
'react-dom',
43+
'react-router-dom',
44+
]
45+
},
5546
output: {
5647
// Add /* filename */ comments to generated require()s in the output.
5748
pathinfo: true,
@@ -211,6 +202,10 @@ module.exports = {
211202
],
212203
},
213204
plugins: [
205+
new webpack.optimize.CommonsChunkPlugin({
206+
name: 'vendor',
207+
filename: 'vendor.js'
208+
}),
214209
// Makes some environment variables available in index.html.
215210
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
216211
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

17/react-router-tutorial/config/webpack.config.prod.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,15 @@ module.exports = {
5656
// You can exclude the *.map files from the build during deployment.
5757
devtool: shouldUseSourceMap ? 'source-map' : false,
5858
// In production, we only want to load the polyfills and the app code.
59-
entry: [require.resolve('./polyfills'), paths.appIndexJs],
59+
entry: {
60+
app: paths.appIndexJs,
61+
vendor: [
62+
require.resolve('./polyfills'),
63+
'react',
64+
'react-dom',
65+
'react-router-dom'
66+
]
67+
},
6068
output: {
6169
// The build folder.
6270
path: paths.appBuild,
@@ -234,6 +242,15 @@ module.exports = {
234242
],
235243
},
236244
plugins: [
245+
new webpack.NormalModuleReplacementPlugin(
246+
/^pages$/,
247+
'pages/index.async.js'
248+
),
249+
new webpack.optimize.CommonsChunkPlugin({
250+
name: 'vendor',
251+
filename: 'vendor.js'
252+
}),
253+
237254
// Makes some environment variables available in index.html.
238255
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
239256
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

17/react-router-tutorial/src/App.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
Posts
77
} from 'pages';
88
import Menu from 'components/Menu';
9+
import AsyncSplitMe from 'components/AsyncSplitMe';
910

1011
const App = () => {
1112
return (
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, { Component } from 'react';
2+
3+
class AsyncSplitMe extends Component {
4+
state = {
5+
SplitMe: null
6+
}
7+
8+
loadSplitMe = () => {
9+
// 비동기적으로 코드를 불러옵니다. 함수는 Promise를 결과로 반환합니다.
10+
// import()는 모듈의 전체 네임스페이스를 불러오므로, default를 직접 지정해주어야 합니다.
11+
import('./SplitMe').then(({default: SplitMe}) => {
12+
this.setState({
13+
SplitMe
14+
});
15+
});
16+
}
17+
render() {
18+
const { SplitMe } = this.state;
19+
// SplitMe가 있으면 이를 렌더링하고, 없으면 버튼을 렌더링합니다.
20+
// 버튼 클릭 시 SplitMe를 불러옵니다.
21+
return SplitMe ? <SplitMe/> : <button onClick={this.loadSplitMe}>SplitMe 로딩</button>
22+
}
23+
}
24+
25+
export default AsyncSplitMe;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
3+
const SplitMe = () => {
4+
return (
5+
<h3>
6+
청크
7+
</h3>
8+
);
9+
};
10+
11+
export default SplitMe;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
3+
export default function asyncComponent(getComponent) {
4+
return class AsyncComponent extends React.Component {
5+
static Component = null;
6+
state = { Component: AsyncComponent.Component };
7+
8+
constructor(props) {
9+
super(props);
10+
if (AsyncComponent.Component) return;
11+
getComponent().then(({default: Component}) => {
12+
AsyncComponent.Component = Component;
13+
this.setState({ Component });
14+
});
15+
}
16+
17+
render() {
18+
const { Component } = this.state
19+
if (Component) {
20+
return <Component {...this.props} />
21+
}
22+
return null
23+
}
24+
}
25+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import asyncComponent from 'lib/asyncComponent';
2+
3+
export const Home = asyncComponent(() => import('./Home'));
4+
export const About = asyncComponent(() => import('./About'));
5+
export const Post = asyncComponent(() => import('./Post'));
6+
export const Posts = asyncComponent(() => import('./Posts'));

0 commit comments

Comments
 (0)