Fork me on GitHub
#shadow-cljs
<
2019-03-29
>
orestis09:03:08

I need to (conditionally?) import a polyfill to support a JS library (react-boostrap, sigh, doesn’t work on IE11). Needs Object.assign. Is there a recommended way to do this with shadow-cljs/clojurescript? Should I load it conditionally directly in the HTML?

orestis09:03:32

There’s more to this — I actually need to make sure to load some polyfills before any 3rd-party code is loaded. I’m using for now a http://polyfill.io script element, but I would prefer if the contents of the returned polyfill to be prepended to my final bundled file, but without passing through google closure optimizations at all.

thheller10:03:09

@orestis you can set :compiler-options {:language-out :ecmascript3} and it should add the closure polyfill for that

orestis10:03:44

I’m writing an issue about it since it seems to be more complicated than that (due to Closure polyfill and React weird interactions)

thheller10:03:04

alternatively you can set :compiler-options {:closure-injected-libs #{"util/assign"}}

orestis10:03:16

Is it language-out or :output-feature-set

thheller10:03:32

for this part :language-out is probably better

thheller10:03:17

note that this only really applies to release builds so if you are testing with development builds that may not work

thheller10:03:36

but since its fairly common for JS libs to unconditionally ship their own polyfills you may end up with multiple versions and the same polyfill

thheller10:03:39

which may not work

orestis10:03:13

Yeah that’s extremely annoying. I see for example that react-bootstrap depends on babel runtime…

orestis10:03:54

I need it for development as well — our designers need to be able to test in IE11 while in dev mode to fix CSS and other things.

thheller10:03:38

I would honestly recommend keeping the polyfills as a separate script element which you can make conditional for only IE

thheller10:03:13

@orestis in the github issue please provide at least some source reference on how I would reproduce the problem

thheller10:03:21

which npm module (+ version) to include and so on

orestis10:03:31

Oh sorry. Doing this right now.

thheller10:03:47

also the actual error you run into

thheller10:03:02

I know it sucks extracting that for IE ...

orestis10:03:24

Do you prefer a sample project? Or just library versions etc?

thheller10:03:57

sample project would be great

orestis10:03:01

Let me see how minimal it can get.

thheller10:03:45

make sure you have the correct versions installed

thheller10:03:51

there might be some version conflicts

thheller10:03:14

please check which version is in node_modules/@babel/runtime/package.json

thheller10:03:29

should be "^7.3.4"

orestis10:03:02

Obviously has to be tested with IE11

orestis10:03:08

Thanks so much for taking some time to look into this. It’s not a high priority for me, so please don’t feel any pressure at all.

thheller10:03:31

:compiler-options
        {:rewrite-polyfills true
         :language-out :ecmascript3}

thheller10:03:39

this works in release mode

orestis10:03:44

Thanks! Checking with the actual app to see.

orestis10:03:39

Can I nest compiler options under “release”?

thheller10:03:55

sure but that doesn't matter as those only apply to release anyways

thheller10:03:59

will have no effect in dev

orestis10:03:41

Doesn’t seem to fix the problem for the actual app… making sure I actually have the correct things.

orestis11:03:39

No luck 😞

orestis11:03:11

There might be other things in my actual application that trigger this in other ways.

thheller11:03:15

I made this demo ns

thheller11:03:17

(ns 
  (:require
    ["react-bootstrap" :as bs]
    ))

(defn init []
  (js/console.log js/Object js/Object.assign))

thheller11:03:42

it loads fine in IE11 when the :compiler-options set

thheller11:03:50

fails with the .assign error if not

thheller11:03:58

;; shadow-cljs configuration
{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

 :dependencies
 []

 :dev-http
 {9005 "public"}

 :builds
 {:app {:target :browser
        :modules {:main {:init-fn }}
        :compiler-options
        {:rewrite-polyfills true
         :language-out :ecmascript3}
        }}}

thheller11:03:47

again only in shadow-cljs release app

orestis11:03:49

Ah, but that doesn’t exercise the code inside react-bootstrap, it looks?

thheller11:03:52

not for compile or watch

thheller11:03:07

yes, but the error you posted happens during load

thheller11:03:27

if you get past the load stuff then its probably a different error

orestis11:03:49

That’s true, in release mode the error happens during load. In dev mode it’s shadow catching the error and reporting it.

thheller11:03:13

just forget about development mode for now

thheller11:03:36

only interested in release as that is currently the only thing that can potentially work

thheller11:03:44

dev is busted and won't work regardless

orestis11:03:27

I’ll see about my minimal repro in release mode and report back after lunch. Thanks for looking into this!

thheller11:03:13

@orestis it works if you set :js-options {:rewrite-polyfills true} + the :compiler-options

thheller11:03:17

even seems to work in dev mode

thheller11:03:53

:js-options
         {:rewrite-polyfills true}
         
         :compiler-options
         {:language-out :ecmascript3
          :rewrite-polyfills true
          :infer-externs :auto}

thheller11:03:30

it worked in my test since I used Object.assign in the CLJS sources which caused the polyfills to be added

thheller11:03:54

but the JS sources are processed in a separate pass so it must be enabled there manually

orestis12:03:51

Can confirm that the js-options fixes the Object.assign issue. The broken Symbol.for polyfill though seems to linger on, probably need to wait for a Google Closure compiler bump for this? Seems the issue is fixed upstream (or at least closed).

thheller12:03:09

what issue is that?

thheller12:03:03

yes I saw that. how to do I reproduce that though?

thheller12:03:22

I'm in the process of bumping the closure compiler anyways so it may just work

thheller12:03:28

still need a way to reproduce that to test

orestis12:03:15

My minimal repro example shows that

orestis12:03:41

Correct rendering

orestis12:03:20

(building… 😄 )

orestis12:03:59

IE11 with broken Symbol polyfill rendering

orestis12:03:40

For some reason, it’s 60107 wherever a react fragment appears. I haven’t been able to get any meaningful google hits for this so potentially you’ll get another number.

thheller12:03:44

didn't notice that 😛

orestis12:03:11

Do I have to go to ES3 or should just rewrite polyfills do it?

thheller12:03:41

the symbol issue also doesn't work with the latest closure compiler version

thheller12:03:43

hmm but it looks like thats not a react issue

thheller12:03:03

if I do this the fragment renders correctly (just removed hx)

thheller12:03:05

(defn ^:dev/after-load render []
  (react-dom/render
    (r/createElement r/Fragment nil
      (r/createElement "div" nil "content 1")
      (r/createElement "div" nil "content 2"))
   (js/document.getElementById "main")))

orestis12:03:57

Could be on subsequent renders?

orestis12:03:24

Probably not, hx should only render once.

orestis12:03:57

In any case, I’ll shrug this. Could be nice to have a self-contained bundle with all the necessary polyfills, but probably best to just load them in HTML.

orestis12:03:06

Sorry for taking up your time

lilactown14:03:09

Might be something wrong with hx. Feel free to file an issue