Any chance we can fit ClojureScript into Webpack ecosystem?

1,268 views
Skip to first unread message

Jiyin Yiyong

unread,
May 11, 2017, 12:45:02 AM5/11/17
to ClojureScript
Already an old boring topic... I'm from JavaScript side and so many people are building apps with Webpack. And so many of alt-js languages got Webpack loaders:

BuckleScript https://github.com/rrdelaney/bs-loader
PureScript https://github.com/ethul/purs-loader
Elm https://github.com/elm-community/elm-webpack-loader
Fable https://github.com/fable-compiler/Fable

Exception:

No Webpack for ReasonML https://github.com/chenglou/reason-react-example/blob/master/webpack.config.js

Can we make a loader for ClojureScript?

Or how about the possibility? I guess Closure Compiler will get in the why. But is it possible if I don't use dead code elimination from Closure Compiler? I know many people need it but seriously no other solutions? And how much does ClojureScript depend on Closure Library?

Thomas Heller

unread,
May 11, 2017, 6:08:30 AM5/11/17
to ClojureScript
IMHO the webpack ecosystem and CLJS can live happily side by side, why is it important that they know about each other? Good JS interop ensures that both sides can interact well.

What would you expect from a loader that you'd be willing to give up the Closure Compiler?

Jiyin Yiyong

unread,
May 11, 2017, 9:10:47 AM5/11/17
to ClojureScript

Unhappy. Bundling ClojureScript projects is a pain since we have to use both JVM(or Lumo in near future) and Webpack(for CSS and images). And we have to use 2 package managers, npm and Clojars. It might not be a big deal for a Clojure developer who accidentally write web pages, but it's heavy work for front-end developers to use 2 sets of toolchains for our projects.

Nowadays Webpack contains lots of features for real world projects, like long time caching, async loading, assets bundling, with all kinds of loaders, that are not supported(or polished) by Closure Compiler. And that also means many companies who use Webpack just need them.

Jonas Kello

unread,
May 11, 2017, 2:15:53 PM5/11/17
to ClojureScript
ReasonML can be compiled by bucklescript loader AFAIK. However I think that will make it compile slower.

Shaun LeBron

unread,
May 11, 2017, 6:11:50 PM5/11/17
to ClojureScript
I'm from the JS side as well, so I'm glad to see this question! Are you imagining something like the following? We should probably start by imagining why someone would want to require cljs this way and if it would even make sense to:

```
require('cljs!./src-cljs') // return all goog.provided namespaces?
require('cljs!./src-cljs/foo/core.cljs') // return a single goog.provide namespace?
```

Either way I think it would need Closure Compiler to return a single asset for each require statement, if I understand webpack correctly.

It's worth mentioning that the recent "node-jre" package allows users to install/use the full cljs JVM compiler in its fully glory through npm without any external dependencies, which I've tested here: https://github.com/cljs/tool

I think it's possible—just unsure of webpack use-cases. Thoughts?

jiyinyiyong

unread,
May 11, 2017, 11:57:58 PM5/11/17
to clojur...@googlegroups.com
It would be nice if we can require ClojureScript in JavaScript, and let Webpack to handle so many issues.

For Webpack use cases, I tried to sell ClojureScript to other front-end developers around me, but saw some problems:

* IMPORTANT: hard to install JVM. For JavaScript projects, installing Node.js(with npm inside) would be okay. It's very hard for JavaScript developers to pick up JVM and Boot(or Leiningen).
* IMPORTANT: long time caching and code splitting. We use these features in production for years. But I don't see a good solution in ClojureScript.
* Async code loading. For large projects some code can be loaded when a router is activated. No good solution found in ClojureScript.
* Assets bundling. Now we rely on Webpack to do that, result in using 2 tools.

Not sure if they can be solved if we have a ClojureScript running on Webpack. But there are many compiled-to-js languages support those features in by supporting Webpack already. That's the purpose behind the post.

Didn't try `node-jre`. I'm guessing we still need to debug JVM stuffs since it's running JVM?

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/HNuYCfPRtQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

Thomas Heller

unread,
May 12, 2017, 4:55:24 AM5/12/17
to ClojureScript
I'm way too biased towards the Closure Compiler and giving that up is simply not an option for me. I am however very interested in making things simpler for everyone.

https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-libraries

