Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 390 lines (289 sloc) 13.618 kb
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
1 # lein-cljsbuild
2
cb80cbc Evan Mezeske Preparing for release.
authored
3 This is a leiningen plugin that makes it easy (and quick) to compile
4 ClojureScript source into JavaScript. It's similar to [cljs-watch] [1],
4e13bbd Evan Mezeske Proselytism improvements.
authored
5 but is driven via lein instead of via a standalone executable. This means
6 that your project can depend on a specific version of lein-cljsbuild, fetch
7 it via `lein deps`, and you don't have to install any special executables into
8 your `PATH`.
cb80cbc Evan Mezeske Preparing for release.
authored
9
91e8506 Evan Mezeske Adding crossover support and examples.
authored
10 Also, this plugin has built-in support for seamlessly sharing code between
11 your Clojure server-side project and your ClojureScript client-side project.
12
cb80cbc Evan Mezeske Preparing for release.
authored
13 [1]: https://github.com/ibdknox/cljs-watch
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
14
c391aaf Evan Mezeske Doc updates. Fixes #20.
authored
15 ## Requirements
16
0b2edaa Evan Mezeske Initial changes for Leiningen 1.7 compatibility.
authored
17 The lein-cljsbuild plugin works with [Leiningen] [2] version `1.6.2` or higher,
18 although 1.7.0 or higher is recommended.
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
19
c391aaf Evan Mezeske Doc updates. Fixes #20.
authored
20 [2]: https://github.com/technomancy/leiningen/blob/master/README.md
cb80cbc Evan Mezeske Preparing for release.
authored
21
c391aaf Evan Mezeske Doc updates. Fixes #20.
authored
22 ## Installation
cb80cbc Evan Mezeske Preparing for release.
authored
23
0b2edaa Evan Mezeske Initial changes for Leiningen 1.7 compatibility.
authored
24 If you're using Leiningen `1.7.0` or newer, you can install the plugin by
25 adding lein-cljsbuild to your `project.clj` file in the `:plugins` section:
cb80cbc Evan Mezeske Preparing for release.
authored
26
593631b Evan Mezeske Try to appease github's markdown flavor.
authored
27 ```clojure
0b2edaa Evan Mezeske Initial changes for Leiningen 1.7 compatibility.
authored
28 ; Using Leiningen 1.7.0 or newer:
91e8506 Evan Mezeske Adding crossover support and examples.
authored
29 (defproject lein-cljsbuild-example "1.2.3"
ba8b27c Evan Mezeske Bump the version.
authored
30 :plugins [[lein-cljsbuild "0.1.0"]])
0b2edaa Evan Mezeske Initial changes for Leiningen 1.7 compatibility.
authored
31 ```
32
33 For versions of Leiningen older than `1.7.0` (not recommended), add
34 lein-cljsbuild to the `:dev-dependencies` section instead:
35
36 ```clojure
37 ; Using Leiningen 1.6.x or older:
38 (defproject lein-cljsbuild-example "1.2.3"
ba8b27c Evan Mezeske Bump the version.
authored
39 :dev-dependencies [[lein-cljsbuild "0.1.0"]])
593631b Evan Mezeske Try to appease github's markdown flavor.
authored
40 ```
cb80cbc Evan Mezeske Preparing for release.
authored
41
42 Make sure you pull down the jar file:
43
44 $ lein deps
45
91e8506 Evan Mezeske Adding crossover support and examples.
authored
46 ## Just Give Me a Damned Example Already!
47
48 See the `example-projects` directory for a couple of simple examples
49 of how to use lein-cljsbuild.
50
0113e9f Evan Mezeske s/example/sample.
authored
51 Also, see the `sample.project.clj` file in this directory for an
31039ba Evan Mezeske Add a note about example.project.js.
authored
52 exhaustive list of all options supported by lein-cljsbuild.
53
6c54184 Evan Mezeske Document the new parallel build feature.
authored
54 ## Basic Configuration
cb80cbc Evan Mezeske Preparing for release.
authored
55
56 The lein-cljsbuild configuration is specified under the `:cljsbuild` section
91e8506 Evan Mezeske Adding crossover support and examples.
authored
57 of your `project.clj` file. A simple project might look like this:
cb80cbc Evan Mezeske Preparing for release.
authored
58
593631b Evan Mezeske Try to appease github's markdown flavor.
authored
59 ```clojure
91e8506 Evan Mezeske Adding crossover support and examples.
authored
60 (defproject lein-cljsbuild-example "1.2.3"
ba8b27c Evan Mezeske Bump the version.
authored
61 :plugins [[lein-cljsbuild "0.1.0"]]
593631b Evan Mezeske Try to appease github's markdown flavor.
authored
62 :cljsbuild {
2ec547a Evan Mezeske Massive documentation update for REPL stuff.
authored
63 :builds [{
64 ; The path to the top-level ClojureScript source directory:
65 :source-path "src-cljs"
66 ; The standard ClojureScript compiler options:
67 ; (See the ClojureScript compiler documentation for details.)
68 :compiler {
69 :output-to "war/javascripts/main.js" ; default: main.js in current directory
70 :optimizations :whitespace
71 :pretty-print true}}]})
593631b Evan Mezeske Try to appease github's markdown flavor.
authored
72 ```
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
73
3138773 Evan Mezeske Add a note about sample.project.clj.
authored
74 For an exhaustive list of the configuration options supported by lein-cljsbuild,
75 see the `sample.project.clj` file in this directory.
c391aaf Evan Mezeske Doc updates. Fixes #20.
authored
76
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
77 ## Usage
78
cb80cbc Evan Mezeske Preparing for release.
authored
79 Once the plugin is installed, you can build the ClojureScript once:
80
81 $ lein cljsbuild once
82
83 Or you can have lein-cljsbuild watch your source files for changes and
84 automatically rebuild them. This is recommended for development, as it
85 avoids the time-consuming JVM startup for each build:
86
87 $ lein cljsbuild auto
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
88
d40c3a9 Evan Mezeske Add a "cljsbuild clean" task, and hook into "clean".
authored
89 To delete all of the JavaScript and ClojureScript files that lein-cljsbuild
90 automatically generated during compilation, run:
91
92 $ lein cljsbuild clean
93
3138773 Evan Mezeske Add a note about sample.project.clj.
authored
94 ## Hooks
95
96 If you'd like your ClojureScript to be compiled when you run `lein compile`, and
97 deleted when you run `lein clean`, add the following entry to your project
98 configuration:
99
100 ```clojure
101 :hooks [leiningen.cljsbuild]
102 ```
103
104 Note that this is also required for lein-cljsbuild to hook into the `lein jar`
105 task. For that to work, you will also need to explicitly enable the `jar` hook
106 by adding the following entry to your :cljsbuild configuration map:
107
108 ```clojure
109 :jar true
110 ```
111
6c54184 Evan Mezeske Document the new parallel build feature.
authored
112 ## Multiple Build Configurations
113
2ec547a Evan Mezeske Massive documentation update for REPL stuff.
authored
114 If the `:builds` sequence contains more than one map lein-cljsbuild
115 will treat each map as a separate ClojureScript compiler configuration,
116 and will build all of them in parallel:
6c54184 Evan Mezeske Document the new parallel build feature.
authored
117
118 ```clojure
119 (defproject lein-cljsbuild-example "1.2.3"
ba8b27c Evan Mezeske Bump the version.
authored
120 :plugins [[lein-cljsbuild "0.1.0"]]
2ec547a Evan Mezeske Massive documentation update for REPL stuff.
authored
121 :cljsbuild {
122 :builds [
123 {:source-path "src-cljs-main"
124 :compiler {:output-to "main.js"}}
125 {:source-path "src-cljs-other"
126 :compiler {:output-to "other.js"}}}])
6c54184 Evan Mezeske Document the new parallel build feature.
authored
127 ```
128
129 This is extremely convenient for doing library development in ClojureScript.
130 This allows cljsbuild to compile in all four optimization levels at once, for
131 easier testing, or to compile a test suite alongside the library code.
132
133 See the `example-projects/advanced` directory for a working example of a
134 project that uses this feature.
135
2ec547a Evan Mezeske Massive documentation update for REPL stuff.
authored
136 ## REPL Support
137
138 Lein-cljsbuild has built-in support for launching ClojureScript REPLs in a variety
139 of ways. Note as of Leiningen 1.x, all plugin REPL commands must be launched
140 via `lein trampoline` to work correctly.
141
142 ### repl-rhino
143
144 The simplest REPL uses Rhino to evaluate the JavaScript that results from compiling
145 your ClojureScript input. This REPL does not have access to your project's namespaces,
146 and is not evaluated in a browser context. It is, however, useful for running simple
147 pure-ClojureScript commands. It is also the only REPL option that does not require
148 your application to provide additional support code:
149
150 $ lein trampoline cljsbuild repl-rhino
151
152 ### repl-listen
153
154 The next REPL is more sophisticated. With support from your application, it is possible
155 to use `repl-listen` to run a REPL with access to your application's ClojureScript namespaces.
156 The REPL may be started as follows:
157
158 $ lein trampoline cljsbuild repl-listen
159
160 This will open a REPL, which will listen on a TCP port for a ClojureScript application
161 to connect to it. By default, it will listen on port `9000`, although this may be changed
162 via the `:repl-listen-port` option. Until a connection is received, the REPL will not be
163 usable.
164
165 From your application, you can connect to the REPL with code such as this:
166
167 ```clojure
168 (ns lein-cljsbuild-example.repl
169 (:require [clojure.browser.repl :as repl]))
170 ; Use of "localhost" will only work for local development.
171 ; Change the port to match the :repl-listen-port.
172 (repl/connect "http://localhost:9000/repl")
173 ```
174
175 For instance, you might include the above call to `repl/connect` in the code for
176 a particular web page served by your application. So, you would launch your application,
177 launch `repl-listen`, and then browse to that page. It would then connect to the REPL,
178 enabling you to execute commands in the context of that page.
179
180 For more information on this approach, see the [ClojureScript Wiki] [3].
181
182 [3] https://github.com/clojure/clojurescript/wiki/Quick-Start
183
184 ### repl-launch
185
186 Finally, the most sophisticated REPL. Like `repl-listen`, `repl-launch` requires
187 application support code to function. The difference between `repl-listen` and `repl-launch`
188 is that the latter may be configured to automatically launch the browser after starting
189 the REPL. This REPL is launched as follows:
190
191 $ lein trampoline cljsbuild repl-launch <launch-id>
192
193 Of course, this won't work until you've told lein-cljsbuild what to launch. Multiple
194 launch presets may be created, and thus the `<launch-id>` parameter is used to select
195 between them. To configure a launch preset, add an entry to the `:repl-launch-commands` map:
196
197 ```clojure
198 (defproject lein-cljsbuild-example "1.2.3"
199 :plugins [[lein-cljsbuild "0.1.0"]]
200 :cljsbuild {
201 :repl-listen-port 9000
202 :repl-launch-commands
203 {"my-launch" ["firefox" "-jsconsole" "http://localhost/my-page"]})
204 ```
205
206 With this configuration, the launch preset is identified by `my-launch`. When a REPL
207 is started with this launch preset, `firefox -jsconsole http://localhost/my-page`
208 will be run in the background, and presumably the page it loads will connect to the REPL:
209
210 $ lein trampoline cljsbuild repl-launch my-launch
211
212 Note that any additional arguments following the `<launch-id>` will be passed to the
213 launch command. Thus, with a configuration such as:
214
215 ```clojure
216 :repl-launch-commands
217 {"my-other-launch" ["firefox" "-jsconsole"}
218 ```
219
220 The target URL could be selected like so:
221
222 $ lein trampoline cljsbuild repl-launch my-other-launch http://localhost/another-page
223
224 For more ideas on how to use `repl-launch`, take a look at `example-projects/advanced`.
225 It has several examples of useful launch commands, with descriptions in its README.
226 Note that, in particular, the possibilities with [PhantomJS] [4] are very intriguing.
227
228 [4] http://www.phantomjs.org/
229
91e8506 Evan Mezeske Adding crossover support and examples.
authored
230 ## Sharing Code Between Clojure and ClojureScript
231
232 Sharing code with lein-cljsbuild is accomplished via the configuration
c5b2f41 Evan Mezeske Document the use of CLASSPATH for crossovers.
authored
233 of "crossovers". A crossover specifies a Clojure namespace, the content
234 of which should be copied into your ClojureScript project. This can be any
235 namespace that is available via the Java CLASSPATH, which includes your
236 project's main :source-path by default.
237
238 When a crossover namespace is provided by your current project (either via the
239 main :source-dir or one of the :extra-classpath-dirs in your project.clj file),
240 the files that make up that namespace (recursively) will be monitored for changes,
241 and will be copied to the ClojureScript project whenever modified.
242
243 Crossover namespaces provided by jar files cannot be searched recursively, and
244 thus must be specified on a per-file basis. They are copied over once, when
245 lein-cljsbuild begins compilation, and are not monitored for changes.
246
247 Of course, remember that since the namespace will be used by both Clojure
41bcef7 Evan Mezeske Use namespaces for crossovers instead of dirs.
authored
248 and ClojureScript, it will need to only use the subset of features provided by
91e8506 Evan Mezeske Adding crossover support and examples.
authored
249 both languages.
250
41bcef7 Evan Mezeske Use namespaces for crossovers instead of dirs.
authored
251 Assuming that your top-level directory structure looks something like this:
91e8506 Evan Mezeske Adding crossover support and examples.
authored
252
253 <pre>
254 ├── src-clj
255 │   └── example
256 │   ├── core.clj
257 │   ├── something.clj
258 │   └── crossover
259 │      ├── some_stuff.clj
260 │      └── some_other_stuff.clj
261 └── src-cljs
262    └── example
263    ├── core.cljs
264    ├── whatever.cljs
265    └── util.cljs
266 </pre>
267
41bcef7 Evan Mezeske Use namespaces for crossovers instead of dirs.
authored
268 And your `project.clj` file looks like this:
91e8506 Evan Mezeske Adding crossover support and examples.
authored
269
270 ```clojure
271 (defproject lein-cljsbuild-example "1.2.3"
ba8b27c Evan Mezeske Bump the version.
authored
272 :plugins [[lein-cljsbuild "0.1.0"]]
91e8506 Evan Mezeske Adding crossover support and examples.
authored
273 :source-path "src-clj"
274 :cljsbuild {
2ec547a Evan Mezeske Massive documentation update for REPL stuff.
authored
275 :builds [{
276 :source-path "src-cljs"
277 ; Each entry in the :crossovers vector describes a Clojure namespace
278 ; that is meant to be used with the ClojureScript code as well.
279 ; The files that make up this namespace will be automatically copied
280 ; into the ClojureScript source path whenever they are modified.
281 :crossovers [example.crossover]
282 :compiler {
283 :output-to "war/javascripts/main.js" ; default: main.js in current directory
284 :optimizations :whitespace
285 :pretty-print true}}]})
91e8506 Evan Mezeske Adding crossover support and examples.
authored
286 ```
287
288 Then lein-cljsbuild would copy files from `src-clj/example/crossover`
289 to `src-cljs/example/crossover`, and you'd end up with this:
290
291 <pre>
292 ├── src-clj
293 │   └── example
294 │   ├── a_file.clj
295 │   ├── core.clj
296 │   └── crossover
297 │      ├── some_stuff.clj
298 │      └── some_other_stuff.clj
299 └── src-cljs
300    └── example
301    ├── a_different_file.cljs
302    ├── crossover
303    │   ├── some_stuff.cljs
304    │   └── some_other_stuff.cljs
305    ├── whatever.cljs
306    └── util.cljs
307 </pre>
308
309 With this setup, you would probably want to add `src-cljs/example/crossover`
310 to your `.gitignore` file (or equivalent), as its contents are updated automatically
311 by lein-cljsbuild.
312
313 ## Sharing Macros Between Clojure and ClojureScript
314
315 In ClojureScript, macros are still written in Clojure, and can not be written
316 in the same file as actual ClojureScript code. Also, to use them in a ClojureScript
317 namespace, they must be required via `:require-macros` rather than the usual `:require`.
318
319 This makes using the crossover feature to share macros between Clojure and ClojureScript
320 a bit difficult, but lein-cljsbuild has some special constructs to make it possible.
321
322 Three things need to be done to use lein-cljsbuild to share macros.
323
324 ### 1. Keep Macros in Separate Files
325
326 These examples assume that your project uses the `src-clj/example/crossover`
327 directory, and that all of the macros are in a file called
328 `src-clj/example/crossover/macros.clj`.
329
330 ### 2. Tell lein-cljsbuild Which Files Contain Macros
331
332 Add this magical comment to any crossover files that contain macros:
333
334 ```clojure
335 ;*CLJSBUILD-MACRO-FILE*;
336 ```
337
c5b2f41 Evan Mezeske Document the use of CLASSPATH for crossovers.
authored
338 This tells lein-cljsbuild to refrain from copying the `.clj` files
339 into the ClojureScript directory. This step can be skipped if the
340 macro file is not included in any of the crossover namespaces.
91e8506 Evan Mezeske Adding crossover support and examples.
authored
341
342 ### 3. Use Black Magic to Require Macros Specially
343
344 In any crossover Clojure file, lein-cljsbuild will automatically erase the
345 following string (if it appears):
346
347 ```clojure
348 ;*CLJSBUILD-REMOVE*;
349 ```
350
351 This magic can be used to generate a `ns` statement that will work in both
352 Clojure and ClojureScript:
353
354 ```clojure
355 (ns example.crossover.some_stuff
356 (:require;*CLJSBUILD-REMOVE*;-macros
357 [example.crossover.macros :as macros]))
358 ```
359
360 Thus, after removing comments, Clojure will see:
361
362 ```clojure
363 (ns example.crossover.some_stuff
364 (:require
365 [example.crossover.macros :as macros]))
366 ```
367
368 However, lein-cljsbuild will remove the `;*CLJSBUILD-REMOVE*;` string entirely,
369 before copying the file. Thus, ClojureScript will see:
370
371 ```clojure
372 (ns example.crossover.some_stuff
373 (:require-macros
374 [example.crossover.macros :as macros]))
375 ```
376
377 And thus the macros can be shared.
378
e0219ff Evan Mezeske Initial commit of lein-cljsbuild.
authored
379 ## License
380
460cada Shantanu Kumar fix typo in documentation
kumarshantanu authored
381 Source Copyright © Evan Mezeske, 2011-2012.
cb80cbc Evan Mezeske Preparing for release.
authored
382 Released under the Eclipse Public License - v 1.0.
383 See the file COPYING.
27ded34 Evan Mezeske Add a contributors section.
authored
384
385 ## Contributors
386
387 * Evan Mezeske **(Author)** (evan@mezeske.com)
388 * Shantanu Kumar (kumar.shantanu@gmail.com)
7604367 Evan Mezeske Add Luke VanderHart to the contributor list.
authored
389 * Luke VanderHart (http://github.com/levand)
Something went wrong with that request. Please try again.