Skip to content

Commit

Permalink
Update benefits-of-templates.md (#716)
Browse files Browse the repository at this point in the history
Converted West-Flemish English to standard English, removed parts that do not focus on the essence of the blog post
  • Loading branch information
xPhentom authored Dec 10, 2023
1 parent e3fc98c commit 2189c4c
Showing 1 changed file with 18 additions and 55 deletions.
73 changes: 18 additions & 55 deletions docs/blog/benefits-of-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,31 @@ Published: 2023-12-08

# Benefits of using JSX for templates

Since v2 `Kubb` has been starting to use JSX templates to create its generated code. Before we used template string but that was not always easy when you had a couple of if statements(not easy to read/understand) and it was also becoming harder to maintain.
Since v2, `Kubb` has been starting to use JSX templates to create its generated code. Previously, we used template strings which became harder to maintain due to increasing complexity.

Because of that we explored if it was possible to use JSX and React to create our generated code. As a front-end developer we use React on a daily base and to use JSX as a template engine would be really nice.
This made us wonder if it was possible to use React and JSX to create our templates.

But to get into details, you need to understand some basic concepts.
## Concepts

## What is template engine?
### What is a template engine?

A template engine is a software program designed to combine templates with a data model(props) to produce a document or output. The language used to write these templates is called a template language. The resulting document can be a web page, a document, or even source code. One specific use case for template engines is source code generation.
A template engine is a software program designed to combine templates with a data model to produce a document or output. The language used to write these templates is called a template language. The resulting document can be a web page, a document, or even source code. One specific use case for template engines is source code generation.

## What is source code generation?
Some well known template engines are [Mustache](https://mustache.github.io/), [Handlebars](https://handlebarsjs.com/), and [EJS](https://ejs.co/). To create Javascript/ you can also use the [TypesScript compiler API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API) to create JavaScript/TypeScript and the OpenApi TypeScript generator uses [Handlebars](https://handlebarsjs.com/).

Source code generation is a technique used in programming where code is automatically generated based on a set of pre-defined rules or templates. This technique can save developers time and effort by automating repetitive tasks and reducing the likelihood of errors. Code generation can be used for a variety of purposes, including creating boilerplate code, generating code from models, and producing code for specific platforms or frameworks. Many commonly used tools, such as graphql, OpenAPI and gRPC, use code generation under the hood.
### What is source code generation?

## Template engines as of today.
Source code generation is a technique used in programming where code is automatically generated based on a set of pre-defined rules or templates. This technique can save developers time and effort by automating repetitive tasks and reducing the likelihood of errors. Code generation can be used for a variety of purposes, including creating boilerplate code, generating code from models, and producing code for specific platforms or frameworks. Many commonly used tools, such as graphql, OpenAPI, and gRPC, use code generation under the hood.

::: tip
For example, the OpenAPI TypeScript generator uses [Handlebars](https://handlebarsjs.com/).
:::

Today there are a couple of template engines that exists like [Mustache](https://mustache.github.io/), [Handlebars](https://handlebarsjs.com/) and [EJS](https://ejs.co/). Next to that you can also use the [TypesScript compiler API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API) to create JavaScript/TypeScript.

### Rapini

An example of this is [rapini](https://github.com/rametta/rapini/blob/main/src/react-query/generator.ts).

```typescript
function makeImportAxiosInstanceTypeDeclaration() {
return ts.factory.createImportDeclaration(
/*modifiers*/ undefined,
/*importClause*/ ts.factory.createImportClause(
/*isTypeOnly*/ true,
/*name*/ undefined,
/*namedBindings*/ ts.factory.createNamedImports([
ts.factory.createImportSpecifier(
/*isTypeOnly*/ false,
/*propertyName*/ undefined,
/*name*/ ts.factory.createIdentifier('AxiosInstance'),
),
ts.factory.createImportSpecifier(
/*isTypeOnly*/ false,
/*propertyName*/ undefined,
/*name*/ ts.factory.createIdentifier('AxiosRequestConfig'),
),
]),
),
/*moduleSpecifier*/ ts.factory.createStringLiteral('axios'),
/*assertClause*/ undefined,
)
}
```
## The search for kubb's search engine

### TypeScript compiler

The [TypesScript compiler API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API) is really nice and powerful to use but not easy to setup. This has a hard learning curve and would not fit our needs. <br/>
We've looked into [TypesScript compiler API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API), but it has a steep learning curve and it does not fit our needs.<br/>

### Ink

Then we found [Ink](https://github.com/vadimdemedes/ink) which is a CLI tool that uses React/JSX as their template engine. As of how they describe it:
Our search brought us to the project named [Ink](https://github.com/vadimdemedes/ink) which is a CLI tool that uses React/JSX as its template engine. The project's bio says the following:

> React for CLIs. Build and test your CLI output using components.
Expand Down Expand Up @@ -98,18 +64,16 @@ render(<Counter />)
<br/>
After some digging around in their code we came up with a solution that would benefit Kubb.

We can use JSX as the template engine and provide some hooks that could be used to access some `Kubb` specific behaviour. <br/>
We can use JSX as the template engine and provide some hooks that could be used to access some `Kubb` specific behavior. <br/>

Getting the `PluginManager` instance or access to the `FileManager` for example. And when using the `@kubb/swagger` plugin, we could also provide some hooks that would return the current operation/path/oas instance. <br/>
So a lot of things that are possible so we started with a small POC for one of our plugins and as of today(dec 2023), we are using templates in all our plugins.
The hooks will allow the engine to use the `PluginManager` instance or access the `FileManager` for example. When using the `@kubb/swagger` plugin, we could also provide hooks that would return the current operation/path/oas instance. <br/>
We saw a lot of opportunities in this approach, so we started with a small POC for one of our plugins. As of today(december 2023), we are using JSX templates in all our plugins.

## Examples

### @kubb/swagger-client

This is what we had before with template strings and the issue here is already that it's not easy to read. One way of making this better could be to split up every part but then you are losing the simplicity and also you need to 'prop drill'.<br/>

With the React/JSX example we could use `context` and define some options in the root.
Below you can find an example of our previous templates. The code is not easy to read. An improvement could be to split the code up, but this will have to be paired with prop drilling, which is something we wish to avoid.<br/>

```typescript
const code = `
Expand All @@ -126,7 +90,8 @@ export function ${name} <${generics.join(', ')}>(${params}): Promise<TData> {
`
```

If you then compare this with an example with JSX/React, you can already see it's easier to read and adding if structures will also be easier with the JSX syntax:
With the React/JSX example, we could use `context` and define some options in the root.
If you compare the previous template with an example using JSX/React, you can already see it's easier to read. Adding if structures will also be easier with the JSX syntax:

`{ shouldBeTrue === true ? <Function/> : undefined }`.

Expand All @@ -144,8 +109,6 @@ If you then compare this with an example with JSX/React, you can already see it'
</Function>
```

At this stage we only did the refactor for the function logic and keeping the template string for the client logic.

## Overriding with templates

We have made a guide in how you can override templates in one of our plugins: [templates the guide](/guide/tutorial/templates).
We've made a guide on how you can override templates in our plugins: [templates the guide](/guide/tutorial/templates).

1 comment on commit 2189c4c

@vercel
Copy link

@vercel vercel bot commented on 2189c4c Dec 10, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

kubb – ./

kubb-git-main-kubb.vercel.app
www.kubb.dev
kubb-kubb.vercel.app
kubb.dev

Please sign in to comment.