clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Ovidiu Stoica 2021-05-25T04:56:05.249400Z

Besides great SPA capabilities. Is there something similar to what NextJS does in the Clojure(script) world?

Mateusz Mazurczak 2021-05-25T09:21:56.249700Z

What capabilities are you looking for?

Ovidiu Stoica 2021-05-25T12:25:35.251700Z

Having for example static pages, dynamic pages with link preview. I guess what I am looking for is SEO friendly capabilities

Ovidiu Stoica 2021-05-25T12:32:03.252300Z

More specifically, say I have a dynamic part of the application which can be an SPA, but also have a blog part with the blogposts written in Markdown but compiled to html pages at build time

Ovidiu Stoica 2021-05-25T12:32:49.252500Z

How would you go about doing that, currently I am looking at the luminous framework but seems that all pages are built at request time

docouto 2021-05-29T22:45:26.433600Z

I'd say you could be able to do these kind of things with macros, but I don't really have experience in this particular use case.

Mateusz Mazurczak 2021-05-25T09:21:56.249700Z

What capabilities are you looking for?

Audrius 2021-05-25T10:37:34.250500Z

Why ^js in (fn [^js this] might me needed? Is it some optimization I guess?

2021-05-25T10:41:19.250700Z

yes. see https://clojurescript.org/guides/externs

1✔️
Pepijn de Vos 2021-05-25T12:09:17.251600Z

how do I resolve such a warning? Probably a type hint somewhere...

Cannot infer target type in expression (. el getScreenCTM)

Ovidiu Stoica 2021-05-25T12:25:35.251700Z

Having for example static pages, dynamic pages with link preview. I guess what I am looking for is SEO friendly capabilities

ingesol 2021-05-25T12:26:12.251900Z

el in this statement cannot be inferred by the compiler, putting getScreen in danger of being renamed during advanced compilation. The simplest solution is to put a ^js type hint where el is declared.

Pepijn de Vos 2021-05-25T12:31:51.252100Z

Thanks! Seems kind of... obvious that the result of a js method on a js object is a js object but ok

Ovidiu Stoica 2021-05-25T12:32:03.252300Z

More specifically, say I have a dynamic part of the application which can be an SPA, but also have a blog part with the blogposts written in Markdown but compiled to html pages at build time

Ovidiu Stoica 2021-05-25T12:32:49.252500Z

How would you go about doing that, currently I am looking at the luminous framework but seems that all pages are built at request time

ingesol 2021-05-25T12:34:02.252700Z

This one was just poste above this question, probably informative https://clojurescript.org/guides/externs

Pepijn de Vos 2021-05-25T12:37:20.252900Z

yea I saw it hmmm

dnolen 2021-05-25T12:40:53.253700Z

@pepijndevos but how did you get el ? generally it's not possible to know what it is

dnolen 2021-05-25T12:41:59.254500Z

there's plenty of inference in ClojureScript but still typical cases that cannot be known in a dynamic language (fn params etc)

Pepijn de Vos 2021-05-25T12:43:54.255700Z

yea in a statically typed language (.-currentTarget aMouseEvent) would have a pretty well defined type... not so in dynamic land

dnolen 2021-05-25T12:44:39.256Z

even that is not completely true

dnolen 2021-05-25T12:44:47.256200Z

once the type is known inference can flow

dnolen 2021-05-25T12:45:08.256700Z

if the type is standard DOM, types are collected from Closure

dnolen 2021-05-25T12:45:22.257100Z

the problem is not inference - the problem is what is the initial type

dnolen 2021-05-25T12:45:45.257600Z

even in most statically typed languages you need this critical bit of info

dnolen 2021-05-25T12:45:50.257900Z

and you are forced to declare

dnolen 2021-05-25T12:46:33.258400Z

the moment you type el than all types will flow correct in the local context and ClojureScript even infers return types

dnolen 2021-05-25T12:47:45.259700Z

not for type checking of course (except a little for numerics) - mostly for extern generation (and elimination of externs already declared)

dnolen 2021-05-25T12:50:24.260400Z

we even check usage - if you use the right type but then call the wrong method - you will get a warning about the method be unresolveable

Aron 2021-05-25T13:24:11.262400Z

I would say this has probably not much to do with dynamic vs. static, since you have all kinds of different issues around the same interface and same problems with static languages as well. In fact, with static you have worse issues, e.g. like this https://github.com/microsoft/TypeScript/issues/299 I personally been bitten by this, never could properly write type signatures for DOM methods. If you don't avoid the whole problem completely, e.g. like how elm-lang does it https://guide.elm-lang.org/effects/ then I guess it's possible, but even they had to iterate on this concept several times, and I am not sure this will be final (looks so, so far).

dnolen 2021-05-25T13:33:19.262900Z

https://clojurescript.org/news/2021-05-24-release

11🎉
isak 2021-05-25T16:45:06.264700Z

This (from the release notes ^) is really cool:

(ns foo.bar
  (:require-macros [foo.baz :refer [macro-that-expands-to-require]]))
(macro-that-expands-to-require)

Ovidiu Stoica 2021-05-25T17:12:11.264800Z

Still looking for an answer to this 😁

dnolen 2021-05-25T17:38:45.265500Z

@ovidiu.stoica1094 just use NextJS w/ ClojureScript?

Ovidiu Stoica 2021-05-25T17:58:40.267900Z

I am not really keen on that sollution as I want to port my existing Next Js implementation to full Clojure & ClojureScript as my backend is already in Clojure w ring & reitit and I would love to get some static pages like for a blog (SEO) and dynamic pages like domain/vote/:dynamic-id for which I just want to generate a preview link for social channels.

dnolen 2021-05-25T18:04:19.269100Z

I don't know if there is a complete solution like NextJS - if I had a good excuse I would do a project with Datomic Cloud Ions

Ovidiu Stoica 2021-05-25T18:05:07.269200Z

Datomic Cloud Ions… I am not familiar and I haven’t used datomic yet but will look into it

Audrius 2021-05-25T19:10:51.270400Z

Hello, How do I make that time will be displayed on users browser locale and with their local timezone displayed as well?

raspasov 2021-05-25T19:19:01.270500Z

Use a library, for example https://github.com/juxt/tick

1✔️
borkdude 2021-05-25T19:44:21.272200Z

If one wanted to make a CLJS plugin system with one base module and other optional modules, with advanced compilation, the :modules system could work. It does work in fact, if you compile all modules from one and the same repo and commit. BUT: what if other parties also wanted to make modules? The advanced compilation naming scheme isn't deterministic/stable enough in this situation. What to do? Revert to simple? Is there a better option? How do other JS libraries tackle this problem? I guess in pure JS there are less problems because you don't have to depend on the same cljs build Perhaps :pseudo-names could work, although the docs suggest this is for debugging and maybe not a good idea?

thheller 2021-05-25T19:51:47.274400Z

not possible with advanced since that is a whole program optimizer. well you can create an "interface" that other modules implement but as soon as you want to use CLJS datastructures you'll run into trouble. JS libs don't generally have this issue this they mostly build on JS objects/arrays

thheller 2021-05-25T19:52:00.274600Z

:pseudo-names is for debugging only

borkdude 2021-05-25T19:52:32.275200Z

yeah, that's what I thought. the interface idea might work too but then each module would have to bring their own mangled versions of the entire cljs lib :)

thheller 2021-05-25T19:52:41.275400Z

exactly

borkdude 2021-05-25T20:01:15.276600Z

I think in theory it would be possible to compile the base module with advanced and then inform the advanced compilation of the other modules about the naming scheme used, to take those into account

borkdude 2021-05-25T20:01:24.276900Z

but Closure would have to support that

thheller 2021-05-25T20:06:17.277700Z

no that is not possible. :advanced will remove everything that isn't used, so how is it supposed to know what modules will use in the code it can't "see"?

thheller 2021-05-25T20:06:23.278100Z

if you disabled that you end up with :simple again

borkdude 2021-05-25T20:09:23.280200Z

the optional module would be compiled with, let's say, a map of raw names -> mangled names, so everything the optional module would use in common with the base module, would get the same mangled name. If code is cut out from the base module, but is used in the optional module, the name doesn't matter, since the only assumption is that the names of the base module are mangled consistently.

thheller 2021-05-25T20:10:41.281200Z

it isn't just about names. things will get inlined, moved around, deleted.

borkdude 2021-05-25T20:11:11.282200Z

yeah good point, then it doesn't work out

thheller 2021-05-25T20:11:17.282300Z

you can simply turn off the renaming of properties but that won't really safe you.

borkdude 2021-05-25T20:11:35.282800Z

ok, so the plugin system would be a closed system, unfortunately

thheller 2021-05-25T20:12:55.284200Z

yeah sort of the same deal as graalvm native-image

borkdude 2021-05-25T20:13:00.284300Z

open for contribution of course, but not something that can be developed independently

borkdude 2021-05-25T20:13:23.284500Z

yep

borkdude 2021-05-25T20:13:56.285200Z

another question, different topic. how common is this-as in normal every day code?

thheller 2021-05-25T20:14:14.285800Z

for some interop code it can be common. otherwise very uncommon.

2021-05-25T20:14:22.286Z

At that stage wouldn't it make more sense to make your primary system a library and deployments just depend on the library and a fixed set of plugins, and then advanced compilation only takes place with all the code already in your system?

borkdude 2021-05-25T20:15:28.286800Z

@suskeyhose normally yes. The use case for the plugin system would be for this: https://borkdude.github.io/sci-script-tag/ so you can make an optional reagent plugin: https://borkdude.github.io/sci-script-tag/tictactoe.html and that works well, as long as you compile from the exact same code base.

2021-05-25T20:16:01.287Z

aaaah, I see

kennytilton 2021-05-25T23:55:32.288300Z

"not possible with advanced since that is a whole program optimizer" Aha! That explains the two days I spent trying to sell multiple repos to advanced! sigh