This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-09
Channels
- # adventofcode (1)
- # aleph (2)
- # beginners (28)
- # boot (26)
- # boot-dev (8)
- # cider (10)
- # clara (10)
- # cljs-dev (130)
- # cljs-experience (1)
- # cljsrn (12)
- # clojure (118)
- # clojure-austin (40)
- # clojure-boston (1)
- # clojure-chicago (1)
- # clojure-dusseldorf (1)
- # clojure-estonia (11)
- # clojure-france (1)
- # clojure-greece (3)
- # clojure-italy (19)
- # clojure-nl (1)
- # clojure-russia (1)
- # clojure-spec (19)
- # clojure-uk (34)
- # clojurescript (62)
- # core-logic (7)
- # cursive (11)
- # datomic (35)
- # emacs (15)
- # fulcro (264)
- # jobs (4)
- # leiningen (5)
- # midje (4)
- # off-topic (74)
- # onyx (27)
- # planck (14)
- # protorepl (4)
- # re-frame (37)
- # reagent (62)
- # rum (2)
- # shadow-cljs (171)
- # slack-help (5)
- # spacemacs (6)
- # specter (9)
@hlolli so I thought about it a bit yesterday. the purpose of the :target
abstraction is to capture as much as possible about the “final” product so it requires almost no post processing. In your case there should be a :target :chrome-extension
where the config itself contains everything required to generate all the support files the chrome extensions want.
:browser
sort of fits but not exactly since you’ll never serve things from a webserver and such
I only did a very basic chrome extension once to test but forgot just about everything
maybe it could even just look at the manifest.json
itself and figure out what if needs to do from there
you could try writing it yourself but the docs are non-existent for that part so its going to be painful 😉
The only required file so far I've seen is https://developer.chrome.com/apps/manifest manifest.json, the :background :scripts would be needed to be automatically filled, but that can also be html file, doubt cljs users will prefer a html file, think we can ignore that option. There are some local storage file schemas :storage :storage-schema, not sure how to best include that into cljs config, but they are just json files. I can also be forgetting something, this is the first time I'm doing extension myself. But starting with the manifest I believe half the battle will be won.
I'm gonna give shadow-cljs/src/main/shadow/build/targets/chrome_extension.clj
a try. I will ask here if I bump into problems.
@thheller I wonder if it would make sense to add :escape-unicode false
here https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/browser.clj#L308 was useing icelandic chars for manifest metadata and they all got \u00xxx
ok, I'll create a PR tonight, another question, is it possible to access :module-hash-names
from the state
passed into this function. https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/browser.clj#L277
(I'm not useing this namespace or file directly, but creating code deriving from it).
:module-hash-names
works by modifying :output-name
for the module, so others don’t need to be concerned with it
:output-name
defaults to :module-id
+`.js`, :module-hash-names
turns it into <module-id>.<hash>.js
ok so I misunderstood you yesterday 🙂
the data I'm looking for is basically cljs-runtime/*.js
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/browser.clj#L406
or rather in the flush-sources
call, see https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/output.clj#L178-L209
or
[[:shadow.build.classpath/resource "goog/base.js"] [:shadow.build.classpath/resource "goog/debug/error.js"] [:shadow.build.classpath/resource "goog/dom/nodetype.js"] [:shadow.build.classpath/resource "goog/string/string.js"] [:shadow.build.classpath/resource "goog/asserts/asserts.js"]
...elided
slashes to dots = real filename.https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/output.clj#L188-L192
completly unrelated to chrome-extensions, there's nothing here in your setup preventing the possibility to provide cljs-compiler as gulp plugin spitting out unoptimized cljs code. Just an idea for later project.
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/karma.clj#L70-L92
this creates one singular big file since karma had issues loading files the “closure-way” when I tried it
yes, one big file is sadly what many modern js tooling relies on. Especially painful adding some cljs code mixed with typescript when one needs to wait a minute for clojurescript to spit 1 file in development.
when that is running we pretty much have better performance than typescript or others would have
would be pretty easy to add on demand compilation of singular files if you don’t need a full “build”
nice, I'm all for wirting js in one language. But there are many projects mixing babel, typescript and coffeescript in one. If cljs could be one of those with minimal tooling, it would be nice. In this case, start the server once and hide that from the user.
but yeah most JS tooling is built assuming that you launch a new process for everything
made a teaser vid a while ago for create-react-app
https://www.youtube.com/watch?v=BLDX5Twt2zk
well for the first 3 years I basically never talked about shadow-cljs
at all so that is probably my fault 😉
been trying to blog more but I prefer writing code so I never get anywhere blog-wise 😉
figwheel
is pretty deeply embedded in pretty much every template/tutorial these days
yes, shadow-cljs is maybe a no-brainer to use for mixing cljs in js project, node platforms, browser plugins and probably Im forgetting a lot. Moveing divs with hot-reload, it wouldn't bother me useing relieable, compiler. After few years for figwheel, 99% of the errors I find like touching any part of my body blindfolded. Doesn't give me as much as it did in the past.
well these days shadow-cljs pretty much does everything that figwheel does, just differently 😉
my last question, you see shadow-cljs and tools.deps (no lein or boot) a good combination, or would tools.deps be redundant?
you can use tools.deps
today but lose all the optimizations the shadow-cljs
script does
yes would be nice, to be able to provide library that can be used by lein+boot and potentially lumo and planck. If there's a standardize deps format.
it is optimized for clojure after all and some things in CLJS are just different especially when integrating with npm
and such
might be better to start with a cljs-deps.edn
than trying to integrate into deps.edn
FWIW I’m really looking forward to being able to use git deps: https://clojure.org/news/2018/01/05/git-deps
standardized deps format is definitely good but tools.deps
assumes a classpath
which is a JVM thing
Well then you have package.json as well, seems to be unavoidable to have two project files. Or integrade tools.deps into package.json. That's a different headace.
tools.deps gives me in lumo a nice way to resolve classpath for deps quickly and easily, nothing more so far.
yeah, I have written my own thing for that https://github.com/shadow-cljs/shadow-cljs-deps
you can run shadow-cljs node-repl
if you need a quick REPL aware of your classpath, might not need lumo
😉
well you can always use :target :node-script
to build the “scripts” and run them directly. lumo
just lets you skip the build step which is nice.
well you can always publish :node-script
to npm
(with a package.json
to declare deps)
@thheller I pinged you several weeks ago regarding transitive NPM dependencies not working correctly when trying to import a JAR dependency built with shadow-cljs. You mentioned that you were aware of the issue but didn’t have the bandwidth to address it. Is this still on your radar? Happy to help in any way to get this implemented.
We did some work to port our front-end projects over to shadow-cljs, and while the NPM modules within that project worked great, we found that when we consumed those projects from another shadow-built project, the NPM modules coming from the dependent project couldn’t be resolved.
Haha it’s a bit hard to describe - let me know if that doesn’t make sense and I’ll try to provide more of a visual illustration of the problem.
I’m not sure of any either - it’s possible that it works since we last tried it. We can try to set up a test case and put it up on a public repo if that helps.
Cool. I’ll put something together with the latest shadow-cljs version and will share with you once it is complete. Thanks!
Hm, I was just trying to use a stage-3 ES feature, but I don't think shadow-cljs is happy about it
no, stuff from the project itself runs through the closure compiler to get :advanced
DCE
function assoc(obj, key, value) { return {...obj}//...obj, [key]: value} } export { assoc }
as far as closure compiler is concerned, this is relevant: https://github.com/google/closure-compiler/issues/2303
anyway, my question, I guess, is whether it's possible to transpile things (slightly) with babel before feeding into closure compiler
I was thinking doing the bare minimum in babel of transpiling to es2016 standard (even keeping the es2015 modules, etc), and then feeding that into closure compiler, so you still get DCE, etc
looks like the commit made it in, unfortunately we can’t yet use the latest release of the closure compiler since CLJS breaks with it 😞
well, other than that the interop with non-npm JS files seems to work a treat, thanks for that
and if you are ever bored, having an option to feed non-npm JS files through babel (instead of closure compiler?) would be a nice addition to shadow-cljs (but certainly not a must-have)
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/resolve.clj#L94
how/why does that work with node_modules then, when they aren't closure-compiler compatible?
I need to add a pre-process anyways to get support for typescript, coffescript, JSX, etc
is it possible to rename the default output filename main.js
, adding :output
and :output-to
in build options didnt made a difference.
not that I actually want to rename it, just want to get that name programatically, in the end.
@thheller Sorry for the confusion before - just updated everything and it seems to work perfectly - thanks for all of your help!
So I believe I've succeeded with this, this can be polished (spec the manifest stuff) but everything put into :chrome-extension will be exported into manifest.json, only thing is to add: :target clj.chrome-extension/process
(clj is just whatever source directory is on cp)
https://gist.github.com/hlolli/265b9183566a4c5829d7ee355e3d0998
runtime-bundled? (or (nil? optimizations) (= :none optimizations) (= :simple optimizations))
is it safe to pass many scripts into “background”? though that was supposed to be one
ns clj.chrome-extension
(:refer-clojure :exclude (flush require))
(:require [shadow.build :as build]
[shadow.build.api :as build-api]
[ :as io]
[clojure.set :as set]
[clojure.data.json :as json]
[shadow.build.data :as data]
[shadow.build.output :as output]
[shadow.build.targets.shared :as shared]
[shadow.build.classpath :as cp]
[shadow.build.modules :as modules]
[shadow.cljs.repl :as repl]
[shadow.build.targets.browser :as browser]))
(defn flush-crx-manifest [{:keys [build-options chrome-extension stage mode] :as state}
{:keys [chrome-extension optimizations] :as config}]
(let [runtime-bundled? (or (nil? optimizations) (= :none optimizations) (= :simple optimizations))
chrome-extension (:chrome-extension config)
cljs-runtime-path (:cljs-runtime-path build-options)
js-main (-> state ::modules/modules :main :output-name)
js-filelist (mapv #(->> (data/get-source-by-id state %)
:output-name
(io/file cljs-runtime-path)
.getPath)
(:build-sources state))
data (merge {:manifest_version (or (:manifest_version chrome-extension) 2)
:name (or (:name chrome-extension) "unnamed-shadow-cljs-extension")
:version (or (:version chrome-extension) "1.0.0")
:background {:scripts (if runtime-bundled?
(into [js-main] js-filelist)
[js-main])}}
chrome-extension)
manifest-name "manifest.json"
manifest-file (data/output-file state manifest-name)
manifest (with-out-str
(json/pprint data :escape-slash false :escape-unicode false))]
(spit manifest-file manifest))
state)
(defn process
[{::build/keys [stage mode config] :as state}]
(-> state
(browser/process state)
(cond->
(= stage :flush)
(flush-crx-manifest config))))
FWIW I’m really looking forward to being able to use git deps: https://clojure.org/news/2018/01/05/git-deps