I don't have a (publishable) example readily available (but might work on one
in the future), but I'll try to answer what I think your question is.
First off — I'm not talking about implementing part of your server-side logic
in ClojureScript. If you want something like this you're better off writing
your whole server app in Clojure, there's enough good libraries around to do
that :)
Second — I'm not talking about some Rails magic like UJS either. I haven't used
that ever, and am not planning to
So "cljs & rails integration" is really a fancy way of saying "the Rails asset
pipeline knows how to compile clojurescript code and serve it" — the Rails
asset pipeline really being Sprockets.
There are two predominant models when it comes to compiling assets in dev:
- Have a 'watcher' process that recompiles source files whenever they're
changed ('lein cljsbuild auto', 'coffee-script --watch', 'sass --watch', etc.)
- Have an 'asset pipeline' integrated in your HTTP server, that compiles
assets on-demand, when they're requested.
When developing a Rails app, it's most convenient to just have the server
running and let the asset pipeline take care of everything. Sure, maybe you're
wasting a few ms waiting for a file to compile while reloading the page, but
you also get to see compile errors in your browser instead of in a tmux pane /
terminal tab somewhere far away — there's no notification to distract you
everything you save a file and the compilation succeeds, you only get info when
something goes wrong, and barring that, you can stay in the comfortable "text
editor / browser" loop.
To integrate a transpiler (like the ClojureScript/CoffeeScript/Sass/LESS
compilers) into an asset pipeline like I just described, you need to have
control over the compiler's cache & the ability to get output for individual
files.
In the case of cljs mainline, that would mean having a ruby gem, loaded into
the Rails asset pipeline, that starts up a JVM, loads the ClojureScript
compiler into it, and then knows enough about its internals to ask for
recompilation when a specific file is being requested by the pipeline, and then
instead of writing them to disk somewhere, return their content so that the
pipeline may serve it.
I'm not saying it's impossible, btw, it's very possible - as Thomas Heller
demonstrated with shadow-build. But this:
https://github.com/thheller/shadow-build/blob/master/src/clj/shadow/cljs/build.clj
— doesn't look like the kind of code I want to maintain in a simple plug-in
for an asset pipeline.
There's a good reason the ClojureScript compiler API is "complicated", though —
it's really powerful. And evaluates macro in a *real* Clojure environment,
unlike Shin (which uses V8 + cljs.core). And I'm still not sure how it handles
caching/incremental build, because honestly, at this point I'm scared to look.
Hopefully Shin can expose a simpler API so it can be integrated in pipelines
all around - whether they are Ruby-based (in which case they can just use the
gem), or not (in which case a disk-based cache is probably the way to go: the
big advantage being that shin boots up *fast* so there's little penalty to that
approach).
TL;DR - asset pipelines benefit from simple interfaces & lighter command-line
tool, and that's what I'm aiming for with shin.
On Wednesday, December 3, 2014 4:13:56 PM UTC+1, Yehonathan Sharvit wrote:
> Could you please share an example of an integration of cljs and rails?
>
>
> On Wednesday, 3 December 2014 00:50:57 UTC+2, Thomas Heller wrote:
> > Hey,
> >
> > good luck with your efforts.
> >
> > It seems to be that is was motivated by alot of frustration due to
> > lein-cljsbuild and Google Closure. Most of the issues mentioned in "S-exps
> > in your browser" are actually addressed in shadow-build [1], part of the
> > reason I wrote it due to some frustrations I had myself.
> >
> > Seems like you moved on but maybe you are interested ...
> >
> > Cheers,
> > /thomas
> >
> > [1] https://github.com/thheller/shadow-build
> >
> > On Tuesday, December 2, 2014 10:01:27 PM UTC+1, Amos Wenger wrote:
> > > There's definitely a business case behind this, otherwise I wouldn't be
> > > able to justify the time put behind it :)
> > >
> > > Obviously, one use-case is to be able to use ClojureScript in Rails
> > > projects seamlessly, without having to 1) use an external "watcher" tool
> > > that runs parallel to the asset pipeline or 2) use something integrated
> > > to the asset pipeline but which spins up a fresh compiler instance every
> > > time (3-4s penalty right there)
> > >
> > > But even when using ClojureScript in standalone projects, say, only
> > > static HTML files + heavy JS client-side logic, it pays off to have a
> > > smaller, quick to boot up compiler be it launched fresh each time and
> > > using a file cache, or living in the background, integrated to a tool
> > > like "guard" (and believe me - an MRI instance is *much* cheaper
> > > memory-wise than a JVM instance with the whole Clojure machinery loaded).
> > >
> > > So it's a lot of small things, really. Small annoyances. I'm trying
> > > really hard not to criticize mainline cljs too much, because it's an
> > > achievement in itself and it'll remain forever the first-class cljs
> > > compiler everybody uses — there's all the goodies in there.
> > >
> > > I guess I just wanted something I could know inside-out. I've started
> > > seriously getting into Clojure only about 2 months ago, so it's been a
> > > great learning experience as well! Plus, it's not my first time writing a
> > > transpiler... but Clojure is much nicer to implement.
> > >
> > > By the way, since the original message went through on the mailing list,
> > > I managed to get reagent-shin to work completely (as far as I can tell)
> > > including input components, etc. The last hurdle was a typo in
> > > PersistentArrayMap.-equiv (one damn parenthesis...).
> > >
> > > I reckon shin is a strange beast "it's experimental!" but "it compiles
> > > 90% of the cljs code out there without modifications!", "don't use it for
> > > anything serious!" but "contributions welcome!", not to mention that it's
> > > written in Ruby - but Ruby is just a tool like any other, that has a very
> > > friendly ecosystem, and whose VMs boot up fast. That's all I asked.
> > >
> > > Since cljs.core has grown to a healthy 2.2K and ~200 defs, I'm now
> > > trying. Macro expansion is the costliest part of the workflow so far,
> > > each taking 10 to 12ms (because every expansion is a module that has to
> > > be translated from AST to JST, generated into JS, loaded into V8, passed
> > > its input, serialize its output, then parse its output back from the Ruby
> > > side). However I have a few ideas on how to make it all faster. And when
> > > I'm out of ideas, caching will help a lot, like mainline does.
> > >
> > > On Tuesday, December 2, 2014 6:16:04 PM UTC+1, Jamie Orchard-Hays wrote:
> > > > Amos, I'm curious about your motivation for this. Fun? Curiosity?
> > > > Business need? I'm using Om/CLJS in a Ruby on Rails app, so this caught
> > > > my eye.
> > > >
> > > >
> > > > On Dec 2, 2014, at 8:35 AM, Amos Wenger <[email protected]> wrote:
> > > >
> > > > > shin (新) is an early-stage but relatively complete implementation of
> > > > > a ClojureScript-to-JavaScript compiler, written in Ruby, and that
> > > > > does not rely on Google Closure's libraries or compiler:
> > > > > https://github.com/memoways/shin
> > > > >
> > > > > The README contains probably more than you ever want to know about
> > > > > Shin, but I am of course happy to answer any of your questions :)
> > > > >
> > > > > The main differences are:
> > > > >
> > > > > - It's not based on any previous Clojure compiler - no use of the
> > > > > analyzer, etc.
> > > > > - It generates AMD modules rather than Google Closure modules
> > > > > - Data structures are implemented on top of Matt Bierner's HAMT+ for
> > > > > the time being (but that may change)
> > > > > - Macros are expanded in JavaScript, using V8 (driven from Ruby)
> > > > > - Uses `escodegen` to generate JavaScript
> > > > >
> > > > > What sorely missing? At this time: metadata support, type
> > > > > annotations, transducers, a cache for the compiler so recompiles are
> > > > > faster, and actually passing source location information from the AST
> > > > > to escodegen.
> > > > >
> > > > > But otherwise, functions, defprotocol/deftype, macros, base
> > > > > collections (list, cons, hash-set, hash-map)
> > > > >
> > > > > Right now the most involved piece of ClojureScript code (except for
> > > > > ~30% of cljs.core and 100% of clojure.string) is probably Reagent,
> > > > > which I am almost done making work with Shin:
> > > > > https://github.com/memoways/reagent-shin — I wanted to wait till it
> > > > > was complete to make the announcement, but I figured I could probably
> > > > > use some help along the way :)
> > > > >
> > > > > Why should anyone care about this ?
> > > > >
> > > > > - Alternative implementations of a language are just plain healthy,
> > > > > even if you don't use them.
> > > > > - Polyglot programming is awesome (Clojure/Ruby/JS all in one!)
> > > > > - 330 specs and growing:
> > > > > https://github.com/memoways/shin/tree/master/spec (maybe we can get a
> > > > > runnable specification of ClojureScript at some point?)
> > > > >
> > > > > Oh, and hopefully obvious disclaimer: don't use it for anything
> > > > > serious! It still breaks often, it's not even a month old, handle
> > > > > with care.
> > > > >
> > > > > That said, helping hands are more than welcome, in particular in
> > > > > these areas:
> > > > >
> > > > > - Identifying differences in behavior with the mainline CLJS
> > > > > implementation
> > > > > - Writing more specs & porting more of cljs.core
> > > > > - Profiling & making the compiler faster (probably more for Ruby
> > > > > folks!)
> > > > > - Figuring out a JS-friendly way to distribute libraries (bower?
> > > > > component?) — eventually have libraries that compile both on mainline
> > > > > and shin?
> > > > >
> > > > > Love,
> > > > > — Amos
> > > > >
> > > > > P.S: I'm not sure how the whole licensing thing works, since
> > > > > ClojureScript is EPL+CA and Shin is just MIT-licensed. There's a note
> > > > > in the README, let me know if there's anything else I need to do!
> > > > >
> > > > > --
> > > > > Note that posts from new members are moderated - please be patient
> > > > > with your first post.
> > > > > ---
> > > > > You received this message because you are subscribed to the Google
> > > > > Groups "ClojureScript" group.
> > > > > To unsubscribe from this group and stop receiving emails from it,
> > > > > send an email to [email protected].
> > > > > To post to this group, send email to [email protected].
> > > > > Visit this group at http://groups.google.com/group/clojurescript.
--
Note that posts from new members are moderated - please be patient with your
first post.
---
You received this message because you are subscribed to the Google Groups
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.