New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webpack, TypeScript, and Code splitting #127
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be "TypeScript, and Code Splitting" if you don't want @amoreauCoveo to rain fire upon you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:gg: :wp: 👍
|
||
## Code splitting | ||
|
||
I would say there are 3 big performance factor when dealing with a modern web application that does heavy use of JavaScript : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"performance factors"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that makes heavy use
remove space before colon
|
||
```typescript | ||
{ | ||
'Searchbox' : (element: HTMLElement)=> Searchbox, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing space :)
Then, on initialization, when we scan the DOM and when we find a `div` that has the class name `CoveoSearchbox`, we call the correct constructor function with the needed parameters. | ||
|
||
```typescript | ||
function createComponent(element: HTMLElement, id : string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
id: string
|
||
To achieve that, we created a `Lazy` file for each component. | ||
|
||
Once again, if we use `Searchbox` as an example : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space + colon
|
||
As an example, let's take the `Searchbox` component. | ||
|
||
First, we have the code itself for the `Searchbox` class (in TypeScript) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No space before colon in English
|
||
What happens when we call `Initialization.registerComponent(Searchbox)` is that, in an internal data structure, we simply associate the `Searchbox.ID` to it's constructor. | ||
|
||
So we get something like this : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No space before colon in English
|
||
What we ended up designing is, instead of associating the ID with a constructor, we want to have an ID associated with a function that returns a `Promise` of a component. | ||
|
||
Something like this : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again space + colon
|
||
The `Searchbox.js` file will contain all the code needed for the `Searchbox` component to function properly, while the `CoveoJsSearch.js` file will only contain the needed code to download the `Searchbox` component. | ||
|
||
Now, when we scan the DOM and find a `div` that match `Searchbox`, we need to do something like this : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space + colon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
find a div
that matches
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice blogpost and great feature to have!
--- | ||
layout: post | ||
|
||
title: "A story of TypeScript, webpack, and code splitting" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What a wonderful sight to see this Oxford comma :)
|
||
In my last blog post, I talked about how we use [webpack](https://webpack.js.org) at Coveo, to improve our development process. | ||
|
||
One of the most powerful feature offered by is [code splitting](https://webpack.js.org/guides/code-splitting/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
most powerful features offered by it is
|
||
## Code splitting | ||
|
||
I would say there are 3 big performance factor when dealing with a modern web application that does heavy use of JavaScript : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that makes heavy use
remove space before colon
|
||
I would say there are 3 big performance factor when dealing with a modern web application that does heavy use of JavaScript : | ||
|
||
- Initial load time before the end user is able to interact with your application. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have *
instead of -
for a real bullet list
The initial load time . . .
- The rendering speed, and how much client side logic your code has to execute. | ||
- How fast the backend can process the various requests you are hammering it with. | ||
|
||
Code splitting is used to improve the first of those 3 points. The basic logic is relatively simple : minimize the amount of code needed for your application to "start", and progressively load more JavaScript as the user needs access to more feature while they are using your application. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove space before colon
|
||
So, for example, we offer a `Searchbox` component, a `Pager` component, a `ResultList` component, etc. We also offer some more "exotic" components, which are useful in their own rights, but either complex (so they need a lot of code to function), or used in some very particular deployments. A good example is the `Facet` component, which offers advanced filtering capabilities, but requires a good amount of client side code to function. | ||
|
||
Since we do not know ahead of time which combination of component will be used in a page (as every implementation is different), we ship a single JavaScript file, containing the code for every components. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for every component (no s)
either that or "for all components"
|
||
``` | ||
|
||
What happens when we call `Initialization.registerComponent(Searchbox)` is that, in an internal data structure, we simply associate the `Searchbox.ID` to it's constructor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to its (no apostrophe)
|
||
The `Searchbox.js` file will contain all the code needed for the `Searchbox` component to function properly, while the `CoveoJsSearch.js` file will only contain the needed code to download the `Searchbox` component. | ||
|
||
Now, when we scan the DOM and find a `div` that match `Searchbox`, we need to do something like this : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
find a div
that matches
} | ||
``` | ||
|
||
Only when we call the `getLazyComponent` function does it downloads the associated component JavaScript file. A component is also only downloaded once. This means that even if the search page has 10 `Searchbox`, we will still only download it a single time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it download (no s)
|
||
## Conclusion | ||
|
||
The page load time will now linearly increase with the page complexity, where simple search pages that uses the most simple components will be faster that very complex one. The performance gain is also much more substantial if the user has a slow internet connection, or a less powerful device to parse the JavaScript code (a mobile device, for example). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
faster than very complex ones.
Update date.
Preview :
https://olamothe.github.io/source.coveo.com/