Note:
The dynamic import() syntax is a ECMAScript (JavaScript) proposal not currently part of the language standard. It is expected to be accepted in the near future.
setup
npx create-react-app my-app
cd my-app
# 邪魔
rm src/*.css src/App.test.js src/logo.svg src/registerServiceWorker.js
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
App.js
import React, { Component } from "react";
class App extends Component {
render() {
return <div />;
}
}
export default App;
何もしてない状態のbuild後のサイズ
yarn build
# ...
# File sizes after gzip:
# 36.22 KB build/static/js/main.cb06ce91.js
色々と入れてゆく
yarn add ramda lodash underscore
App.js
import React, { Component } from "react";
import * as R from "ramda";
import * as _ from "lodash";
import * as us from "underscore";
class App extends Component {
render() {
return (
<div>
{R.always("aaaa")}
{_.join(["a", "b", "c"], "~")}
{us.now()}
</div>
);
}
}
export default App;
するとbuild後のファイルがクソデカになっていく
yarn build
# ...
# File sizes after gzip:
# 75.55 KB (+39.52 KB) build/static/js/main.5c0f838b.js
build後のファイルを分割する手法として動的インポートが提案されている
// before
import { add } from './math';
console.log(add(16, 26));
// after
import("./math").then(math => {
console.log(math.add(16, 26));
});
公式が推奨しているライブラリを使ってみる
yarn add react-loadable
index.js
import React from "react";
import ReactDOM from "react-dom";
import Loadable from "react-loadable";
const LoadableApp = Loadable({
loader: () => import("./App"),
loading: () => <div>Loading...</div>
});
ReactDOM.render(<LoadableApp />, document.getElementById("root"));
mainの減量成功
yarn build
#File sizes after gzip:
# 40.29 KB build/static/js/0.ab70241c.chunk.js
# 37.81 KB (-37.74 KB) build/static/js/main.0a2572c6.js
分割場所は一旦rootでやっておけばよさそう
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
const Loading = () => <div>Loading...</div>;
const Home = Loadable({
loader: () => import('./routes/Home'),
loading: Loading,
});
const About = Loadable({
loader: () => import('./routes/About'),
loading: Loading,
});
const App = () => (
<Router>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Router>
);
因みに分割されるのが逆に嫌な時はwebpackの設定で制御可能
yarn eject
yarn
config/webpack.config.prod.js
...
plugins: [
...,
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
}),
]
...
動的インポートをしていても分割されない
yarn build
#File sizes after gzip:
# 76.97 KB (+39.16 KB) build/static/js/main.7748b8f8.js
「...2MBのJSファイルは流石にやりすぎましたわ」