Note: I'm a moderately experienced programmer in general and using clojure but have never done serious web development.
I set up a basic ClojureScript project using Chestnut and walked through the "Hello World" steps just fine. However I would really like to talk to my backend as well. For this purpose I redefined the Reagent code to be
(defn greeting []
[:input {:type "button"
:value (:text #app-state)
:on-click #(http/get {})}])
Which gets a 404 response when clicked. So at least I'm talking to somebody. I can also see evidence of my get-requests in the server.log file. However at this point I'm struggling with a number of conceptual points.
First of all http/get is a function defined in clj-http.client, which wasn't part of the Chestnut setup. It feels like I'm already off track if I have to go hunting for libraries to send something as basic as a get-request.
Secondly the file for the user namespace has the following lines predefined by Chestnut:
(def http-handler
(wrap-reload #'mypage.server/http-handler))
(defn run []
(figwheel/start-figwheel!))
I can't see any place where the http-handler is ever used. So I don't understand what that definition even does.
Also the way I understand Figwheel, when I call "run" it'll spin up a new web server which then a) serves the index.html and b) connects to my browser via some TCP port and starts pumping new JavaScript through that connection. This second part is very speculative on my part. If this is actually what happens my next question would be if Figwheel also needs to sit on the other side of that connection or if browsers have some common API that allows code reloading from the outside.
Lastly I can kinda tell that the ring routes and http-handler defined in the mypage/server.clj file (below) are being called somehow, since modifying these changes the error from the get-request, however it's a complete mystery to me how this works. The way I understand it the get-request I'm sending from the browser is sent to the Figwheel-server, the origin of the site. I have no reason to believe that Figwheel knows anything about the http-handlers I've defined in the server file.
(defroutes routes
(GET "/" _
{:status 200
:headers {"Content-Type" "text/html; charset=utf-8"}
:body (io/input-stream (io/resource "public/index.html"))})
(resources "/"))
(def http-handler
(-> routes
(wrap-defaults api-defaults)
wrap-with-logger
wrap-gzip))
For a ClojureScript project (i.e. not Clojure), I believe you want this: https://github.com/r0man/cljs-http
I don't have a complete answer, but I do have a couple points that might help.
Clojurescript ultimately compiles down to JavaScript, and makes heavy use of (and has access to) the Google Closure library. So if you really want to, you can use JavaScript interop to just make an AJAX call from the client-side, just like you would in JS. The closure library provides a wrapper for this---see docs here https://developers.google.com/closure/library/docs/xhrio . But there are also several easy http and Ajax libraries for clojurescript, so why not use them? Another part of the joy and magic of clojurescript is that the Google closure optimizations that get applied do lovely things like strip out dead code, so I believe (and someone else can correct me if I'm wrong) that there is little (no?) production cost to putting some extra libraries in.
Figwheel is ultimately dev, not production, and doesn't depend on the http server that you set up for production use. Indeed, there are templates out there for front-end-only cljs projects that still use figwheel--- here's one example. Figwheel spins its own server to push changes to the browser, I'm not quite sure how it works.
Related
This might sound a stupid question, but how do I turn a piece of hiccup into html in a ClojureScript reagent application?
I want something like this :
(html [:div [:p "hello world" ]])
that produces
<div><p>hello world</p></div>
This is what you can do in hiccup.core, but as far as I can see, that's in Clojure. Not ClojureScript in the browser.
OTOH, ClojureScript / Reagent clearly knows how to do it in the browser. It's doing it all the time. But I can't actually find a library call anywhere in reagent where I can do this explicitly, outside the reagent rendering process.
I'm not sure why you would want to do this, but it appears one answer is to use the function:
reagent.dom.server/render-to-string
Normally, your Reagent components only return Hiccup data, and you let reagent.dom/render do all the hard work of reactively "rendering" only the changed components into the DOM.
P.S. When in doubt, you can often find documentation at cljdoc.org. Most Clojure projects have a direct link there from their GitHub page (Reagent does, for example). Or, you can go to cljdoc.org directly and search there.
I have a terminal app built in Clojure and connected to MySQL, but I would like to know the simplest way to add a front-end to it. I came across this post (that is 5 years old) that recommends ring, and set it up: Add webapp frontend to existing clojure app.
After adding deps to project, added handler function to core.clj:
(defn handler [request]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"})
Started a webserver and got output "Hello World."
Ok, now what? I am familiar with templates like Figwheel that allow you to build Clojurescript right out of the box (that doesn't come with a back-end?) and tools like Reagent that allow you to write React with Clojurescript, but what I am interested in is, how to add a front-end to an already existing terminal app, in whatever framework I choose, be it plain React, Clojurescript with Reagent, Angular, or even old-fashioned HTML/CSS/Javascript. It seems there are lots of templates but no instructions for how to do it from scratch.
Any of the following would have been acceptable answers: Selmer, Hiccup, Enlive.
Beginner here.
Can I compile an existing Clojure script to run it on the web using ClojureScript?
Let's say that I have a script that prints Hello world in my terminal, and I want to print that text on the browser. Should I rewrite a whole script with ClojureScript syntax, or should I just compile it using another compiler?
(ns clojure-hello-world.core
(:gen-class))
(defn -main [& args]
(println "Hello World"))
(Long answer :P)
Even though Clojure and ClojureScript share a good amount of features, there are some that are specific to one or the other. For example there are no real classes in JavaScript so the :gen-class specification in the ns form doesn't make much sense.
One important fact is that the syntax of both Clojure and ClojureScript is exactly the same, differences have to do mostly with the host VM in which they run (Java VM in the case of Clojure and JavaScript VM in the case of ClojureScript).
There is a list of the differences between the two Clojure implementations here.
There's also a tool called cljx to "write a portable codebase targeting Clojure/ClojureScript". Recently there has been some discussion on the Clojure Dev group around finally implementing feature expressions which would on one hand deprecate the use of cljx but on the other complicate the work that tools have to do to extract information from Clojure source files.
I would start with lein-cljsbuild to get started. This will get you going with a nice edit eval and look at browser loop. It's well worth getting this setup first because it makes learning ClojureScript much more fun. I promise it's worth the hassle. If you need more interactive support the folks in #clojure on freenode are very kind and helpful.
Basically, the Browser executes JavaScript. You compile your ClojureScript code to JavaScript. The Browser loads your JavaScript via an HTML page. So, you have to create an HTML Page and point your Browser at it.
The simplest way I got started was to use Luminous (http://www.luminusweb.net/docs/clojurescript.md).
However, Chestnut (https://github.com/plexus/chestnut) looks promising.
I'm using Austin to set up a browser-connected REPL, and following the example of its sample project, which uses Enlive to add the REPL script to the page.
Now I'd like to deploy my app, but I don't wan't Austin or my REPL to be on the page in production. What's the intended way to use the REPL only in development?
Is there a way to use Enlive as a middleware I could use in development and not in production?
There's almost always something that uniquely distinguishes a production environment from :dev that you can use as a conditional: if in :dev, inject the result of (browser-connected-repl-js); if not, don't.
If your deployment environment doesn't have such a property, I'd suggest adding one, as this sort of "only in environment X" use case is pretty common for a lot of things.
On the other hand, if you're looking to avoid having Austin and its dependencies included in your production-targeted builds entirely without changing any of your code that uses browser-connected-repl-js, one solution might be to simply dummy up the relevant Austin namespace, e.g.:
(ns cemerick.austin.repls)
(defn browser-connected-repl-js [& _] "")
Put that in cemerick/austin/repls.clj in a directory that is included in your project.clj's non-:dev profile:source-paths. Now your code will deploy to production without Austin and its dependencies, and your code will transparently call the above dummy function (injecting nothing into your page(s)).
I've heard of two Clojure based web application frameworks: Webjure and Compojure. Can someone let me know which is better?
Now you can add Ring to the list. All of these frameworks are very new and likely to evolve (or die) quickly, but Compojure does seem to be the most actively developed based on the past 6 months or so.
"Better" is too subjective a question to get a definitive answer to. Try them all and see what works.
Compojure has been working very well for me so far. I like the simplicity of the design, the flexibility and the fact that it encourages a nice idiomatic functional style.
Sample server:
(use 'compojure)
(defroutes my-app
(GET "/index.html"
(html
[:h1 "Hello World!!"]
[:body "This is some text"]))
(ANY "*"
[404 "Page not found"]))
(run-server {:port 80}
"/*" (servlet my-app))
Note that Compojure uses Ring internally.
I second Rayne's recommendation on Moustache.
Right now, we are using Ring (base layer, middleware), Moustache (routing), Hiccup (html generation). We just began using Compass for CSS (http://compass-style.org/). So far, I'm happy with this collection of small libraries rather than a big "complete stack" framework (Django, Rails, ect...).
Now, there is also a new one named Noir build on top of compojure. Really recommended, especially with Heroku.
Compojure seems to be getting the most buzz right now. Not necessarily indicative of quality, but the one with the most eyes will probably evolve the fastest.
There is also Moustache, which is what I use in TryClojure, along with Ring. It's pretty awesome.
Compojure is based on Ring, which is a low-level framework that doesn't attempt to hide much of HTTP. It's similar to WSGI (Python) or Rack (Ruby). Ring has a concept of middleware, small pieces of code that can do something meaningful with an HTTP request and/or response, such as dump header infos, manage cookies etc. Compojure is a higher-level framework, somewhat similar to Ruby's Sinatra. Its aim is to provide a convenient API (or DSL, if you prefer) for most tasks a Web app developer faces. It's usually used together with an HTML generation library, such as Hiccup.
I haven't heard much about Webjure in the last few months, I'm not sure it's in active development (but I'd be interested to find out more). It precedes Ring, AFAICT, which seems to have become somewhat of a standard for Clojure Web frameworks.
I've been building a project for my own use using Compojure and it has worked out great. It doesn't really get in the way very much and lets you focus on what's important, your problem domain. The project is about 1100 lines of clojure just to give you an idea of the size.