Fork me on GitHub
Michaël Salihi15:09:33

Hello! Just to be sure before doing some tests, I would to know if I go in the right direction.

Michaël Salihi15:09:21

This is about :js-provider :external js-options.

Michaël Salihi15:09:52

I can use the external-index file to do some tree shaking with for eg. webpack, right?


or rather I don't know what webpack tree shaking looks like these days. I doubt it though.

Michaël Salihi15:09:24

OK, so this is maybe not the solution for one project.


what kind of shaking are you looking for? generally the best result you'll get is by using modular libs that allow you to access certain stuff directly


whether you use those with just shadow-cljs or together with webpack will then be a minor difference

Michaël Salihi15:09:50

After checking the file, I understand that bundler cannot works on DCE because the require are "global" in compare in my CLJS code.

ALL["@ant-design/icons"] = require("@ant-design/icons");
 ALL["@ant-design/pro-layout"] = require("@ant-design/pro-layout");
 ALL["react-dom"] = require("react-dom");

Michaël Salihi15:09:19

["antd/es/button" :default Button]
            ["@ant-design/pro-layout" :default ProLayout :refer [PageContainer]]
            ["@ant-design/icons" :refer [AppstoreOutlined FileTextOutlined LikeOutlined SettingOutlined AlipayCircleFilled]]


good example. instead of requiring the @ant-design/icons directly which itself imports thousands of other things you are unlikely to use


just require what you actually use directly, eg. (:require ["@ant-design/icons/FileTextOutlined" :as FileTextOutlined])


(clj-kondo should be able to inform you what you're actually using or not)

👍 2

that only loads what you actually need and eliminates the other thousands

Michaël Salihi15:09:47

Yes thank you. This is my first try but I go in direction to :js-provider :external because Ant design lib relies heavily on importing less css file for all his components

Michaël Salihi15:09:25

node_modules/antd/es/tag/style/index.js:import '../../style/index.less';
node_modules/antd/es/tag/style/index.js:import './index.less';
node_modules/antd/es/time-picker/style/index.js:import '../../style/index.less';
node_modules/antd/es/time-picker/style/index.js:import './index.less'; // style dependencies

Michaël Salihi15:09:05

So it breaks Shadow-cljs build.

Michaël Salihi15:09:42

I knwo I can avoid this error excluding assets with ignore-asset-requires true

Michaël Salihi15:09:28

but after that the CSS styles are missing for these components.

Michaël Salihi15:09:15

So I try to find the best way to glue all of that.


not a clue. antd has always been rather terrible from a package perspective. requiring custom webpack plugins and so on to work


so using webpack seems like a good strategy

Michaël Salihi15:09:21

Perfect, make sense. Thank you for the confirmation.

Michaël Salihi15:09:32

So if I want to use Shadow-CLJS + Webpack, :js-provider :external is the only solution, right?


not the only but the recommended

Michaël Salihi15:09:18

For my project right now it works well, except my external-index file size is 1.8M 😕

Michaël Salihi15:09:51

This is the reason for my first question.


that should solve itself if you require icons directly


instead of relying on wonky tree shaking

Michaël Salihi15:09:00

OK, I try that right now, thanks.

Michaël Salihi15:09:10

Maybe this approach would be interesting in the CLJS world:


no, thats nonsense

Michaël Salihi15:09:44

Don't know if it's doable


why complicate your build setup 10x when you can just require the icon you want and write 3 lines more code?

Michaël Salihi15:09:10

For my part, it suits me very well to target imports. It was more of a suggestion / idea in order to avoid mistakes when working as a team.

Michaël Salihi15:09:47

In fact, it remains only good practices to be communicated at the team. 👍

Michaël Salihi15:09:41

Thank you for your precious help.


antd is one of those libs that really really wants you to use webpack so definitely go with that

🙌 2

I had some code to make the external-index generate actual import { Thing } from "thing" instead of require but that had all sorts of other issues

Michaël Salihi20:09:45

Interesting. What kind of issues ? Specific for some config or globally very unstable ?


commonjs <-> ESM interop issues mostly. say you have reagent using (:require ["react" :as react]) that would map to import * as react from "react" but given that react is shipped as commonjs only it must be imported via import react from "react"


but figuring this out at build time is hard when not actually building JS (since webpack will do it)


so either it would requiring some sort of config you'd need to provide manually or some magic I don't like


can't have reagent change the import since that would then break others not using ESM

Michaël Salihi06:09:25

OK I understand. Being able to configure that would be great! Thank you for all these details.

Michaël Salihi06:09:24

Your code to make external-index generate import is on testing branch?


no, just commented out

Michaël Salihi06:09:47

Perfect, I'll check.

Michaël Salihi12:09:39

Hi, I come back to our exchange because I continued my tests and I am a little desperate and I will seek confirmation before abandoning the plan to use Ant design pro with ClojureScript.

Michaël Salihi12:09:47

Even targeting components, icons directly, my external-index bundled by webpack weight more than 1,1Mb.

Michaël Salihi12:09:35

["@ant-design/pro-layout" :default ProLayout :refer [PageContainer]]
["@ant-design/icons/AppstoreOutlined" :default AppstoreOutlined]
["@ant-design/icons/FileTextOutlined" :default FileTextOutlined]
["@ant-design/icons/LikeOutlined" :default LikeOutlined]
["@ant-design/icons/SettingOutlined" :default SettingOutlined]
["@ant-design/icons/AlipayCircleFilled" :default AlipayCircleFilled]

Michaël Salihi12:09:35

As the external-index file uses commonjs require then I can't do anything at webpack level, like eg tree shaking like with es import, right?

Michaël Salihi12:09:20

@thheller This is not a personal project but a professional request and your opinion will be very valuable in order to know if I can confirm that there is a solution or if I must give up. Thanks


I would recommend writing a file like the external index by hand just using import


and then actually running webpack and see what size you get vs require


or even analyzing why things are that big


eg. shadow-cljs build report and webpack bundle analyzer


so I went with require


Hello, if I have a namespace that looks like this

(def dog "doug")
and another namespace
;; other stuff
I end up with a namespace clash
Namespace clashes with var
That makes sense, I understand why that happens. Is there a way to work around this without renaming namespaces or vars? I was thinking there would be some configuration for my :target :browser build where I could declare something the effect of "namespace should be compiled to the name 'something_completely_different' on the output javascript object" It's not that big of a deal, I can always rename, but it would be nice to be able to keep the ones I have right now.


@dannyfreeman that would need to be solved in the cljs compiler directly. not something shadow-cljs can change.

💯 2

Got it, thanks for the quick response. We'll just re-think our names, no big deal.


yeah its unfortunate. I'd like to change it myself but that may break a lot of code out there


so unlikely this is going to change anytime soon


Everything has it's quirks, cljs is no different


Does the :browser target support the :exports option? I'm trying to build a browser package and a node package from the same source, but I'd like to exclude some node-specific functions from the browser build.


no. use a separate build for node stuff


I am setting it up as a separate build already, just they both use the same source. I guess I can move the node-specific stuff to another namespace and include it as a submodule


@thheller hmm would the :esm build target be helpful there as well, since it basically generates the same source for browser and node?


dont know enough to say. I would go with two builds given there is node-specific stuff