Fork me on GitHub
#shadow-cljs
<
2021-09-17
>
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?

thheller15:09:36

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.

thheller15:09:00

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

thheller15:09:43

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]]

thheller15:09:03

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

thheller15:09:16

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

borkdude15:09:46

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

👍 2
thheller15:09:49

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.

thheller15:09:22

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

thheller15:09:35

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?

thheller15:09:46

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.

thheller15:09:11

that should solve itself if you require icons directly

thheller15:09:17

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: https://github.com/ant-design/babel-plugin-import#example

thheller15:09:44

no, thats nonsense

Michaël Salihi15:09:44

Don't know if it's doable

thheller15:09:13

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.

thheller15:09:32

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

🙌 2
thheller15:09:16

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 ?

thheller06:09:26

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"

thheller06:09:12

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

thheller06:09:02

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

thheller06:09:28

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?

thheller06:09:26

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

thheller14:09:51

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

thheller14:09:06

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

thheller14:09:02

or even analyzing why things are that big

thheller14:09:19

eg. shadow-cljs build report and webpack bundle analyzer

thheller15:09:16

so I went with require

lispers-anonymous15:09:27

Hello, if I have a namespace that looks like this

(ns foo.bar)
(def dog "doug")
and another namespace
(ns foo.bar.dog)
;; other stuff
I end up with a namespace clash
Namespace foo.bar.dog clashes with var foo.bar/dog
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 foo.bar 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.

thheller15:09:46

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

💯 2
lispers-anonymous15:09:38

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

thheller15:09:23

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

thheller15:09:30

so unlikely this is going to change anytime soon

lispers-anonymous16:09:08

Everything has it's quirks, cljs is no different

winsome16:09:17

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.

thheller16:09:44

no. use a separate build for node stuff

winsome16:09:39

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

borkdude18:09:14

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

thheller20:09:44

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