{
    "componentChunkName": "component---src-templates-article-page-template-js",
    "path": "/ftw/how-code-splitting-works-in-ftw/",
    "result": {"data":{"markdownRemark":{"frontmatter":{"title":"How code splitting works in FTW","slug":"how-code-splitting-works-in-ftw","updated":"2021-02-12T00:00:00.000Z","category":"ftw-routing","ingress":"This article explains how the code splitting setup works in Flex Template for Web (FTW).","skills":null},"htmlAst":{"type":"root","children":[{"type":"element","tagName":"h2","properties":{"id":"background-info","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#background-info","ariaLabel":"background info permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Background info"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"FTW-daily started using code-splitting from version "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"8.0.0"}]},{"type":"text","value":" and\nFTW-hourly from "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"10.0.0"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Previously, "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"sharetribe-scripts"}]},{"type":"text","value":" created one\n"},{"type":"element","tagName":"a","properties":{"href":"https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"UMD"}]},{"type":"text","value":"\nbuild that was used on both server and frontend. I.e. all the code used\nin the app was bundled into a single "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"main.bundle.js"}]},{"type":"text","value":" file and that was\nused in the web app and server."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Unfortunately, this has meant that code-splitting was not supported: it\ndidn't work with the UMD build due to an old bug in Webpack."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"With sharetribe-scripts version "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"5.0.0"}]},{"type":"text","value":", we changed this behaviour:\nsharetribe-scripts creates 2 different builds when "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"yarn run build"}]},{"type":"text","value":" is\ncalled. Basically, this means that build-time increases (including\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"yarn run dev-server"}]},{"type":"text","value":" call)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"However, this setup makes code-splitting possible. To make this easier,\nwe have added "},{"type":"element","tagName":"a","properties":{"href":"https://loadable-components.com/","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"Loadable Components"}]},{"type":"text","value":"\nlibrary to the setup."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"what-is-code-splitting","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#what-is-code-splitting","ariaLabel":"what is code splitting permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"What is code splitting"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Instead of downloading the entire app before users can use it, code\nsplitting allows us to split code away from one main.bundle.js file into\nsmaller chunks which you can then load on demand. To familiarize\nyourself with the subject, you could read about code splitting from\n"},{"type":"element","tagName":"a","properties":{"href":"https://reactjs.org/docs/code-splitting.html","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"reactjs.org"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In practice, FTW templates use route-based code splitting: page-level\ncomponents are now using\n"},{"type":"element","tagName":"a","properties":{"href":"https://loadable-components.com/","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"Loadable Components"}]},{"type":"text","value":" syntax to create\n"},{"type":"element","tagName":"a","properties":{"href":"https://webpack.js.org/api/module-methods/#import-1","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"dynamic imports"}]},{"type":"text","value":"\nfunctionality."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"const"}]},{"type":"text","value":" AboutPage "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"loadable"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"import"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"/* webpackChunkName: \"AboutPage\" */"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'./containers/AboutPage/AboutPage'"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When Webpack comes across these loadable objects, it will create a new\nJS & CSS chunk files (e.g. "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"AboutPage.dc3102d3.chunk.js"}]},{"type":"text","value":"). I.e. those\ncode-paths are separated from the main bundle."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Previously, (when code-splitting was not supported), when you loaded\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/about"}]},{"type":"text","value":" page, you received "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"main.bundle.js"}]},{"type":"text","value":" & "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"main.bundle.css"}]},{"type":"text","value":". Those\nfiles were pretty huge containing all the code that was needed to create\na template app and any page inside it. Loading a single file takes time\nand also browsers had to evaluate the entire JS-file before it was ready\nto make the app fully functional."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"why-you-should-use-it","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#why-you-should-use-it","ariaLabel":"why you should use it permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Why you should use it?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The main benefit of code splitting is to reduce the code that is loaded\nfor any single page. That improves the performance, but even more\nimportantly, it makes it possible to add more navigational paths and\npage-variants to the codebase. For example, adding different kinds of\nListingPages for different types of listings makes more sense with\ncode-splitting. Without code splitting, new pages, features, and\nlibraries would have a performance impact on the initial page load of\nthe app and therefore SEO performance would drop too."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Note: currently, most of the code is in shared "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"src/components/"}]},{"type":"text","value":"\ndirectory and this reduces the benefits that come from code-splitting.\nIn the future, we are probably going to move some components from\nthere to page-specific directories (if they are not truly shared\nbetween different pages)."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"how-code-splitting-works-in-practice","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#how-code-splitting-works-in-practice","ariaLabel":"how code splitting works in practice permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"How code splitting works in practice"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you open "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/about"}]},{"type":"text","value":" page, you'll notice that there are several JS & CSS\nfiles loaded:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Main chunk"}]},{"type":"text","value":" (e.g. "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"main.1df6bb19.chunk.js"}]},{"type":"text","value":" &\nmain.af610ce4.chunk.css). They contain code that is shared between\ndifferent pages."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://twitter.com/wSokra/status/969633336732905474","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Vendor chunk"}]}]},{"type":"text","value":"\n(Currently, it's an unnamed chunk file. e.g. "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"24.230845cc.chunk.js"}]},{"type":"text","value":")"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Page-specific chunk"}]},{"type":"text","value":" (e.g. "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"AboutPage.dc3102d3.chunk.js"}]},{"type":"text","value":")"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"So, there are several chunk files that can be loaded parallel in the\nfirst page-load and also page-specific chunks that can be loaded in\nresponse to in-app navigation."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Naturally, this means that during in-app navigation there are now more\nthings that the app needs to load: "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"data"}]},{"type":"text","value":" that the next page needs and\n"},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"code chunk"}]},{"type":"text","value":" that it needs to render the data. The latter is not\nneeded if the page-specific chunk is already loaded earlier."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"preloading-code-chunks","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#preloading-code-chunks","ariaLabel":"preloading code chunks permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Preloading code chunks"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Route-based code splitting means that there might be a fast flickering\nof a blank page when navigation happens for the first time to a new\npage. To remedy that situation, FTW templates have forced the\npage-chunks to be\n"},{"type":"element","tagName":"a","properties":{"href":"https://loadable-components.com/docs/prefetching/#manually-preload-a-component","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"preloaded"}]},{"type":"text","value":"\nwhen the mouse is over "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"NamedLink"}]},{"type":"text","value":". In addition, "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Form"}]},{"type":"text","value":" and\n"},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Button"}]},{"type":"text","value":" components can have a property\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"enforcePagePreloadFor=\"SearchPage\""}]},{"type":"text","value":". That way the specified chunk is\nloaded before the user has actually clicked the button or executed form\nsubmit."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"route-configuration","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#route-configuration","ariaLabel":"route configuration permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Route configuration"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"To make the aforementioned preloading possible, the loadable component\nis directly set to \"component\" conf in routeConfigurations.js file:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── src\n    └── routeConfiguration.js"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"extrainfo","properties":{"title":"FTW-product has routeConfiguration.js file in a different location"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── src\n    └── routing\n        └── routeConfiguration.js"}]}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"text","value":"    "},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// const AuthenticationPage = loadable(() => import(/* webpackChunkName: \"AuthenticationPage\" */ './containers/AuthenticationPage/AuthenticationPage'));"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"path"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'/signup'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"name"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'SignupPage'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"component"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" AuthenticationPage"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"extraProps"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"tab"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'signup'"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"data-loading","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#data-loading","ariaLabel":"data loading permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Data loading"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"FTW templates collects "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"loadData"}]},{"type":"text","value":" and "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"setInitialValues"}]},{"type":"text","value":" Redux functions\nfrom\n"},{"type":"element","tagName":"a","properties":{"href":"https://github.com/erikras/ducks-modular-redux","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"modular Redux file"}]},{"type":"text","value":"\n(i.e. files that look like "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<SomePageComponent>"}]},{"type":"text","value":".duck.js). This happens\nin "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"pageDataLoadingAPI.js"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── src\n    └── containers\n        └── pageDataLoadingAPI.js"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Then those files can be connected with routing through route\nconfiguration."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"js"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-js"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-js"]},"children":[{"type":"text","value":"    "},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// import getPageDataLoadingAPI from './containers/pageDataLoadingAPI';"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","comment"]},"children":[{"type":"text","value":"// const pageDataLoadingAPI = getPageDataLoadingAPI();"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"path"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'/l/:slug/:id'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"name"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'ListingPage'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"component"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" ListingPage"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","literal-property","property"]},"children":[{"type":"text","value":"loadData"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" pageDataLoadingAPI"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"ListingPage"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"loadData"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"css-chunk-changes","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#css-chunk-changes","ariaLabel":"css chunk changes permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"CSS chunk changes"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"To ensure that every page-level CSS chunk has custom media queries\nincluded, those breakpoints are included through a separate file\n("},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"customMediaQueries.css"}]},{"type":"text","value":") and it is imported into the main stylesheet\nof every page."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"shell"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-shell"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-shell"]},"children":[{"type":"text","value":"└── src\n    └── styles\n        └── customMediaQueries.css"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"server-side-rendering-ssr","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#server-side-rendering-ssr","ariaLabel":"server side rendering ssr permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Server-side rendering (SSR)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When FTW templates receive a page-load call on server and the page is a\npublic one ("},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"\"auth\""}]},{"type":"text","value":" flag is not set in route configuration), the server\nwill render the page into a string and returns it among HTML code. This\nprocess has 4 main steps:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"server/dataLoader.js"}]},{"type":"text","value":" initializes store"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"It also figures out which route is used and fetches route\nconfiguration for it"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"If the configuration contains a "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"loadData"}]},{"type":"text","value":" function, the call is\ndispatched"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"As a consequence, the store gets populated and it can be used to\nrender the app to a string."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"build-directory","style":"position:relative;"},"children":[{"type":"element","tagName":"a","properties":{"href":"#build-directory","ariaLabel":"build directory permalink","className":["anchor","before"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Build directory"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Sharetribe-scripts dependency uses Webpack to build the application. It\ncopies the content from "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"public/"}]},{"type":"text","value":" directory into the "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"build"}]},{"type":"text","value":" directory\nand the Webpack build bundles all the code into files that can be used\nin production mode."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Code for server-side rendering is saved to "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"build/node"}]},{"type":"text","value":" directory."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Code for client-side rendering is saved to "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"build/static"}]},{"type":"text","value":" directory."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Both builds have also a "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"loadable-stats.json"}]},{"type":"text","value":" file, which basically\ntells what assets different pages need."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"server/importer.js"}]},{"type":"text","value":" exposes two\n"},{"type":"element","tagName":"a","properties":{"href":"https://loadable-components.com/docs/server-side-rendering/#collecting-chunks","target":"_blank","rel":["noopener","noreferrer"]},"children":[{"type":"text","value":"ChunkExtractors"}]},{"type":"text","value":" -\none for web and another for node build."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"server/index.js"}]},{"type":"text","value":" requires the entrypoint for the node build, extracts\nrelevant info, and passes them to "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"dataLoader.loadData()"}]},{"type":"text","value":" and\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"rendered.render()"}]},{"type":"text","value":" calls."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"webExtractor (ChunkExtractor for the web build) is used to collect\nthose different code chunks (JS & CSS files) that the current\npage-load is going to need."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In practice, "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"renderApp"}]},{"type":"text","value":" function wraps the app with\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"webExtractor.collectChunks"}]},{"type":"text","value":". With that the webExtractor can figure\nout all the relevant loadable calls that the server uses for the\ncurrent page and therefore the web-versions of those chunks can be\nincluded to rendered pages through "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"<script>"}]},{"type":"text","value":" tags."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]}],"data":{"quirksMode":false}},"headings":[{"value":"Background info","depth":2},{"value":"What is code splitting","depth":2},{"value":"Why you should use it?","depth":3},{"value":"How code splitting works in practice","depth":2},{"value":"Preloading code chunks","depth":3},{"value":"Route configuration","depth":3},{"value":"Data loading","depth":4},{"value":"CSS chunk changes","depth":3},{"value":"Server-side rendering (SSR)","depth":2},{"value":"Build directory","depth":3}]}},"pageContext":{"slug":"how-code-splitting-works-in-ftw","category":"ftw-routing"}},
    "staticQueryHashes": ["3794076007","439097193","717698143"]}