{"action":"opened","issue":{"url":"https://api.github.com/repos/CodeLittlePrince/blog/issues/3","repository_url":"https://api.github.com/repos/CodeLittlePrince/blog","labels_url":"https://api.github.com/repos/CodeLittlePrince/blog/issues/3/labels{/name}","comments_url":"https://api.github.com/repos/CodeLittlePrince/blog/issues/3/comments","events_url":"https://api.github.com/repos/CodeLittlePrince/blog/issues/3/events","html_url":"https://github.com/CodeLittlePrince/blog/issues/3","id":271203232,"number":3,"title":"webpack v3 结合 react-router v4 做 dynamic import — 按需加载（懒加载)","user":{"login":"CodeLittlePrince","id":17001245,"avatar_url":"https://avatars1.githubusercontent.com/u/17001245?v=4","gravatar_id":"","url":"https://api.github.com/users/CodeLittlePrince","html_url":"https://github.com/CodeLittlePrince","followers_url":"https://api.github.com/users/CodeLittlePrince/followers","following_url":"https://api.github.com/users/CodeLittlePrince/following{/other_user}","gists_url":"https://api.github.com/users/CodeLittlePrince/gists{/gist_id}","starred_url":"https://api.github.com/users/CodeLittlePrince/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CodeLittlePrince/subscriptions","organizations_url":"https://api.github.com/users/CodeLittlePrince/orgs","repos_url":"https://api.github.com/users/CodeLittlePrince/repos","events_url":"https://api.github.com/users/CodeLittlePrince/events{/privacy}","received_events_url":"https://api.github.com/users/CodeLittlePrince/received_events","type":"User","site_admin":false},"labels":[{"id":739495371,"url":"https://api.github.com/repos/CodeLittlePrince/blog/labels/Webpack","name":"Webpack","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-11-04T16:10:42Z","updated_at":"2017-11-04T16:10:42Z","closed_at":null,"author_association":"OWNER","body":"为什么要做dynamic import？\r\n---\r\ndynamic import不知道为什么有很多叫法，什么按需加载，懒加载，Code Splitting，代码分页等。\r\n总之，就是在SPA，把JS代码分成N个页面份数的文件，不在用户刚进来就全部引入，而是等用户跳转路由的时候，再加载对应的JS文件。\r\n这样做的好处就是加速首屏显示速度，同时也减少了资源的浪费。\r\n\r\n为什么选择 webpack 3?\r\n---\r\n\r\n - 更高的性能\r\n - 有scope hosting功能，不再需要rollup来处理代码冗余\r\n - 可与react-router结合，更优雅的做dynamic import\r\n - 最重要的一点是，我正经学webpack的时候3已结出了- -\r\n\r\n完整的 react spa 项目地址\r\n---\r\n[GitHub项目地址][1]\r\n\r\n\r\n这个一个完整的项目，这节相关的内容可在router/routerMap.jsx中找到。\r\n\r\n第一步：安装 babel-plugin-syntax-dynamic-import\r\n---\r\nbabel用的是babel-env，使用方法可以去babel官方学习，实践可看我项目的源代码。\r\n\r\n`npm i -D babel-plugin-syntax-dynamic-import` 以后， 在.babelrc文件的plungins中加上`\"syntax-dynamic-import\"`。\r\n\r\n第二步：安装 react-loadable\r\n---\r\n`npm i -S react-loadable` 以后，我们就能愉快得做dynamic import了。\r\n\r\n第三步： 编辑routerMap\r\n---\r\n\r\n```\r\nimport React from 'react';\r\nimport { HashRouter as Router, Route, Switch } from 'react-router-dom';\r\nimport createHistory from 'history/createBrowserHistory';\r\nconst history = createHistory();\r\n\r\nimport App from 'containers';\r\n\r\n// 按路由拆分代码\r\nimport Loadable from 'react-loadable';\r\nconst MyLoadingComponent = ({ isLoading, error }) => {\r\n    // Handle the loading state\r\n    if (isLoading) {\r\n        return <div>Loading...</div>;\r\n    }\r\n    // Handle the error state\r\n    else if (error) {\r\n        return <div>Sorry, there was a problem loading the page.</div>;\r\n    }\r\n    else {\r\n        return null;\r\n    }\r\n};\r\nconst AsyncHome = Loadable({\r\n    loader: () => import('../containers/Home'),\r\n    loading: MyLoadingComponent\r\n});\r\nconst AsyncCity = Loadable({\r\n    loader: () => import('../containers/City'),\r\n    loading: MyLoadingComponent\r\n});\r\nconst AsyncDetail = Loadable({\r\n    loader: () => import('../containers/Detail'),\r\n    loading: MyLoadingComponent\r\n});\r\nconst AsyncSearch = Loadable({\r\n    loader: () => import('../containers/Search'),\r\n    loading: MyLoadingComponent\r\n});\r\nconst AsyncUser = Loadable({\r\n    loader: () => import('../containers/User'),\r\n    loading: MyLoadingComponent\r\n});\r\nconst AsyncNotFound = Loadable({\r\n    loader: () => import('../containers/404'),\r\n    loading: MyLoadingComponent\r\n});\r\n\r\n// 路由配置\r\nclass RouteMap extends React.Component {\r\n    render() {\r\n        return (\r\n            <Router history={history}>\r\n                <App>\r\n                    <Switch>\r\n                        <Route path=\"/\" exact component={AsyncHome} />\r\n                        <Route path=\"/city\" component={AsyncCity} />\r\n                        <Route path=\"/search/:category/:keywords?\" component={AsyncSearch} />\r\n                        <Route path=\"/detail/:id\" component={AsyncDetail} />\r\n                        <Route path=\"/user\" component={AsyncUser} />\r\n                        <Route path=\"/empty\" component={null} key=\"empty\" />\r\n                        <Route component={AsyncNotFound} />\r\n                    </Switch>\r\n                </App>\r\n            </Router>\r\n        );\r\n        // 说明\r\n        // empty Route\r\n        // https://github.com/ReactTraining/react-router/issues/1982  解决人：PFight\r\n        // 解决react-router v4改变查询参数并不会刷新或者说重载组件的问题 \r\n    }\r\n}\r\n\r\nexport default RouteMap;\r\n```\r\n大功告成\r\n---\r\n我们可以运行webpack，然后就能看到效果（图仅为dev环境，build才会再打包一个vendor.js，为什么要有vendor.js，请见[devDependencies和dependencies的区别 >>][2]）\r\n\r\n![clipboard.png](https://github.com/CodeLittlePrince/ImagesForGithub/blob/master/blog-webpack-1.png?raw=true)\r\n\r\n参考文章\r\n---\r\n[Code Splitting in Create React App][3]\r\n\r\nQ&A\r\n---\r\n有同学表示，我的方法做页面分离并没有什么好处，因为每个页面都依赖了三方库的代码，所以其实页面有很多冗余代码，能想到这点很棒，已经开始有架构思维了。不过，注意这个想法在`dev`环境下，这个同学是对的。\r\n\r\n那到了`build`环境，或者说到了发布环境，又是怎么样的呢？的确，这篇文章我没有提到，请见我的另一篇文章[devDependencies和dependencies的区别][4]。这篇文章主要解释了npm的package.json中devDependencies和dependencies区别是什么。\r\n\r\n看完以后，我们就可以知道，为什么我之前说“注意这个想法在`dev`环境下，这个同学是对的”了。因为，我们`npm run build`以后，webpack会把三方包打包到vendor.js文件，页面逻辑代码不会牵涉其中，每个页面都会引用vendor.js这个文件，这样的话，就不会出现重复引入冗余代码的情况了。\r\n\r\n\r\n  [1]: https://github.com/CodeLittlePrince/react-webapp-spa\r\n  [2]: https://segmentfault.com/a/1190000011129059\r\n  [3]: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html\r\n  [4]: https://segmentfault.com/a/1190000011129059"}}
{"actor":{"display_login":"CodeLittlePrince"}}