This is an example of how I intend to do that for node libraries, ie. something you just require. This actually bundles things up in a UMD format so the same can work for non-node environments. I would happily add a :browser-umd target that solves some of the issues for webpack users.

https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser

I have used the underlying shadow-build for over 3 years now to do code-splitting with permanent caching of generated files (ie. each generated file has a unique name). I also recently added the :module-loader which lets you async load modules on demand.

Not sure what asset bundling does so no comment on that.

I can't do anything about the JVM. I have been using it for too long so I may be blind to the issues people are having with it. It isn't that bad?

I would say there is actually a good solution to the issues you mention. They just aren't available in the "mainstream" tools and I suck at writing documentation. I'm happy to provide examples any time but need help with the writing.

Coming back to the webpack loader: I have a few ideas how I would write such a thing. The issue I see, and why I don't, is that the end result is bad. CLJS is built very much with the GCL in mind. cljs/core.js is 1.2MB (151KB gzip) unoptimized. One large file is very non-idiomatic npm/webpack. That also does not contain any user code. UglifyJS is able to shorten some of the code but you still keep about 84K gzip'd. To me that is unacceptable.

Web-targeted JS needs to be optimized as much as possible and currently that means using the GCL. I don't want to create a "simple" solution that sacrifices this just to make dev-time easier.

I have been CLJS first for too long now to imagine which issues people are having who are webpack first. Happy to discuss ideas or proposals. Maybe there are ways (like the :node-library, :node-script) that could work even in :advanced mode.

jiyinyiyong

unread,
May 12, 2017, 7:46:32 AM5/12/17
to clojur...@googlegroups.com
I used ClojureScript for a year. Probably there are tricks from Closure Compiler that I have no idea.

For the size, I saw some of the sites I often use have large JavaScript size(with Disable Cache ticked):

weibo.com 1.2M
Twitter 437K
image.png
image.png
image.png
I don't think 84k is a very big deal, while it is for smaller websites. Besides, we may cache and sure the cljs.core.js part, we may use Prepack in the future. In my case it's tolerable.

Today, using tools like https://github.com/facebookincubator/create-react-app and https://github.com/vuejs/vue-cli we almost get long time caching and code splitting with only several lines of code, with assets(images, fronts) bundling out of box. Hard to imagine we sell those people ClojureScript without competitive features.

It would still be awesome if you can share about code splitting and permanent caching in ClojureScript :)

Thomas Heller

unread,
May 12, 2017, 9:23:07 AM5/12/17
to ClojureScript
I wrote some things down here:
https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-the-browser#productionrelease-builds

Code splitting is done by the :modules, whether or not you want to use the loader is up to you. I personally don't but that is because I have a rather traditional website that actually has different pages and I can determine which modules are needed based on the page. If you have an actual SPA you probably want to use the loader.

:module-hash-names and :bundle-foreign are the caching bits. I just added the :module-hash-names since that was still in my private build config, but that was in use for about 3 years.


I had an idea for webpack, I'll let you know if it works out.


On Friday, May 12, 2017 at 1:46:32 PM UTC+2, Jiyin Yiyong wrote:
> I used ClojureScript for a year. Probably there are tricks from Closure Compiler that I have no idea.
>
>
> For the size, I saw some of the sites I often use have large JavaScript size(with Disable Cache ticked):
>
>
> weibo.com 1.2M
>
>
> Twitter 437K
> teambition.com 1.9M
>
>
>

Andrea Richiardi

unread,
May 12, 2017, 1:13:18 PM5/12/17
to ClojureScript
On Friday, May 12, 2017 at 1:55:24 AM UTC-7, Thomas Heller wrote:
> I'm way too biased towards the Closure Compiler and giving that up is simply not an option for me. I am however very interested in making things simpler for everyone.
>
> https://github.com/thheller/shadow-devtools/wiki/ClojureScript-for-node.js-libraries
>


This looks very nice, with a colleague here we event went as far as thinking, what if we completely drop GCP support for node.js targets.
We talked about this a bit on Clojurians, I like your idea to get closer to the node way. I am not a JS dev at all, but I understand the pain of existing JS devs when they approach the ClojureScript world.
They need to change everything they know, not only learn a language but also new (JVM) tooling. Many say no thanks, which is a pity because they are missing out :D

I have recently worked on a POC using Reason. The tooling is rough but it fits the JS ecosystem. The compiler is super fast (faster than Typescript even on my machine!). We ended up picking Typescript because of the tooling basically for a zero version of our stuff. I already don't like it that much ah ah.

