Fork me on GitHub
#shadow-cljs
<
2019-10-11
>
jaime13:10:52

How do you handle cache busting & copying the index.html to the target directory where main.js file is generated? Eg. Reference to main.js without cache busting

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script src="main.js"></script> <--- no cache busting
</body>
</html>
In webpack there is a plugin where you can add hash main.[hash].js and define a path where your index.html template is located, and it will copy it to the target directory

jaime20:10:43

@thheller thank you for link. I got the hash working. However it is still not obvious to me how to put the hashes filename in index.html on every build? Would you mind sharing an example?

thheller20:10:56

you read the manifest.edn, you read your input index.html. you str/replace the data or however fancy you want to get

thheller20:10:07

something like that

thheller20:10:29

you can use anything for this really

thheller20:10:36

doesn't have to be clojure

thheller20:10:15

I can create a full example tomorrow if this isn't clear enough

jaime21:10:01

Cool. I think it is enough. I will try to make it work. Then maybe I will send a PR to update docs.

jaime21:10:11

Thanks a lot :)

jaime21:10:23

btw, I have an idea. It may not be the scope of shadow-cljs. But I’m interested on your opinion. What if we tell shadow-cljs where the index.html (lets call it template) is located so that it can copy it in the output-dir? Then inside the index.html template, we can define text that can be replaced by an actual value later. For instance any text that starts with $<NAME>.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>$__DOC_TITLE</title>
</head>
<body>
  $__SCRIPTS <-- will include all scripts
</body>
</html>
The naming conventation is just an example. Also, on how to get the value needs further thought.

jaime21:10:24

If you think it’s something that can be added as an improvement. I’m interested on doing it

jaime21:10:13

build-hooks are awesome! Thanks a lot, I have something to learn more about 😄

isak14:10:49

@jaime.sangcap A custom script that spits out the html, reading "manifest.edn" for prod builds

tslocke16:10:36

I did shadow-cljs release app for the first time (in a while at least). Now when I go back to watch I'm getting loads of errors where it seems the JS objects for the CLJS namespaces don't exist. e.g. Cannot set property 'global' of undefined, where global is the first defn in that namespace. I've tried clearing everything in .shadow-cljs, and in the js/out dir, but it's still broken. Any ideas?

thheller16:10:06

bad browser cache?

tslocke16:10:17

I don't think so. I've been right clicking on the reload button (Chrome) and doing "Clear cache and reload"

thheller16:10:22

and you are sure you are loading your actual output files? not some older files from some older directory or so?

tslocke16:10:03

Pretty sure, but I'll double check that

tslocke16:10:22

Turned source maps off to get the actual path of the JS file, confirmed the timestamp is from 2 minutes ago. Same for main.js

tslocke16:10:17

ARGH nvm. It's a name clash with something I'm assigning to js/window :face_palm:

picard-facepalm 4
ghaskins17:10:07

hi all…im running up against something that I don’t understand: basically trying to compile with :react-native target, and am including some .js and getting “ReferenceError: Can’t find variable: shadow$provide”

ghaskins17:10:11

any help appreciated

ghaskins17:10:29

