airbnb / hypernova

A service for server-side rendering your JavaScript views
MIT License
5.82k stars 211 forks source link

Loadable Component integration #196

Open gempir opened 2 years ago

gempir commented 2 years ago

Loadable components is arguably the most popular and most established lazy loading framework for react.

It also supports server side rendering, but it's unclear how I could implement it with hypernova.

https://loadable-components.com/docs/server-side-rendering/

This is the code suggested

import { ChunkExtractor } from '@loadable/server'
// This is the stats file generated by webpack loadable plugin
const statsFile = path.resolve('../dist/loadable-stats.json')
// We create an extractor from the statsFile
const extractor = new ChunkExtractor({ statsFile })
// Wrap your application using "collectChunks"
const jsx = extractor.collectChunks(<YourApp />)
// Render your application
const html = renderToString(jsx)

That does not fit into hyernova's concept though.

I think the trick here is reading the stats.json file and getting the component out of there with all it's chunks and then returning that in hypernova's getComponent function.

Has anyone implemented this? Is this even possible?

Example entry in stats.json

{
    "desktop/ProductDetailPage": {
        "name": "desktop/ProductDetailPage",
        "chunks": [
            "defaultVendors-node_modules_react-redux_es_index_js-node_modules_react_jsx-runtime_js",
            "defaultVendors-node_modules_babel_runtime-corejs3_core-js-stable_reflect_construct_js-node_mo-3cb5d8",
            "defaultVendors-node_modules_axios_index_js-node_modules_hypernova_lib_index_js-node_modules_r-55ddae",
            "defaultVendors-node_modules_loadable_component_dist_loadable_esm_js-node_modules_babel_runtim-b0fd6c",
            "defaultVendors-node_modules_body-scroll-lock_lib_bodyScrollLock_esm_js-node_modules_qrcode_re-e0a433",
            "defaultVendors-node_modules_marked_lib_marked_js",
            "defaultVendors-node_modules_recharts_es6_cartesian_CartesianGrid_js-node_modules_recharts_es6-7e21ec",
            "defaultVendors-node_modules_photoswipe_dist_photoswipe_js-node_modules_react-router-dom_node_-765712",
            "common-js__hypernova_hypernova-react_js",
            "common-js_actions_updateSessionAction_ts-js_components_common_ErrorBoundary_tsx-js_components-fd7b57",
            "common-js_components_common_CTAButton_jsx-js_components_common_LoadableWrapper_tsx-js_enumera-085e65",
            "common-js_actions_addToWatchListAction_js-js_actions_loginAction_ts-js_actions_removeFromWatc-5aef14",
            "common-js_entrypoints_desktop__Content_jsx-js_entrypoints_desktop__Header-19b13a",
            "common-js_components_desktop_Common_ProductTile_ProductTileDefault_tsx",
            "common-js_actions_addToCartAction_ts-js_actions_customerReview_ts-js_components_common_Delive-0140d8",
            "common-js_components_common_CIElements_Checkbox_jsx-js_components_common_CtaButtonNew_tsx-js_-014156",
            "common-js_components_common_PriceHistory_Graph_tsx-js_components_common_PriceHistory_Navigati-fa65de",
            "common-js_components_desktop_ProductDetail_component_AddToWatchList_tsx-js_components_desktop-3c5fcb",
            "common-js_components_desktop_ProductDetail_component_ImageViewer_jsx-js_components_desktop_Pr-98cfed",
            "common-js_components_desktop_ProductDetail_component_QuestionsAndAnswers_QuestionsAndAnswers_-7188d8",
            "common-js_components_common_AppDiscountPromotionBanner_tsx-js_components_common_RouterScrollR-265ac8",
            "desktop/ProductDetailPage"
        ],
        "assets": [
            {
                "name": "defaultVendors-node_modules_react-redux_es_index_js-node_modules_react_jsx-runtime_js.237fa9caf96de3b092d6.js"
            },
            {
                "name": "defaultVendors-node_modules_babel_runtime-corejs3_core-js-stable_reflect_construct_js-node_mo-3cb5d8.c8ddf2979bdc82ee921d.js"
            },
            {
                "name": "defaultVendors-node_modules_axios_index_js-node_modules_hypernova_lib_index_js-node_modules_r-55ddae.da1935fe3adc8008ec9d.js"
            },
            {
                "name": "defaultVendors-node_modules_loadable_component_dist_loadable_esm_js-node_modules_babel_runtim-b0fd6c.fdfa81d92030ee9ae8ef.js"
            },
            {
                "name": "defaultVendors-node_modules_body-scroll-lock_lib_bodyScrollLock_esm_js-node_modules_qrcode_re-e0a433.27739f84a6e652a81f1b.js"
            },
            {
                "name": "defaultVendors-node_modules_marked_lib_marked_js.b8cc2a547fa853d24ff7.js"
            },
            {
                "name": "defaultVendors-node_modules_recharts_es6_cartesian_CartesianGrid_js-node_modules_recharts_es6-7e21ec.2d737089da78fb511217.js"
            },
            {
                "name": "defaultVendors-node_modules_photoswipe_dist_photoswipe_js-node_modules_react-router-dom_node_-765712.e3ee481e14980e50af79.js"
            },
            {
                "name": "common-js__hypernova_hypernova-react_js.f46a13c9b9ec301e7d75.js"
            },
            {
                "name": "common-js_actions_updateSessionAction_ts-js_components_common_ErrorBoundary_tsx-js_components-fd7b57.b130ce635d93ecd0caab.js"
            },
            {
                "name": "common-js_components_common_CTAButton_jsx-js_components_common_LoadableWrapper_tsx-js_enumera-085e65.28250a2f668a853e0abb.js"
            },
            {
                "name": "common-js_actions_addToWatchListAction_js-js_actions_loginAction_ts-js_actions_removeFromWatc-5aef14.05247e44355c0c5069d5.js"
            },
            {
                "name": "common-js_entrypoints_desktop__Content_jsx-js_entrypoints_desktop__Header-19b13a.1a98c84e033017ddcb15.js"
            },
            {
                "name": "common-js_components_desktop_Common_ProductTile_ProductTileDefault_tsx.0b4e4ee0f9fb06076041.js"
            },
            {
                "name": "common-js_actions_addToCartAction_ts-js_actions_customerReview_ts-js_components_common_Delive-0140d8.aa076da5383654f0c5ab.js"
            },
            {
                "name": "common-js_components_common_CIElements_Checkbox_jsx-js_components_common_CtaButtonNew_tsx-js_-014156.362e9fe541de2b114828.css"
            },
            {
                "name": "common-js_components_common_CIElements_Checkbox_jsx-js_components_common_CtaButtonNew_tsx-js_-014156.f0316407dc955aff5587.js"
            },
            {
                "name": "common-js_components_common_PriceHistory_Graph_tsx-js_components_common_PriceHistory_Navigati-fa65de.fb3c33e8a1e0de247aa8.js"
            },
            {
                "name": "common-js_components_desktop_ProductDetail_component_AddToWatchList_tsx-js_components_desktop-3c5fcb.ab37a26c2f91e9295608.css"
            },
            {
                "name": "common-js_components_desktop_ProductDetail_component_AddToWatchList_tsx-js_components_desktop-3c5fcb.fcdabee3dc2462c97a4a.js"
            },
            {
                "name": "common-js_components_desktop_ProductDetail_component_ImageViewer_jsx-js_components_desktop_Pr-98cfed.10ae1db6f9b33c850fb4.css"
            },
            {
                "name": "common-js_components_desktop_ProductDetail_component_ImageViewer_jsx-js_components_desktop_Pr-98cfed.c7b08e553b7e013c9b70.js"
            },
            {
                "name": "common-js_components_desktop_ProductDetail_component_QuestionsAndAnswers_QuestionsAndAnswers_-7188d8.10128e10f20875b5e37d.js"
            },
            {
                "name": "common-js_components_common_AppDiscountPromotionBanner_tsx-js_components_common_RouterScrollR-265ac8.16ef7fc2b8ce4afaf1a7.js"
            },
            {
                "name": "desktop/ProductDetailPage.64fda021634f643e7c30.css"
            },
            {
                "name": "desktop/ProductDetailPage.da943256ae25da9f42dd.js"
            }
        ],
        "filteredAssets": 0,
        "assetsSize": null,
        "filteredAuxiliaryAssets": 62,
        "auxiliaryAssetsSize": null,
        "children": {},
        "childAssets": {}
    }
}