This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-01
Channels
- # announcements (2)
- # architecture (8)
- # babashka (21)
- # beginners (75)
- # calva (3)
- # clj-kondo (6)
- # cljdoc (6)
- # cljs-dev (10)
- # clojars (4)
- # clojure (94)
- # clojure-europe (12)
- # clojure-nl (4)
- # clojure-norway (3)
- # clojure-spec (6)
- # clojure-uk (4)
- # clojurescript (51)
- # community-development (13)
- # core-async (3)
- # css (1)
- # cursive (8)
- # datomic (7)
- # girouette (3)
- # graphql (3)
- # improve-getting-started (4)
- # integrant (2)
- # interop (5)
- # jobs (12)
- # kaocha (1)
- # lsp (24)
- # malli (4)
- # membrane (13)
- # nextjournal (9)
- # off-topic (6)
- # re-frame (9)
- # reitit (2)
- # remote-jobs (1)
- # reveal (4)
- # ring (4)
- # scittle (3)
- # shadow-cljs (4)
- # spacemacs (1)
- # testing (2)
- # vrac (1)
Does anybody use tailwindcss and what is your development tooling story? A coworker keeps mentioning the lsp server for it decided I just look at the docs for now
clojure-lsp is absolutely amazing
For some reason I have to add ^js
in front of PAtom to make this not give a warning. Weird.
12 | (extend-type nyancad.hipflask/PAtom reagent.ratom/IReactiveAtom)
-------^------------------------------------------------------------------------
Cannot infer target type in expression (. (. nyancad.hipflask/PAtom -prototype) -reagent$ratom$IReactiveAtom$)
I have required both
Weird, I can't reproduce it in a toy project, even if I place the protocol and the type in their own namespaces. The only way I see that error is if I remove the requires.
Make sure you're using the latest CLJS release. If you can still reproduce the error there, I'd say it's worth coming up with a minimal reproducible example and posting it on http://ask.clojure.org.
I'm assuming this is one of those corner cases there really isn't a good answer for but... I'm having a hell of a time trying to get advanced compilation to play nicely with pouchdb dynamic plugins. https://pouchdb.com/custom.html Does anyone have any thoughts on how they would tackle this? Example of breaking code:
(.. local-pouch
(createIndex
(clj->js {:index {:fields ["type"]}})))
createIndex not found
etc
Currently using figwheel with the :npm
feature.
:npm {:bundles {"dist/index.bundle.js" "src/js/index.js"}}
Not sure if I should be looking at making a foreign-libs file or using type annotations or some other magic.(.. pouchdb
(plugin (.. js/window -auth -default))
(plugin (.. js/window -perms))
(plugin (.. js/window -pfind -default)))
where
pouchdb
comes from
(ns some.ns
(:require pouchdb))
where
pouchdb
comes from
# ./src/js/index.js
var PouchDB = require('pouchdb').default;
window.pouchdb = PouchDB;
which gets compiled to dist/index.bundle.js
via yarn webpack
to be used by figwheel's :npm
feature
:npm {:bundles {"dist/index.bundle.js" "src/js/index.js"}}
(which makes it available in the :require
of the ns
form)I tried doing the plugins in the index.js
file, but that didn't work either 😞 that also didn't work with :simple
optimizations, but I may have made a mistake if that was supposed to work.
Why do you use js/window
and not regular :require
?
Is Webpack really relevant here?
Unclear to which src
and dist
you're referring to.
good questions. On js/window
... it worked and I didn't question it. There was a lot of trial and error.
The purpose of webpack is to make the javascript dependencies available to the clojurescript code. The output of the webpack compilation is fed to the input of the google closure compiler.
dist/index.bundle.js
is the output of the webpack compilation. src/index.js
is the source file used by webpack to generate dist/index.bundle.js
. This is because I'm including the pouchdb
dependencies via npm
. Although now that you mention it, maybe I could avoid all this by just using script tags
> The purpose of webpack is to make the javascript dependencies available to the clojurescript code. The output of the webpack compilation is fed to the input of the google closure compiler. Why?.. Is it a limitation of Figwheel? With shadow-cljs, I can just use NPM dependencies without any hassle in 95% of the cases.
You don't have an index.js
file? :thinking_face: interesting
If I were in your place, I would definitely try to see if shadow-cljs works in this case. You wouldn't need script tags, js/window
, webpack,.. - none of that stuff. You'd just use an NPM dependency almost as if it were a CLJ dependency.
so let me get this right... you just npm install whatever
and then do (:require whatever)
in your ns
form and that's all there is to it for you?
As an example, I use mousetrap
in one of my projects.
So I did npm i -E mousetrap
at some point, I have (:require ["mousetrap" :as mousetrap])
in one of the files, and then I use that mousetrap
via regular JS interop.
> and that's all there is to it for you?
Most of the time, yes. Although I put double quotes in the :require
for NPM dependencies. I don't think it's strictly needed for any library names/paths that are valid CLJS symbols, but I still prefer to do it to make it clear that the dependency comes from NPM.
interesting :thinking_face:. Well the main issue for me is runtime dynamic advanced compilation. If shadow can handle that, then I suppose it's time to switch tooling
I think that nowadays figwheel-main has a similar way of working with NPM dependencies, but I haven't used it.
I've tried it but I can't figure it out
so I'm still using the old way
> runtime dynamic advanced compilation I understand the words "advanced compilation". What does "runtime compilation" mean in your case? And what is "dynamic compilation"?
It's the "plugin" thing.
So there's a pouchdb
object, right? And the "plugin" just adds methods onto the pouchdb
object.
If it's not, you can stop the needed methods from being munged by optimization via externs.
mousetrap
also has plugins - and they work just fine, I just require every plugin I use and IIRC register them with Mousetrap, no issues whatsoever.
Perhaps, but I think the issue is that when the advanced compiler sees
(.. pouchdb-instance -some-plugin some-plugin-function)
it may not be obvious what it is and isn't supposed to rename
> mousetrap
also has plugins - and they work just fine, I just require every plugin I use and IIRC register them with Mousetrap, no issues whatsoever.
This might be what I'm looking for. Is that a shadow specific thing or is that the clojurescript notion of externs?
I wasn't sure if shadow/figwheel and the externs played nicely or if they were incompatible
If something comes from a :require
of an NPM dependency, every method call and property access on it, including chained ones, will be used in automatic externs inference. Meaning, such things won't be renamed.
If the compiler doesn't know about whether something is a JS, a CLJS, or a goog object, and you're using JS interop on it, it will warn you that the type is unknown - most of the time, it means that you're trying to use interop on a JS object where the fields/methods must not be renamed. In that case, just put ^js
in front of the binding.
There has been a recent discussion about it, but ^js
doesn't survive built-in CLJS functions. So e.g. in (first #js [#js {}])
CLJS will not know that its result is a JS value. Personally, I prefer to simply put ^js
on all bindings for JS objects that don't come from goog or CLJS.
> I wasn't sure if shadow/figwheel and the externs played nicely or if they were incompatible Both shadow-cljs and figwheel[-main] are just wrappers+modifications of the CLJS compiler. They do work with and rely on externs.
But note that manually writing externs files is pretty much an outdated phenomenon by now, at least in my understanding. I haven't had to do it for a few years now. Literally all you need is to put ^js
in the right places.
A rather old but still relevant article from the author of shadow-cljs: https://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html
> But note that manually writing externs files is pretty much an outdated phenomenon by now, at least in my understanding. I haven't had to do it for a few years now. Literally all you need is to put ^js
in the right places.
yeah exactly, struggling to remember how to do it. Was assuming I must be doing something else wrong.
Would you try externs first or switching to shadow first?
Oh, apart from automatic externs inference from all things that come from NPM, you also already have externs inference for all things that come from js/*
. So location
will never be renamed in (.-location js/window)
or js/window.location
.
> Would you try externs first or switching to shadow first? Definitely switching, because the tool has been a fantastic asset in my projects, and its author is one of the most responsive people on this server.
fair enough! Ok I'll give it a shot and report back 🙂 thanks so much for your insight!
Okay I ended up getting it to work with the externs route, just b/c it was quicker to try than converting tooling. I guess I'm stuck on FW awhile longer 😅
for posterity,
# src/js/pouchdb-externs.js
var pouchdb = function() {};
pouchdb.plugin = function() {};
pouchdb.plugin().auth = {};
var auth = {};
auth.default = {};
var perms = {};
var pfind = {};
pfind.default = {};
pouchdb.logIn = function() {};
pouchdb.changes = function() {};
pouchdb.changes().on = function() {};
pouchdb.createIndex = function() {};
pouchdb.get = function() {};
pouchdb.put = function() {};
= function() {};
pouchdb.remove = function() {};
pouchdb.allDocs = function() {};
pouchdb.find = function() {};
pouchdb.sync = function() {};
pouchdb.sync().on = function() {};
pouchdb.destroy = function() {};
with
:externs ["src/js/pouchdb-externs.js"]
did the trickHey all: with the latest version of cljs 1.11.4
, I am seeing this warning at the REPL:
------ WARNING #6 - :infer-warning ---------------------------------------------
File: /Users/sritchie/code/clj/sicmutils/src/sicmutils/numbers.cljc:372:31
--------------------------------------------------------------------------------
369 | ;;
370 | (letfn [(long-expt [base pow]
371 | (loop [^Long n pow
372 | ^Long y (.getOne Long)
-------------------------------------^------------------------------------------
Cannot infer target type in expression (. Long getOne)
shadow-cljs does not give me that warning anymore when I replace that code with (Long/getOne)
, but then at the cider repl I DO see:
sicmutils.value> (goog.math.Long/getOne)
WARNING: Use of undeclared Var goog.math.Long/getOne at line 1 <cljs repl>
#object[Long 1]
the cider repl in emacs is using the same cljs version. Has anyone seen this before?added a fix for this in shadow-cljs https://github.com/thheller/shadow-cljs/commit/69b43270c8a9fcdec899822f243a9e26824f1d5c
Thanks @U05224H0W! I’ll look out for a release and finish up my cljs upgrade down the road.