(the .js in this case is generated by the protoc compiler and imported in cljs with a (:require)…this pattern works in :browser but seems to blow up in :react-native

ghaskins17:10:05

I can see that shadow-cljs did in fact incorporate the generated .js, but it places a reference to shadow$provide that doesnt seem to be fulfilled

thheller17:10:41

so you have a (:require ["./some.js" :as x])? with some.js being some generated code?

ghaskins17:10:18

or something close to that, anyway..i think the .js is omitted

ghaskins17:10:42

let me look

thheller17:10:47

yeah thats fine

ghaskins17:10:02

(I basically borrowed from a poc I did successfully with :browser

thheller17:10:31

hmm that should work but it might have a scoping issue

thheller17:10:53

can you adjust the generated code to use import/export? so ES6 modules?

ghaskins17:10:32

let me check how I ran the protoc compiler

thheller17:10:49

or maybe the closure JS style?

thheller17:10:23

this should just work. let me see if I can reproduce

ghaskins17:10:34

forgive me, i am not a js expert so im fumbling around a bit

ghaskins17:10:54

I generated the code with the “commonjs” import_style

ghaskins17:10:11

which I believe was necessary to get it to work in the :browser target

ghaskins17:10:33

if I understand what you are saying above, I should try the closure style

ghaskins17:10:43

but im not sure about the ES6 modules option

thheller17:10:01

the closure JS option is likely the best yes

ghaskins17:10:06

ok, ill try that

thheller17:10:14

but then it becomes a regular namespace, so you import it by whatever name it generated

thheller17:10:33

goog.provide('proto.example.high_score.Ponycopter'); (lol)

thheller17:10:48

would be (:require [proto.example.high_score.Ponycopter :as lol])

ghaskins17:10:05

ok, let me give that a whirl and report back, ty!!

thheller17:10:11

ES6 is also ok

thheller17:10:16

commonjs should work too though

ghaskins17:10:41

im sure I am doing something wrong somewhere along the way

thheller17:10:09

it is totally possible this just has an issue for react-native

thheller17:10:30

you can try if it works in a release build. I'd suspect that it does.

ghaskins17:10:18

fwiw: this tool generates a project with the structure I am using

ghaskins17:10:50

(though in my current iteration, I have abandoned lein-shadow and dropped back to raw shadow-cljs.edn

ghaskins17:10:01

(thrashing around trying to solve the problem)

ghaskins17:10:25

but all permuations seem to have the same fundamental problem of the missing shadow$provides call

ghaskins17:10:35

anyway, i will play with the generated code type as you suggested

thheller17:10:54

how does anyone get anything done with react-native ... the last time I ran this project it worked fine

thheller17:10:04

react-native run-android
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 855 file(s) to forward-jetify. Using 12 workers...
info JS server already running.
info Installing the app...
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :app:transformClassesWithDexBuilderForDebug FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See 
20 actionable tasks: 2 executed, 18 up-to-date

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> Could not read path 'C:\Users\thheller\code\tmp\reagent-react-native\react-native\android\app\build\intermediates\transforms\dexBuilder\debug\288\androidx\arch\core'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at 

BUILD FAILED in 31s

error Failed to install the app. Make sure you have the Android development environment set up: . Run CLI with --verbose flag for more details.
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> Could not read path 'C:\Users\thheller\code\tmp\reagent-react-native\react-native\android\app\build\intermediates\transforms\dexBuilder\debug\288\androidx\arch\core'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at 

BUILD FAILED in 31s

    at checkExecSyncError (child_process.js:621:11)
    at execFileSync (child_process.js:639:15)
    at runOnAllDevices (C:\Users\thheller\code\tmp\reagent-react-native\react-native\node_modules\@react-native-community\cli-platform-android\build\commands\runAndroid\runOnAllDevices.js:74:39)
    at buildAndRun (C:\Users\thheller\code\tmp\reagent-react-native\react-native\node_modules\@react-native-community\cli-platform-android\build\commands\runAndroid\index.js:158:41)
    at C:\Users\thheller\code\tmp\reagent-react-native\react-native\node_modules\@react-native-community\cli-platform-android\build\commands\runAndroid\index.js:125:12
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
    at async Command.handleAction (C:\Users\thheller\AppData\Roaming\npm\node_modules\react-native\node_modules\@react-native-community\cli\build\cliEntry.js:160:7)

thheller17:10:06

hmm nevermind ... just ran react-native run-android a second time and that worked

thheller17:10:28

@ghaskins I have reproduced the error though, looking into that

martinklepsch17:10:39

Is it possible to set goog.DEBUG to true for advanced builds?

thheller17:10:41

ES6 module works though, although I only tested with export const foo = "foo";. no clue what the protoc generated files look like

thheller17:10:58

:closure-defines {goog.DEBUG true}?

martinklepsch17:10:45

Yeah, that’s what I’ve been doing but my marker code isn’t showing up

martinklepsch17:10:29

let me play around a bit more

martinklepsch17:10:36

just wanted to ensure it’s meant to work 🙂

thheller17:10:06

that is definitely meant to work yes

thheller17:10:53

@ghaskins found the problem

thheller17:10:53

@ghaskins should be fixed in 2.8.64

👍 4
ghaskins18:10:23

thanks for the quick turnaround. Ill confirm the fix now

ghaskins18:10:57

def seems fixed, thanks!

ghaskins18:10:07

ran into another problem, but it might be on my end

ghaskins20:10:37

its not really clear what the problem is, but there seems to be an issue with .js transitives now

ghaskins20:10:08

I tried to build a stripped down use case, and I succeeded though the error is slightly different

ghaskins20:10:58

in essence, it seems there is some kind of problem referencing something like google-protobuf/google/protobuf/any_pb.js, even though that is included in the “google-protobuf” package

ghaskins20:10:26

(again, i am open to the notion that its “operator error” ;)

ghaskins20:10:07

(i cant say that my tool generated a competent android config..i run iOS here)

ghaskins20:10:26

appreciate any insights

ghaskins20:10:29

L15 to load

thheller20:10:23

you might have more luck if you copy the generated JS files to some dir

thheller20:10:34

assuming you are using :output-dir "app"

thheller20:10:04

copy the generated files to <project>/proto next to <proto>/app

thheller20:10:25

then include the protobuf stuff via (def x (js/require "../proto/whatever.js"))

thheller20:10:03

but what would be absolutely ideal is just using closurejs generated output

thheller20:10:26

but I'm not exactly sure how that output looks

thheller20:10:14

how do I get protoc? I want to try this myself now

thheller20:10:02

this has to be the worst bundled thing I have ever seen

thheller20:10:08

what even is this project structure 😛

thheller20:10:16

(the protobuf stuff that is)

thheller21:10:11

I give up. this has to be the absolute worst managed package I have ever seen. seriously. I have seen some crazy bad packages but this takes the absolute top rank

thheller21:10:24

since I hate giving up ... I got it working

thheller21:10:27

geez this is bad 😛

ghaskins01:10:28

wow, you are awesome

ghaskins01:10:30

ill check it out

ghaskins02:10:18

what I cant figure out is this all worked perfectly when I target :browser, but I think I see what you are seeing

ghaskins02:10:07

if I use commonjs output, :react-native output seems to be missing my generated source….if I use closure output, it cant find the google provided exports

thheller09:10:03

even for the browser it makes much more sense to use the closurejs style

thheller09:10:34

it'll be fully :advanced compatible and result in a way way smaller build

ghaskins13:10:30

Yeah, I think I ran into a problem which led me to try commonjs…but I no longer recall what the issue was

ghaskins13:10:18

in any case, I did check my browser apps and it looks like they were using shadow-cljs 2.8.55 (vs 2.6.64 in react-native) so I was wondering if there was a regression

ghaskins13:10:57

but I updated the browser app to 2.8.64 and it still works fine (even with the basic commonjs flow) so it does seem like there is some kind of difference

thheller13:10:24

don't get hung up too much on whether this works in the browser or not

ghaskins13:10:32

it seems like the google-protobuf npm package doesnt get included in the same way, but I dont understand why

thheller13:10:39

using the closure JS style is 100% better regardless of the platform you are on

ghaskins13:10:22

ill try to digest your working example and report back

ghaskins13:10:32

thanks for the time (and shadow-cljs is awesome, btw, so thanks for that too)

thheller13:10:53

the commonjs code is basically just a wrapper around the closure JS code

thheller13:10:23

if there is something the closureJS stuff can't do that the commonjs variant would be able to let me know

thheller13:10:58

I'm confident that the closureJS variant will be able to do anything, it just might not come pre-packaged in some way

thheller13:10:17

(google doesn't seem to care much about packaging this stuff cleanly)

thheller17:10:38

@martinklepsch just tested and it definitely works. only thing that might cause trouble if you are mixing strings and symbols. :closure-defines should only be symbol keys but in case you have strings also the merge rules might delete one value if there is a conflict

simonkatz17:10:07

Can I tell shadow-cljs or NPM what to do when there are dependency conflicts? (Something like :exclusions in Leiningen, perhaps?) I’m getting this:

NPM version conflict for "react" in deps.cljs (will use A)
A: "16.9.0" from jar:file:/Users/xxxx/.m2/repository/reagent/reagent/0.9.0-rc1/reagent-0.9.0-rc1.jar!/deps.cljs
B: "16.8.6" from jar:file:/Users/xxxx/.m2/repository/re-com/re-com/2.6.0/re-com-2.6.0.jar!/deps.cljs

thheller17:10:31

hmm you control which version is installed

thheller17:10:47

its just warning you that deps.cljs specified different versions

simonkatz17:10:29

Ah, right. Thanks!

simonkatz17:10:50

Hmmm. So, yes, you’re right, I am specifying the version of react (in package,json). But I if I had conflicts in the transitive dependencies of my :dependencies, might I have to specify (as a top-level dependency) which version I want? And live with the warnings?

thheller18:10:52

npm doesn't really have a mechanism for this and deps.cljs is kinda dirty anyways

thheller18:10:31

I may just remove the warning

thheller18:10:52

I don't know how to solve this cleanly

simonkatz18:10:39

OK; I see. Thanks. (I’m new to npm so still getting to grips with the basics.)

thheller18:10:26

it likely is fine. CLJS dependencies declaring JS dependencies directly is kind of a new thing so there are some kinks that need to be worked out

lilactown18:10:01

I’ve run shadow-cljs check app and I am seeing a bunch of places that have the following warning: ShadowJS expressions are not callable This could totally be because I’m doing some weird shit with npm/cljsjs transition. what exactly does this warning pertain to, though?

lilactown18:10:26

here’s an example line it’s calling out:

(-> (js/$ ".floating-scrollbar") (.floatingScroll "destroy"))

thheller18:10:49

don't pay too much attention to the check output. the closure typechecking isn't really meant to be used the way I'm using it

thheller18:10:28

too much overall noise anyways