Parcel: 🙋 Support ClojureScript

Created on 18 May 2018  ·  18Comments  ·  Source: parcel-bundler/parcel

🙋 feature request

Support ClojureScript in Parcel's core

🤔 Expected Behavior

It should compile ClojureScript scripts.

😯 Current Behavior

It does not compile ClojureScript scripts.

💁 Possible Solution

A ClojureScriptAsset should be created as ClojureScript can directly be compiled to JS.

🔦 Context

I want to bundle and compile my ClojureScript files.

💻 Examples

  • index.cljs
(ns hello-world.core)

(println "Hello world!")
  • index.pug
html
  head
    title Parcel + Clojure
  body
    script(src='index.cljs')

Good First Issue Help Wanted Feature

Most helpful comment

There might be a JVM-free option with Lumo: https://anmonteiro.com/2017/02/compiling-clojurescript-projects-without-the-jvm/

I've been looking into this and it should be possible to invoke Lumo from Parcel, with following caveats:

  • Lumo does not have a Javascript API to the compiler, so you would need to generate the CLJS build file¹
  • Lumo does not seem to have an embedding API yet (see anmonteiro/lumo#306) so you would have to go through the Lumo CLI to run the equivalent of npx lumo --classpath src build.cljs
  • Lumo's compiler is relatively slow (even when considering JVM startup time), so it might be a good option for people that don't have a JVM and don't want one, but if there is a JVM on the system, the traditional route might be better, especially for things like parcel watch

1: something like build.cljs

(require '[lumo.build.api :as b])

(b/build "src"
  {:main 'helloworld.core
   :output-to "main.js"
   :optimizations :advanced
   :target :nodejs})

All 18 comments

Hi @xingzhefeng, thanks for opening an issue. I took the liberty to translate it to English and used our issue template so users around the world can contribute.


(translated using Google translate)

嗨 @xingzhefeng,谢谢你打开一个问题。我冒昧地将其翻译成英文,并使用我们的问题模板,以便全世界的用户都能做出贡献。

哈哈,非常好. 辛苦了


(translated using Google translate)

Haha, very good. Hard work.

I'm going to begin work on this! Will open a Pr this week.

good news 👍

@thoughtbyte r u working on this issue?

Looking into this myself, I think there will be issues around using the cljs compiler because it relies on the JVM which has a slow start up time - this is different to parcel's other supported asset types which generally don't have any significant warm up time. To keep things fast it might be better to implement this as a plugin that would spin up the JVM instance in the background.

There might be a JVM-free option with Lumo: https://anmonteiro.com/2017/02/compiling-clojurescript-projects-without-the-jvm/

I've been looking into this and it should be possible to invoke Lumo from Parcel, with following caveats:

  • Lumo does not have a Javascript API to the compiler, so you would need to generate the CLJS build file¹
  • Lumo does not seem to have an embedding API yet (see anmonteiro/lumo#306) so you would have to go through the Lumo CLI to run the equivalent of npx lumo --classpath src build.cljs
  • Lumo's compiler is relatively slow (even when considering JVM startup time), so it might be a good option for people that don't have a JVM and don't want one, but if there is a JVM on the system, the traditional route might be better, especially for things like parcel watch

1: something like build.cljs

(require '[lumo.build.api :as b])

(b/build "src"
  {:main 'helloworld.core
   :output-to "main.js"
   :optimizations :advanced
   :target :nodejs})

Gonna give this a try. Some thoughts below.

I wouldn't go with tooling that is based on bootstrapped ClojureScript, also the tool is not well maintained anymore. Since ClojureScript compiler itself is written in Clojure that runs on JVM, I'd say we should use that. Startup time is not an issue, it's the default, having developed software in ClojureScript I don't see this as something that kills productivity.

Alright, so I've built a custom integration for ClojureScript, based on shadow-cljs, taking Elm integration as an example. But it seems that Parcel switched to a mechanism known as _transformers_, which requires creating a dedicated package and I have no idea how to link it locally for testing. yarn link doesn't help.

Is there a guide/issue on testing transforms locally?

  • Either clone the Parcel repo and add it in packages or
  • create a monorepo setup with a parcel-transformer-closurescript package and an example pacakge. Install parcel@nightly from npm in the example pcakge

@mischnic Thanks. Is there any docs for Transformer class? Trying to understand how to remap Asset style extension into a transformer.

Not at the moment, maybe this is helpful (or the other transformers): https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/coffeescript/src/CoffeeScriptTransformer.js

If not: ask if you have a specific question

@mischnic I see. So I have multiple phases that transform should run

  1. Init cljs build config (parse method?)
  2. Run the compiler (transform method)
  3. Cleanup and return the output (also transform method?)

Looking at examples in Asset style extension the 1st phase is usually done in parse method, which also exists in Transformer class, but I'm not sure if this is a right place. Does people use parse to init configs because it runs before transform?

Does asset.getConfig accept a custom config parser? If not, where to look at so I can create a custom config reader.

Also are there any examples on running tests for transformers?

If you need to load a config file, use the getConfig method:

https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/pug/src/PugTransformer.js

If all you do is "Clojure as a string -> JS as a string/Babel AST", there is no advantage to using parse (which is only beneficial when your transformer could reuse an AST from a previous transformer). You can just do everything (except for loading the config in transform). If Clojure can output a babel compiatble ast, you should do setAST and implement generate().

Does asset.getConfig accept a custom config parser? If not, where to look at so I can create a custom config reader.

If you have something other than JS, JSON or TOML (and is not 100% specific to ClojureScript):
https://github.com/parcel-bundler/parcel/blob/7c0aa3d2b9cd4a8d3cb6135e6b07d05f33406389/packages/core/utils/src/config.js#L17-L20

Also are there any examples on running tests for transformers?

Integration tests: https://github.com/parcel-bundler/parcel/blob/v2/packages/core/integration-tests/test/mdx.js

If you have something other than JS, JSON or TOML (and is not 100% specific to ClojureScript)

The format is specific to Clojure. I'll use referred implementation to build a custom reader.

Another question: What would the strategy of integrating ClojureScript development build with Parcel, given that:

  • In dev ClojureScript does not produce a bundle, just maps source files to output js files
  • ClojureScript has its own hot-reloading system, how that can be integrated with Parcel?

In dev ClojureScript does not produce a bundle, just maps source files to output js files

You have two options in the transformer: return one asset (the bundle that Clojure produced). Or return multiple js assets (be sure that imports between these assets still work).

(In production mode, you might want to also run the Closure Compiler compiler in the transformer since ClojureScript output seems to be optimized for that.)

ClojureScript has its own hot-reloading system, how that can be integrated with Parcel?

I don't know. I'm not familiar with ClojureScript.

@roman01la hey! any good news (or bad ones)?

Was this page helpful?
0 / 5 - 0 ratings