RAKSUL TechBlog

ラクスルグループのエンジニアが技術トピックを発信するブログです

Apply code-splitting in Novelty front-end side

Hi, I am Nuong, working as a Front-End (FE) developer for the Novelty team. Novelty is an e-commerce website that allows small and medium businesses to do on-demand printing for novelty items. At Novelty, we care a lot about delivering the best user experiences and we are always improving the performance of our website, to make it as fast as possible. In this post, I would like to share how we implement code-splitting for our Javascript on the frontend side to speed up our website.

In the Novelty project, We build our frontend using the VueJs framework. As a typical Vue project, there are many modules with components that represent many features on the UI. However, Novelty is slightly different from other common Vue single page application (SPA) projects, instead of having the FE handling all routing, we still rely on Rails to do our routing for us, and only mounted the necessary components on each page load. Each module on the FE side will be in charge of supporting rendering data for a corresponding web page that is returned from the server-side. The practical approach we applied in integrating the FE code to Rails is quite straightforward, the FE code will be bundled into JS files and those files will be added to the web page similar to other Javascript sprinkles.

Our FE code's bundling pipeline:

Insert to every web page:

The problem

In the beginning, the FE code was bundled into one single file app.jsand this file was added to every webpage that is using FE code for rendering data. As time passed, the project became larger, more features were added, and the FE code size increased as well. As a result, we had to think about the potential issues that could happen with the current bundling method:

  • The size of app.jsbecomes too large: The whole FE code turns into a single file, its size soon be enormous network payload when loaded in the webpage, and increasing the loading time of the page. ( Https://web.dev/total- byte-weight / ).
  • Unused code is included in every page: Each page just needs one corresponding part of code but we always load others along with that.
  • app.js cannot be cached since its contents keep changing every time we change the source code hence the app becomes much slower right after any deployment.
  • Unscoped error: One error while initiating code will affect all pages even if some pages don't even use this block of code.

        Solution

        To solve the above-mentioned problems, we decided to go with code-splitting. This method is not a new technique, it is strongly recommended to apply widely in websites building with ReactJs, VueJs, and other JS frameworks. Code-splitting is a feature supported by bundler Webpack, which we are currently using in the Novelty project, so why don't we take advantage of it? After our plan is clear, we are going to separate code for each router path instead of putting everything in one file as before:

        Then we will add those output assets to corresponding web pages. But at this time, the output assets from FE are still added to the web page templates manually. It did not really matter with only one app.jsfile but manually adding many assets to many templates. And managing the changes is a big challenge. We needed to think about automating this process, and it could need more comprehensive work to achieve this goal, including server-side and FE side work. For that reason, we decided to implement it step by step.

        After analyzing the FE bundle code, we decided to separate only the code for editor page for several reasons:
        • The editor page is using a different template on our server-side code, so it is easy to change from adding app.jsto adding others.
        • The editor page requires the huge fabric.jslib, its size is more than 900KB, which accounts for a significant proportion of the bundled file while it is only useful for the editorpage, not others.

          And what we finally implemented:

          • Created two entries file for webpack
            • editor.entry.ts for editor page.
            • app.entry.ts for the rest pages.
          • Optimized bundle for each entry using optimization option:
            ...
            optimization: { 
              splitChunks: { 
                chunks: 'all', //Optimize for all types of chunks. 
                maxInitialRequests: 2, //Expect maximum number of parallel requests at an entry point is 2 
                minSize: 0,// No restriction 
                maxSize: 0, //No restriction 
                cacheGroups: { 
                  fabric: { // bundle fabric to separated chunk so we can apply longer cache for this file. 
                    test: /[\\/]node_modules[\\/](fabric)[\\/]/, 
                    name: 'fabric', 
                    enforce: true 
                  } 
                } 
              }
            }
            ...

            Output assets:

          • Added output assets to the web page templates.

          After implemented code-splitting, we used Chrome's development tool to measure the effects :

          💡
          Testing environment: Server: Novelty QA2. Date: Sep 28th, 2020. Minify: Unminified

          The file size that we need to deliver through the network is considerably reduced:

          And the performance reported by the Lighthouse tool is positive as well: Editor page:

          Other pages:

          Conclusion

          The result of splitting js code for the editor page is quite positive, even though it is limited to only parts of the site this step inspires us to take more actions to improve the performance of Novelty as much as possible.