jiyinyiyong

unread,
May 12, 2017, 1:29:53 PM5/12/17
to clojur...@googlegroups.com
Time not enough to read every detail, but I found it great that most of my points are covered in the Wiki, code splitting, file hashing, async loading.

However I think it's not we current have for all ClojureScript users, since it's implemented by yourself based on lein, like hashing https://github.com/thheller/shadow-devtools/blob/de6ede2add891aa798a3109c596ecafefdff94fe/src/main/shadow/cljs/devtools/targets/browser.clj#L235-L237 I'm a Boot user, and it became a problem.

I heard about goog.module.ModuleManager before but never thought I could make use of it given that fact it was poorly documented... Your project is cool.

Thomas Heller

unread,
May 12, 2017, 1:48:52 PM5/12/17
to ClojureScript

> However I think it's not we current have for all ClojureScript users, since it's implemented by yourself based on lein

That is incorrect. It is a pure Clojure library with no dependency on leiningen. I just happen to use leiningen and do not know enough about boot to create proper instructions for boot.

You can use it via the REPL

BOOT_CLOJURE_VERSION=1.9.0-alpha15 boot -d thheller/shadow-devtools:1.0.20170512-13 -s src repl

(require '[shadow.cljs.devtools.api :as cljs])
(cljs/once :build-id)

https://github.com/thheller/shadow-devtools/wiki/REPL

Some ideas in boot don't play too well with the design I have in mind for shadow-devtools but you can use it just fine.

jiyinyiyong

unread,
May 12, 2017, 9:47:01 PM5/12/17
to clojur...@googlegroups.com
Cool.... Hope one day it's in Lumo too XD

Thomas Heller

unread,
May 13, 2017, 6:43:57 AM5/13/17
to ClojureScript
On Saturday, May 13, 2017 at 3:47:01 AM UTC+2, Jiyin Yiyong wrote:
> Cool.... Hope one day it's in Lumo too XD

Not by me but the features could certainly be ported.

I spent quite a bit of time yesterday fighting through webpack sources trying to come up with an efficient way of doing things.

The easy solution would be to make everything one-way which means JS can require CLJS but CLJS cannot require "local" JS, only modules from npm. So (js/require "react") would work but (js/require "./foo") would not.

So in JS you would could say var x = require("webpack-cljs/cljs.core"). The way things are handled in webpack/npm means you must have a module-name which would be webpack-cljs or something along that line. But a package cannot depend on the local sources.

Having sources to actually be side-by-side doesn't mirror too well to JS since you usually don't have namespaces there.

Imagine
src/index.js
src/foo.js
src-cljs/foo/bar.cljs

In index.js you could say require("./webpack-cljs/foo.bar") and in the cljs file I could imagine
(webpack/require "./foo") where it would always be relative context root (ie. src). The compiler would actually just generated a src/webpack-cljs/foo.bar.js. Same way it would for the module version.

The problem with that is that people may start writing npm packages in CLJS where each package would contain its own version of cljs.core. That would be really really bad.

Ideally I want
src/index.js
src/foo.js
src/foo/bar.cljs

but have not figured out how to do that yet. webpack has a ton of mutable state all over the place so trying to figure out what is going on is not that easy.

I'll probably write the simple version today and see how things work out.

Thomas Heller

unread,
May 13, 2017, 1:08:26 PM5/13/17
to ClojureScript

> I'll probably write the simple version today and see how things work out.

So the simple version sort of works.

http://thheller.com/webpack-cljs-preview/index.html
http://thheller.com/webpack-cljs-preview/bundle.js
This was generated by "webpack -d" and

index.js:
---
var foo = require("webpack-cljs/dummy.foo");
console.log(foo.bar());
---

dummy/foo.cljs:
---
(ns dummy.foo)

(js/console.log "dummy.foo")

(defn bar []
"bar")
---

Nothing special but works well enough, still haven't figured out most of the webpack things though. Currently they shadow-devtools just runs independently and generates files into ./node_modules/webpack-cljs/dummy.foo.js to make the require "pretty" (I really do not like relative paths).

Will polish things a bit and maybe provide a public repo tomorrow. Still convinced that this is a very bad idea though. ;)

Thomas Heller

unread,
May 14, 2017, 8:23:09 AM5/14/17
to ClojureScript
I started a new topic [1] for the implementation.

