v0.24.1 #784
bitspittle
announced in
Announcements
v0.24.1
#784
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
This is a jam packed release featuring long-planned tweaks to the network APIs as well as new lucide and material symbol icons!
In the previous release, we revisited the backend network APIs to support multipart requests, but due to backwards compatibility, we could not yet touch the frontend APIs, as the method names we wanted to use were already taken. Instead, we deprecated them.
In this release, those frontend changes are now done! Potentially, there may be some codebases out there which might break with this change, but they would have been ignoring scary deprecation warnings for a while now. As these methods are not used by most Kobweb users, we decided to incrementally update the release version instead of put out a new major version.
If you are a developer with a fullstack website and you get warnings after updating, please review the
Notessection below about migrating. We did our best to tell the IDE how to automatically update your deprecated code to the latest versions of the API, but it doesn't always do the best job.Important
Planning to upgrade? Review instructions in the README.
Changes
Frontend
Icons!
Notessection below for more details.Introduced a slew of Kotlin-idiomatic network request APIs.
Notessection below for more details.CSS Modifiers
Modifier.animation { delay(...) }object-positionpropertytext-wrappropertytab-sizepropertyimage-renderingpropertyimage-orientationpropertyTransform.Nonevalue (and global keywords, e.g.Transform.Inherit)Improved CSSPosition output, now producing simpler output
CSSPosition(Edge.Left)is now just"left", and not"left 0% top 50%"Worker
Made network APIs more flexible so they could be called from a worker script.
windowthrows a runtime exception. So now....window.fetch(...)self.fetch(...)Added support for launching coroutines inside a worker context
CoroutineContext(window.asCoroutineDispatcher()).launch { ... }CoroutineContext(self.asCoroutineDispatcher()).launch { ... }Backend
You can now expose system properties from your build script to your backend server
Notessection below for more details.Added support for multiple headers on the same request
When you run
kobweb run --layout=staticin dev mode, it will now return 404 on dynamic pages.Gradle
KOBWEB_EXPORT_BROWSER_PATHor directly in your site's build script viakobweb.app.export.browser.path.Notes
Material Symbols
Kobweb has supported Material Design Icons for a long time, but Google deprecated those and replaced them with Material Symbols instead. If you are using MDI in your own project, you may want to consider migrating over if possible, as presumably MDI is mostly stale now and future work will go into MS.
// site/build.gradle.kts kotlin { sourceSets { jsMain.dependencies { implementation(libs.silk.icons.ms) } } }At that point, you can reference them in your code! Material Symbol icon methods begin with the
Msprefix.For example, if you wanted to use the mail icon, find the corresponding method with the same name:
MsMail()You can also pass in a style, with one of three values (where outline is the default):
Lucide Icons
Check out the official page to see their list of icons.
To use these in your project, simply add the following dependency to your build script:
// site/build.gradle.kts kotlin { sourceSets { jsMain.dependencies { implementation(libs.silk.icons.lucide) } } }At that point, you can reference them in your code! Lucide icon methods begin with the
Lucideprefix.For example, if you wanted to use the mail icon, find the corresponding method with the same name:
LucideMail()The full API for that method is:
so feel free to play with those values in your own site.
Backend system properties
If you are running a kobweb server and want to expose some values to it from the build script, we made this easy:
kobweb { app { server { systemProperties.put("example.key", "example.value") } } }Then, anywhere inside your
jvmMainserver code:We are using this new feature in the todo template example (e.g.
kobweb create examples/todo). This allows us to make it easy for users to toggle the implementation of the backend datastore from in-memory to a MongoDB database. Feel free to check out the project if you are curious!Revisiting Network APIs
The stdlib
fetchAPI is very powerful but full of dynamic, type-unsafe code. Kobweb's network APIs aresuspendfriendly and type-safe.However, in the earliest days of Kobweb development, I made an incorrect assumption and oversimplified what I would accept for a request's payload body. Specifically, I only accepted a byte array for it. However, there are several different data types that web request APIs traditionally accept, including multipart bodies, json, html text, and blobs.
Therefore, this version of Kobweb introduces a new
RequestBodyclass which you construct with one of the various providedbodyOffactory methods. So where before you would pass raw bytes into one of the Kobweb network methods, now you pass in the output of abodyOfcall instead.Of course there is a
bodyOffor raw bytes. But we also support wrapping the other types as well (blobs, etc.)And instead of returning raw bytes back, we now return a
Responseobject (a standard class in web APIs). You can pull raw bytes out of its body payload by using our newbodyAsBytesextension method:A little more verbose, admittedly, but now users can work with
Responseobjects directly, which is a lot more powerful.Real-world example: multipart request
To showcase a real example, the following code was introduced in the last release demonstrating how to send a multipart request:
Now, I would write it as follows, ditching the
RequestInitobject and the need toawaitthe response (since Kobweb'sfetchmethod is suspend aware):Migrating deprecated network methods
We deprecated a lot of network methods in this release, since, as we discussed in the prior section, we settled on the approach we should have used in the beginning: take in a rich request body type and return a
Responseobject.If you are a user caught up in this, we apologize for the inconvenience.
In the previous release, we pushed people away from using, say,
fetch, which originally returned raw bytes, and migrated them to usefetchBytesinstead (same function, new name). Now, here we are abandoning raw bytes! And pushing users back to the original method, except now it takes in a rich body type and outputs aResponse. Users are expected to callbodyAsByteson top of theResponseobject to get those raw bytes out again.For every method we deprecated, we included logic to help the IDE try to migrate the code for you. However, sometimes, it just really sucks at it, so manual migration / tweaking may be required.
In the following table, we'll use the
postmethod to demonstrate before and after migrations, but keep in mind this same transition would apply for any of the HTTP verbs (get, put, delete, etc.).window.fetchBytes(HttpMethod.POST, url, bytes)window.fetch(HttpMethod.POST, bodyOf(bytes)).bodyAsBytes()window.tryFetchBytes(HttpMethod.POST, url, bytes)window.tryFetch(HttpMethod.POST, bodyOf(bytes)) { bodyAsBytes() }window.http.postBytes(url, bytes)window.http.post(bodyOf(bytes)).bodyAsBytes()window.http.tryPostBytes(url, bytes)window.http.tryPost(bodyOf(bytes)) { bodyAsBytes() }window.http.postBytes(url, bytes)window.http.post(bodyOf(bytes)).bodyAsBytes()window.http.tryPostBytes(url, bytes)window.http.tryPost(bodyOf(bytes)) { bodyAsBytes() }window.api.postBytes(url, bytes)window.api.post(bodyOf(bytes)).bodyAsBytes()window.api.tryPostBytes(url, bytes)window.api.tryPost(bodyOf(bytes)) { bodyAsBytes() }window.api.postBytes(url, bytes)window.api.post(bodyOf(bytes)).bodyAsBytes()window.api.tryPostBytes(url, bytes)window.api.tryPost(bodyOf(bytes)) { bodyAsBytes() }As you can see, the new versions are a bit more verbose, but by separating out the logic for making the request and reading the response, we get a lot more power with fewer methods.
Serialization extensions
Not many people know that Kobweb also provides an artifact (
com.varabyte.kobwebx:kobwebx-serialization-kotlinx) that adds extensions for network requests that are Kotlinx serialization aware.We also revisited those methods and simplified them as well.
For the following table, imagine we had the following serializable classes:
In the following table, note that a common change is moving the
Resresponse class out from the initial request signature into a trailingbodyAs<T>call.window.http.postBytes<Req>(url, req)window.http.post<Req>(url, req).bodyAsBytes()window.http.tryPostBytes<Req>(url, req)window.http.tryPost<Req>(url, req) { bodyAsBytes() }window.http.post<Req, Res>(url, req)window.http.post<Req>(url, req).bodyAs<Res>()window.http.post<Res>(url)window.http.post(url, body = null).bodyAs<Res>()window.http.tryPost<Req, Res>(url, req)window.http.tryPost<Req>(url, req) { bodyAs<Res>() }window.http.tryPost<Res>(url)window.http.tryPost(url, body = null) { bodyAs<Res>() }window.api.postBytes<Req>(url, req)window.api.post<Req>(url, req).bodyAsBytes()window.api.tryPostBytes<Req>(url, req)window.api.tryPost<Req>(url, req) { bodyAsBytes() }window.api.post<Req, Res>(url, req)window.api.post<Req>(url, req).bodyAs<Res>()window.api.post<Res>(url)window.api.post(url, body = null).bodyAs<Res>()window.api.tryPost<Req, Res>(url, req)window.api.tryPost<Req>(url, req) { bodyAs<Res>() }window.api.tryPost<Res>(url)window.api.tryPost(url, body = null) { bodyAs<Res>() }The above tables certainly makes it look like this would be a very disruptive change indeed, but in practice, not too many people use fullstack Kobweb, and even for those that do, some of these methods are pretty niche, so we don't expect most users to even notice a single warning!
Thanks
The community really benefits from contributions like this. Thank you so much!
Full Changelog: v0.24.0...v0.24.1
This discussion was created from the release v0.24.1.
Beta Was this translation helpful? Give feedback.
All reactions