Hi Oliver,

clj is a shell script that provides an interface to several functions 
within the clojure JAR file. The first time you run it, clj has to download 
the clojure JAR and store it in your $HOME/.m2/repository directory tree 
for later use.

Every time you run clj, it will check the current directory to see if there 
is a deps.edn file present. If so, it will read the :deps map from it to 
determine which dependency libraries need to be made available on your JVM 
classpath. Any which have not already been downloaded to 
$HOME/.m2/repository will be downloaded at this point and save for later 
use.

Note, in particular, that to compile clojurescript to javascript, you must 
include the clojurescript JAR in your deps.edn file. This will ensure that 
it is downloaded to $HOME/.m2/repository and added to your classpath, so 
that the `--main cljs.main --compile hello-world.core --repl` command can 
be evaluated successfully.

At a minimum, you will need to add this to your project's deps.edn file in 
order to run the clj command you provided:

```clojure
{:paths ["src/cljs"]
 :deps  {org.clojure/clojure       {:mvn/version "1.10.3"}
         org.clojure/clojurescript {:mvn/version "1.10.866"}}}
```
Next, create the file src/cljs/hello_world/core.cljs, containing this code:

```clojure
(ns hello-world.core)

(defn say-hello []
  (js/alert "Hello from CLJS!"))

(say-hello)
```

At this point, your directory tree should look like this:

.
├── deps.edn
└── src
    └── cljs
        └── hello_world
            └── core.cljs

Now you are ready to compile core.cljs into Javascript. Let's run the 
command you provided in your original post:

clj -M --main cljs.main --compile hello-world.core --repl

This will read deps.edn, make sure you have the clojure and clojurescript 
JARs in $HOME/.m2/repository (or download them if not), spin up a JVM with 
src/cljs and both JARs on its classpath, load the cljs.main namespace (from 
the clojurescript JAR), and run its -main method with ["--compile" 
"hello-world.core" "--repl"] as its arguments. This -main method is the 
entrypoint function for the clojurescript compiler, which then loads the 
hello-world.core namespace (found under src/cljs/hello_world/core.cljs <-- 
note that - in namespaces becomes _ in filenames). The clojurescript 
compiler then compiles your code into javascript under the out/ directory 
by default. Finally, since you passed the "--repl" argument, a web browser 
window will be opened and pointed to http://localhost:9000, which loads up 
a default webpage provided the clojurescript JAR file, that contains 
javascript code to connect back to your clj REPL, so that the browser can 
act as the runtime environment for your javascript code as well as any 
forms that you type at the REPL.

Since your code included a call to (say-hello) at the toplevel, this 
function will be run as soon as the page loads, which will display a 
javascript alert box in your browser window with the text "Hello from 
CLJS!" in it.

To verify that everything is working correctly, you'll want to use require 
and in-ns to load and navigate to your hello-world.core namespace in the 
REPL. Then you can run the (say-hello) function again interactively. Here's 
the command sequence you want to type:

ClojureScript 1.10.866
cljs.user=> (require 'hello-world.core)
nil
cljs.user=> (in-ns 'hello-world.core)
nil
hello-world.core=> (say-hello)
nil

If everything works correctly, you'll see the familiar javascript alert box 
pop up in your browser window with the text "Hello from CLJS!" in it.

Now,  although this shows that your clojurescript to javascript compilation 
is working correctly, it doesn't provide a straightforward path to simply 
copy your javascript into a separate web application and load it. That's 
because in order for your say-hello function to work, you need to include 
not only your generated javascript (from hello-world.core) but also all the 
javascript for the clojurescript and google closure systems that are the 
necessary dependencies here. If you look at out/main.js, you'll see the 
javascript code that your browser window loads when it starts up the 
browser REPL page. This code injects script tags into the page to loads the 
clojurescript and google closure dependencies, then the browser repl code, 
and finally loads your hello_world.core javascript file (note again that 
javascript module names use _ rather than - as in clojurescript).

If you look in out/hello_world/core.js, you'll see just the javascript that 
your clojurescript file generated:

```javascript
goog.provide('hello_world.core');
goog.require('cljs.core');
hello_world.core.say_hello = (function hello_world$core$say_hello(){
return alert("Hello from CLJS!");
});
```

What you'll need to do for your simple practice example is to tell the 
clojurescript compiler to combine all of the javascript that was generated 
from your hello_world/core.cljs file together with all of its dependencies 
into a single file, prune all of it to remove everything that you don't 
absolutely need to make your code work, minify all the variable and 
function names, and remove the whitespace, so it loads quickly. That, my 
friend, is what we call "advanced mode compilation". You can enable it with 
this command:

clj -M --main cljs.main --optimizations advanced --output-to app.js 
--compile hello-world.core

When this command finishes, you'll find a file called app.js in the current 
directory. Make a file called index.html in the current directory 
containing this code:

```html
<html>
    <head>
        <title>CLJS Test Page</title>
        <script type="text/javascript" src="app.js"></script>
    </head>
    <body>
        Did you see an alert box?
    </body>
</html>
```

Now simply open index.html in your web browser, and you'll see the same 
alert box as before pop up with the text "Hello from CLJS!" in it.

Hopefully, that will give you the tools you need to get your feet wet with 
clojurescript programming. You can see all the command line options for the 
clojurescript compiler by running this command:

clj -M --main cljs.main -h

Also, please keep in mind that clojurescript developers don't usually work 
directly at the command line like this. Instead, they would usually use a 
tool like figwheel-main or shadow-cljs to automate the compilation process 
and hot-load live code changes to your browser during development.

Welcome again to the wonderful world of clojure and clojurescript 
programming. Have fun and happy hacking!

~Gary

On Thursday, July 1, 2021 at 9:52:07 AM UTC-4 Oliver Baumann wrote:

>
> Total newbie tries out ClojureScript...
>
> Got Clojure installed, chcekd that clj works. Then I walked through the 
> Getting Started tutorial, but get stuck on the compile (i.e. transpile?) 
> step: 
>
> I execute on the command line
>
> clj -M --main cljs.main --compile hello-world.core --repl
>
> and get 
>
> Error building classpath. Failed to read artifact descriptor for 
> org.clojure:clojure:jar:1.10.3
> ...
> Caused by: java.io.EOFException: SSL peer shut down incorrectly
> ...
>
> Looks like I need an internet connection to transpile the hello_world 
> file? Or do I something else totally wrong?
>
> How can I transpile a simple dependency-less file to JavaScript without 
> internet connection?
>

-- 
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/clojurescript/0bd7a41a-d874-40c4-bdaa-cb8d2d7a92d6n%40googlegroups.com.

Reply via email to