reitit

Shahwarcoder 2024-02-26T08:45:04.522289Z

Hello @ikitommi I am using Reitit frontend for my routing but I am seeing the build size goes very high when including reitit coercion which brings in the clojure analyzer.cljc file which is almost 200Kb size. Is there a way to minimise this or use Reitit without the coercion itself?

lwhorton 2024-03-27T15:11:25.989879Z

i was looking to similarly optimize my bundle size. after quite a bit of work i realized that it's kind of a fool's errand for a lot of applications. you cant depend on basically any javascript library; most of them are bloated with transient deps. you have to find ways to optimize your css with tailwinds-like stripping of unused classes, or some other strategy. you have to be particular about which parts of cljs core and other cljs you end up using. a lot of code has to be annotated for proper tree-shaking. then, after working really hard to cut a few kbs at every opportunity... one of the first xhr fetches to a backend service returns 500kb. all those gains in payload size and first render time are immediately lost. :x i think for most apps i've ever written it's a much better strategy to make my caching as efficient as possible, which is quite simple with something like shadowcljs and a static assets server

dumrat 2024-02-26T08:46:27.837039Z

You can opt out of coercion

Shahwarcoder 2024-02-26T08:47:50.026609Z

so if I opt out then I will also loose parsing of prams or body from routes, isn't it?

dumrat 2024-02-26T08:50:54.634879Z

You should be able to hand-roll your own coercer that makes use of the same route data if that's a concernt

juhoteperi 2024-02-26T08:52:28.636179Z

Not sure what is the dependency source for clojure analyzer.cljc

Shahwarcoder 2024-02-26T08:56:30.250699Z

(def router
  (rf/router routes {:data {:coercion rcs/coercion}}))
@juhoteperi not sure, this line adds the analyzer to my build somehow. I removed the coercion and then analyzer got removed

Shahwarcoder 2024-02-26T08:58:57.022539Z

@juhoteperi Here is the screenshot of my report file

juhoteperi 2024-02-26T09:01:36.625729Z

aha you are using spec instead of malli

Shahwarcoder 2024-02-26T09:02:16.594239Z

so what should we use then?

Shahwarcoder 2024-02-26T09:03:02.412619Z

https://github.com/metosin/reitit/blob/master/examples/frontend/src/frontend/core.cljs I followed this example, here is suggested spec

juhoteperi 2024-02-26T09:03:15.650619Z

Depends on what you want. Due to Spec implementation spec-tools needs to use Cljs analyzer and there is probably no way around that.

Shahwarcoder 2024-02-26T09:04:26.085859Z

I don't use spec anywhere except while defining the router which I showed above

juhoteperi 2024-02-26T09:05:08.087199Z

Malli doesn't need the cljs analyzer but the Reitit coercion implementation isn't very optimized for frontend use, so I'm not sure if Malli coercion implementation is much lighter than Spec.

juhoteperi 2024-02-26T09:06:38.368619Z

I'd say Malli is the preferred one, but examples are probably from time before Malli. And it depends a lot if you are already using one of the "schema libs" elsewhere.

Shahwarcoder 2024-02-26T09:07:19.157529Z

So are you suggesting to use router without any coercion? how much will that affect my code. I haven't yet reached to very complex route definitions with query params and stuff, but will use then in later stage.

Shahwarcoder 2024-02-26T09:07:52.784479Z

> I'd say Malli is the preferred one, but examples are probably from time before Malli. And it depends a lot if you are already using one of the "schema libs" elsewhere. I don't think I am using schema libs too.

juhoteperi 2024-02-26T09:08:03.625979Z

I use Reitit frontend with Malli coercion

juhoteperi 2024-02-26T09:08:20.797369Z

Query parameters could be inconvenient without coercion usually

Shahwarcoder 2024-02-26T09:08:53.325289Z

ok. let me try with malli

juhoteperi 2024-02-26T09:10:45.851819Z

