Skip to content
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

Merged
merged 5 commits into from Apr 7, 2017
Merged

Conversation

olamothe
Copy link
Member

@olamothe olamothe commented Apr 6, 2017

Copy link
Member

@malaporte malaporte left a 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.

@olamothe olamothe changed the title Webpack, TypeScript, Code splitting Webpack, TypeScript, and Code splitting Apr 7, 2017
Copy link
Contributor

@francoislg francoislg left a 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 :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"performance factors"

Copy link
Collaborator

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,
Copy link
Contributor

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) {
Copy link
Contributor

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 :
Copy link
Contributor

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) :
Copy link
Contributor

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 :
Copy link
Contributor

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 :
Copy link
Contributor

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 :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space + colon

Copy link
Collaborator

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

Copy link
Collaborator

@amoreauCoveo amoreauCoveo left a 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"
Copy link
Collaborator

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/).
Copy link
Collaborator

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 :
Copy link
Collaborator

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.
Copy link
Collaborator

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.
Copy link
Collaborator

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.
Copy link
Collaborator

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.
Copy link
Collaborator

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 :
Copy link
Collaborator

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.
Copy link
Collaborator

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).
Copy link
Collaborator

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.

@olamothe olamothe merged commit d08f65e into coveo:gh-pages Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants