@traveloka/core/next
This module handles how we interplay our app with native Next.js interface.
Important files
-
Common next config (next.config.js)
packages/core/next/config.js
-
Templates for next special pages:
_documentand_app.packages/core/next/withTravelokaDocument.tsx— For_document(this governs how we render our HTML page, like what<script>and<meta>tags and to include in the page).packages/core/next/withTravelokaApp.tsx— For_app(note that this includes all the providers that we need on the page).
-
Data-fetching helpers for your page
packages/core/next/withTravelokaPage.tsx— Backwards compatibility for pages that still usesgetInitialProps(from earlier versions of Next.js). You should no longer use this fuction.packages/core/next/data-fetching/staticProps.ts— Helper function for use withgetStaticProps. Note that this internally callspackages/core/next/data-fetching/getSharedStaticProps.tspackages/core/next/data-fetching/getSharedServerProps.ts— Helper function for use withgetServerSideProps, with default Next.js behavior.packages/core/next/data-fetching/cacheableServerProps.ts— Helper function for use withgetServerSideProps, with caching enabled by default (for your safety, we do not expose user/request-specific data inside thegetServerSidePropscontext, so the page can be cached by CDN). Note that this internally callspackages/core/next/data-fetching/getSharedCacheableServerProps.ts
-
Routing utilities
packages/core/next/routing/NextRouter.tsx— replacement of 'next/router` to prevent "dev-only" routes to become accessible to the general public (Next.js does not have this context, and without this helper, using Next's default router will allow client-side navigation to that page)packages/core/next/routing/NextLink.tsx— replacement component fornext/link, to address similar issue like the abovepackages/core/next/routing/usePrefetchJs.ts— Hook for cross-service JS/CSS chunk prefetching. Loads a pre-built manifest (prefetch_js.js) from CDN and injects<link rel="prefetch">tags for all chunks needed by a target route in another service. For same-service prefetch, delegates to Next.js built-inrouter.prefetch().
How this module works
Rendering page
Data fetching function is run in this order (top-to-bottom)
- Your page's data fetching function, e.g.
getStaticProps- Note that by using our data-fetching helpers like
staticPropsorcacheableServerProps, we auto-generate additional props (we call it "shared props" that is required on the_app) level. - By setting special props like
statusCode, you can configure your response
- Note that by using our data-fetching helpers like
getInitialPropsinsidewithTravelokaDeocument- Only runs in server-side (not during client-side navigation)
- Generally it doesn't have something very interesting for us
- The renderer inside
withTravelokaApp- This fires some monitoring/telemetry/tracking we have in place
- This configures the reponse code based on the
statusCodeprops returned - This renders the providers and the content of your page.
Shared props
"Shared props" are the shape that withTravelokaApp expects a page props should have. See the definition of SharedPageProps type to see what they are.
App context
"App context" gives the context to how we render a page: which locale/currency it is, what interface it is, which feature controls are active, etc.
We pass this (raw) app context to the getStaticProps data-fetching function of staticProps and cacheableServerProps. For getServerSideProps, you will naturally call getSharedServerProps which returns this object as one of its property.
NOTE: There is "normalized" app context via the use of
packages/core/next/normalizeAppContext.ts. Apparently, this is only used insidewithTravelokaPageand is most likely only there for backwards-compatibility with early adoption of TVLK5. (?)
Next context
Next exposes a different ctx object depending on the type of data-fetching function object you used (for example, in getStaticProps, ctx.req would be a dummy request object with limited props).
Due to how our internal code depends on certain properties of req (e.g. req.get), and it was a huge effort to make the consumers of this req function aware whether the page is a server-rendered or a static function, we came along to just "normalize" the req functions to have all the properties that we might use (defining a "mock" but sensible value for the static page).
Note that we have different "normalizer" functions depending on whether you are using getStaticProps, getServerSideProps, or cacheableServerProps (see packages/core/next/data-fetching/normalizeNextContext.ts).
normalizeNextContext— Isomorphic form for API callsstaticCtxToNextCtx— ForstaticPropsserverSideContextToNextContext— ForgetServerSidePropsserverSideContextToCacheableNextContext— ForcacheableServerProps