It hasn’t been long since the release of 0.3.0, and here we are with another minor release – version 0.4.0. Yes, backward compatibility is broken again, but I believe the reason is a good one.
I have significantly reworked how attributes like types and relations are used in the Rattus ORM code. While last release's changes were related to the names of decorators and methods, this time I focused on what is probably the most important thing for frontend developers - the size of the bundle.
What Has Been Done
I noticed that even if you just create a database and add a model with no keys, some types and even relations would still be included in your bundle. This is a legacy of Vuex ORM Next.
This happened because for some model field operations, we need to
know precisely what we are dealing with: type, relation, and
sometimes even the specific type or relation. In Vuex ORM Next,
this was done using instanceof
checks, which require the code
of the specific class. In version 0.4.0, @rattus-orm/core
has been revised to avoid this.
However, that’s not all. If you’re not using decorators to describe
models, you know that each type or relation is a static method
of the Model
class:
export class User extends Model {
static entity = 'user'
static fields () {
return {
id: this.uidField(),
name: this.stringField(''),
age: this.numberField(0)
}
}
}
This means that the most basic class always includes all types and relations!
In version 0.4.0, this has also been revised. Now to describe a field, you need to call a separate function instead of a static method:
export class User extends Model {
static entity = 'user'
static fields () {
return {
id: createUidField(this),
name: createStringField(this, ''),
age: createNumberField(this, 0)
}
}
}
The downside here is minor: we need to pass the class constructor context to the function. This is always the first argument in all methods, and the rest follow the same order as before.
The same applies to relations – they are now separate functions with the constructor context as the first argument.
This change means we only include what is actually used by your application in the bundle.
Results
Let’s look at the results. For building the file in this experiment, I use Bun v1.1.30.
Model Without Fields
First, let’s see what we have with the following source file:
import { Model } from '@rattus-orm/core'
class User extends Model {}
Let’s build it using version 0.3.0:
$ bun build size-test.ts --minify --outfile size-test-built.js > /dev/null \
$ && npx tiny-file-size --gzip --brotli ./size-test-built.js
size-test-built.js 19.87 KB │ gzip: 5.17 KB │ brotli: 4.61 KB
We see that the file size is 19.87 KB uncompressed and 4.61 KB compressed with Brotli.
What does it look like with version 0.4.0:
$ bun build size-test.ts --minify --outfile size-test-built.js > /dev/null \
$ && npx tiny-file-size --gzip --brotli ./size-test-built.js
size-test-built.js 12.34 KB │ gzip: 3.77 KB │ brotli: 3.37 KB
The file size is reduced by 37.8% uncompressed and about 27% compressed. Looks good!
Model with a Single StringField
Now let’s add a name
property to our model – it will be a string.
import { Model } from '@rattus-orm/core'
// v0.3.0
import { StringField } from '@rattus-orm/core/decorators'
// v0.4.0
import { StringField } from '@rattus-orm/core/field-types'
class User extends Model {
@StringField('')
public name: string
}
Build with 0.3.0:
$ bun build size-test.ts --minify --outfile size-test-built.js > /dev/null \
$ && npx tiny-file-size --gzip --brotli ./size-test-built.js
size-test-built.js 20.38 KB │ gzip: 5.41 KB │ brotli: 4.82 KB
And with 0.4.0:
$ bun build size-test.ts --minify --outfile size-test-built.js > /dev/null \
$ && npx tiny-file-size --gzip --brotli ./size-test-built.js
size-test-built.js 13.51 KB │ gzip: 4.21 KB │ brotli: 3.77 KB
The file is about 33% smaller uncompressed and 22% smaller compressed.
In conclusion, the bundle size is reduced by roughly a third. Naturally, if you use all data types and relations, the bundle size will be the same as in version 0.3.0. However, the goal of this release is to benefit those who use only specific parts of Rattus ORM.