I can add a new example quickly

Shahwarcoder 2024-02-26T09:11:24.258269Z

sure, that would be helpful, but here is the gist of what I have done

Shahwarcoder 2024-02-26T09:12:21.620519Z

...(:require [reitit.coercion.malli :as rcm])...

(def routes [....])

(def router
	(rf/router routes {:data {:coercion rcm/coercion}
										 ;:controllers [{:start (js/console.log "start" "root-controller")
											;							:stop (js/console.log "stop" "root controller")}]
										 }))

(rfe/start!
							 router/router
							 (fn [matched-route]
								 ;(swap! router/routes-state (fn [old-match] (if matched-route (assoc matched-route :controllers (rfc/apply-controllers (:controllers old-match) matched-route)))))
								 (when matched-route
									 (set-active-name! (-> matched-route :data :name))
									 (set-active-view! (-> matched-route :data :view))))
							 ;; set thi to "false" to enable HistoryAPI
							 {:use-fragment false})

juhoteperi 2024-02-26T09:13:55.313369Z

here is a simple frontend example: https://github.com/metosin/reitit/blob/master/examples/frontend-malli/src/frontend/core.cljs

juhoteperi 2024-02-26T09:14:07.498679Z

Just to show the basic :parameters format for FE use

Shahwarcoder 2024-02-26T09:14:55.702839Z

@juhoteperi thank you so much

Shahwarcoder 2024-02-26T09:17:26.678229Z

Its still huge though, almost 167Kb

Shahwarcoder 2024-02-26T09:18:51.610169Z

@juhoteperi

Shahwarcoder 2024-02-26T09:19:26.843379Z

How can I remove swagger and other stuff not needed from here?

juhoteperi 2024-02-26T09:22:22.852429Z

Open issue unfortunately https://github.com/metosin/reitit/issues/463

😞 1
Shahwarcoder 2024-02-26T09:23:32.575479Z

@juhoteperi Can you share me an implementation to use linear-router? I guess that would be the most optimised one.

juhoteperi 2024-02-26T09:27:20.989989Z

I don't think I have that anywhere in use

juhoteperi 2024-02-26T09:28:14.947969Z

But IIRC you could just call Reitit/linear-router instead of reitit/router. The reitit.frontend/router is just merging one option into the call, so you would need to add that yourself: https://github.com/metosin/reitit/blob/master/modules/reitit-frontend/src/reitit/frontend.cljs#L89-L95

juhoteperi 2024-02-26T09:28:57.461179Z

so (rf/router routes {options}) -> (r/router-linear routes {:compile ... options})

juhoteperi 2024-02-26T09:29:49.619069Z

But also the optimization isn't always working very predictably, there are cases when not calling a function doesn't remove all the code that function uses (like -get-apidocs and swagger code)

Shahwarcoder 2024-02-26T09:31:03.668919Z

Ok, let me try to implement this and see if I face any issue.

juhoteperi 2024-02-26T09:31:40.139359Z

We haven't had cases where the JS artifact size would have been super important, so optimizing Reitit-frontend size hasn't been a priority. If you are building a app for intranet like use, and you have just a few users it isn't super important. Or if you are using large JS libs.

Shahwarcoder 2024-02-26T09:34:36.229249Z

I am using it for my internal users and it won't harm us to use large libraries but, I would very much want to use reitit on production apps too. I have spent quite deal of my time to setup multi level nesting with reitit for pages and subpages and would want to use this as a replacement for react router.

Shahwarcoder 2024-02-26T09:35:14.324019Z

I think there should be a plan to improve reitit frontend to minimise the bundle size

Shahwarcoder 2024-02-26T09:38:02.214959Z

{:name :routes.fms.events
									:comp-level 2
									:view ($ events/Events)
									:parent [:routes.fms]
									}
If you see my routes, have added comp-level for which level a components needs to be rendered and parent to show under which parent the component can be rendered. Removing all this will just be waste of time.