Coder Social home page Coder Social logo

rduplain / hello-cljs Goto Github PK

View Code? Open in Web Editor NEW
8.0 1.0 1.0 180 KB

Hello, world! Native Clojure with ClojureScript and Node.js.

License: Eclipse Public License 1.0

Makefile 39.34% Clojure 13.20% Shell 47.46%
shadow-cljs clojurescript clojure-cli cross-platform clojure nodejs npm gnu-make makefile

hello-cljs's Introduction

Hello ClojureScript

Build Status

Summary

Write code with ClojureScript and npm. Target Node.js. Ship as binaries which run natively without dependencies on GNU/Linux, Mac OS X, FreeBSD, and Windows. The binaries ship with a snapshot filesystem and an embedded Node runtime loaded via ELF/Mach-O/PE32+, respective to the target operating system. Code can include npm modules and ClojureScript (Clojure) libraries.

Project Overview

This project demonstrates tooling for ClojureScript with workflows appropriate to Unix tradition with a build oriented toward general-purpose programming (with Node.js, and not the browser). Build redistributable native binaries with ClojureScript and npm libraries.

While Java is a dependency of Clojure, this project focuses exclusively on building ClojureScript for Node.js. The same workflow applies to other JavaScript targets, namely the browser, if the Clojure deps and npm packages support the runtime. The redistributable binary only applies with a Node.js target, but this workflow can produce a .js file suitable for other JavaScript targets.

Of particular note, both Clojure and JavaScript have many options available to build a project. This demonstration project arrives at many decisions aligned with Unix expectations:

  • Use Clojure command line tools directly, with deps.edn.
  • Use Node.js and npm directly, with package.json (node_modules).
  • Use shadow-cljs to build .js from deps.edn and node_modules.
  • Use pkg to build binaries from node_modules and the built .js file.
  • Use a Makefile (GNU Make) to provide a simple developer workflow.

Dependencies

Development:

Production has no dependencies. The redistributable binaries run natively on GNU/Linux, Mac OS X, and Windows, respectively.

Workflow

Development:

  • make -- Test, build binaries, and test platform binary (make release).
  • make bin -- Create redistributable binaries.
  • make build -- Build the ClojureScript project into a single .js file.
  • make install -- Install packages; this is run automatically.
  • make outdated -- Check for outdated packages.
  • make release -- Test, build binaries, and test platform binary.
  • make repl -- Run a ClojureScript repl. (Use an IDE instead, below.)
  • make test-refresh -- Run project tests and watch for changes.
  • make test -- Run project tests.

To build a binary for FreeBSD, set up a development environment and run make release-for-os on a FreeBSD system, with resulting binary at ./target/hello.

Production:

  • After running make, find redistributable binaries in ./target/bin-*/.
  • The redistributable binaries run natively without dependencies on GNU/Linux, Mac OS X, and Windows, respectively.
  • The binaries include their own Node.js runtime and therefore are relatively large (tens of megabytes) compared to other system executables.
  • If needed, these binaries compress by a factor of 3 with bzip2. A release step could publish compressed binaries with an install step which decompresses and puts the binary on the PATH.

Integrated Development Environment

Run M-x cider-jack-in from Emacs with CIDER, using shadow-cljs as the command. Once loaded, in the CIDER clj repl, start a CLJS repl with:

(require '[shadow.cljs.devtools.api :as shadow])
(shadow/node-repl :app)

Note that shadow-cljs has a fake piggieback; use the shadow-cljs snippet above in a clj repl to create the cljs repl instead of using M-x cider-jack-in-cljs. Alternatively, load the snippet above into a custom cljs repl type in CIDER with its cider-register-cljs-repl-type function and use M-x cider-jack-in-cljs on that newly registered type.

While cider-connect is available, the available tools are best run separately as to allow repl interactions separately from the build process. Start this CIDER repl before starting any other shadow-cljs process.

Using npm Packages

shadow-cljs loads any module found in the node_modules directory. See this guide for example require forms.

Using Macros

Keep in mind that ClojureScript has differences from Clojure:

ClojureScript’s macros must be defined in a different compilation stage than the one from where they are consumed. One way to achieve this is to define them in one namespace and use them from another.

To use a macro in a ClojureScript project, define the macro in a .clj or .cljc file. In a cljs (ns ...) form, reference macros with the (:require-macros ...) form, which has the same format as (:require ...). Note that ClojureScript compiler :optimizations set to :none in development will result in Node.js loading separate files. In effect, this means that any namespace references in a macro will not be automatically brought forward when requiring the macro during a repl session or when tests are running (unless using shadow-cljs release subcommand to compile the tests into a single file), and names will not resolve and will be undefined in the resulting macro-expanded code.

In development:

  • In the repl, load the requisite macro definition and its require calls.
  • In the cljs test matching the macro definition, require the namespaces which will allow the expanded macro to fully resolve its references.

These steps are only strictly required in development; the production build compiles a single .js and Node.js and may find the relevant references. Test accordingly.

Wishlist


Copyright (c) 2018-2020, Ron DuPlain. EPL-1.0 licensed. Use freely on projects with any license, including proprietary work.

hello-cljs's People

Contributors

rduplain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

mekkanikka

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.