You can find an example here:
https://github.com/thheller/npm-module-example

I'd be very interested in feedback from people that actually use webpack already.

[1] https://groups.google.com/forum/?fromgroups#!topic/clojurescript/AGXku7Ous0Y

Brian Hurlow

unread,
Jun 12, 2018, 10:48:12 PM6/12/18
to ClojureScript
wow seeing this thread got me really excited – I'm working on a js project that has some cljs embedded into it and going with the grain of the js ecosystem would really help my team use it.

js areas where I could see a webpack loader working:

- Hot Module Replacement (like figwheel)
- importing cljs react components into js with react like semantics e.g. import Dropdowm from 'src/cljs/ui.cljs'
- access to some of the core lib (would use in place of immutable.js)

The project I'm working on exposes an npm script to compile the cljs source in full and I bootstrap all the namespaces in a single require on the node.js. Even as crude as this is there's a lot of promise. I'll start looking at webpack possibilities

Jiyin Yiyong

unread,
Jun 13, 2018, 10:44:53 PM6/13/18
to ClojureScript
Make sure you have read this http://shadow-cljs.org/

daniel sutton

unread,
Jun 13, 2018, 11:00:35 PM6/13/18
to ClojureScript
haven't followed this thread but david nolen just wrote a new article about webpack and cljs here:

jiyinyiyong

unread,
Jun 15, 2018, 2:47:03 AM6/15/18
to clojur...@googlegroups.com
I read that post on ClojureVerse. With shadow-cljs it already very trivial to use React by writing `["react" :as React]`. Importing standalone JavaScript files is easy too with https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html . Using Webpack is too much steps.

On Thu, Jun 14, 2018 at 11:00 AM daniel sutton <daniels...@gmail.com> wrote:
haven't followed this thread but david nolen just wrote a new article about webpack and cljs here:

--

David Nolen

unread,
Jun 15, 2018, 10:23:01 AM6/15/18
to clojur...@googlegroups.com
I think the guide demonstrates quite clearly it's very trivial with ClojureScript now. People can easily add templates (via cljs-new), or create a la carte libraries that automate the small number of steps.

David

On Fri, Jun 15, 2018 at 2:46 AM, jiyinyiyong <jiyin...@gmail.com> wrote:
I read that post on ClojureVerse. With shadow-cljs it already very trivial to use React by writing `["react" :as React]`. Importing standalone JavaScript files is easy too with https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html . Using Webpack is too much steps.

On Thu, Jun 14, 2018 at 11:00 AM daniel sutton <daniels...@gmail.com> wrote:
haven't followed this thread but david nolen just wrote a new article about webpack and cljs here:

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/HNuYCfPRtQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescript+unsubscribe@googlegroups.com.

To post to this group, send email to clojur...@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

--
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 clojurescript+unsubscribe@googlegroups.com.

jiyinyiyong

unread,
Jun 15, 2018, 11:44:40 AM6/15/18
to clojur...@googlegroups.com
It's good news for ClojureScript.

But shadow-cljs is always my favorite. Say I want to use "dayjs" in my project. I do `npm install dayjs`, and add one line of dependency https://github.com/Cirru/calcit-editor/blob/e00823b18ed9ad9e77249002124fd01a145f3510/src/app/comp/messages.cljs#L11 then I got the function `Dayjs` I wanted. Two steps only.

On Fri, Jun 15, 2018 at 10:23 PM David Nolen <dnolen...@gmail.com> wrote:
I think the guide demonstrates quite clearly it's very trivial with ClojureScript now. People can easily add templates (via cljs-new), or create a la carte libraries that automate the small number of steps.

David

On Fri, Jun 15, 2018 at 2:46 AM, jiyinyiyong <jiyin...@gmail.com> wrote:
I read that post on ClojureVerse. With shadow-cljs it already very trivial to use React by writing `["react" :as React]`. Importing standalone JavaScript files is easy too with https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html . Using Webpack is too much steps.

On Thu, Jun 14, 2018 at 11:00 AM daniel sutton <daniels...@gmail.com> wrote:
haven't followed this thread but david nolen just wrote a new article about webpack and cljs here:

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/HNuYCfPRtQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.

To post to this group, send email to clojur...@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

--
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 clojurescrip...@googlegroups.com.

To post to this group, send email to clojur...@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/HNuYCfPRtQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages