This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-22
Channels
- # announcements (88)
- # autochrome-github (2)
- # babashka (26)
- # beginners (5)
- # biff (2)
- # cider (73)
- # clj-kondo (4)
- # cljsrn (6)
- # clojure (54)
- # clojure-art (3)
- # clojure-europe (73)
- # clojure-germany (5)
- # clojure-new-zealand (1)
- # clojure-nl (13)
- # clojure-norway (16)
- # clojure-uk (8)
- # clojurescript (73)
- # conjure (1)
- # core-async (10)
- # cursive (17)
- # datahike (51)
- # datalevin (21)
- # datomic (4)
- # emacs (2)
- # events (3)
- # fulcro (35)
- # honeysql (6)
- # introduce-yourself (1)
- # jackdaw (3)
- # jobs (1)
- # leiningen (4)
- # lsp (3)
- # malli (17)
- # off-topic (60)
- # other-languages (5)
- # pathom (17)
- # pedestal (3)
- # polylith (19)
- # portal (2)
- # practicalli (1)
- # rdf (14)
- # reitit (3)
- # releases (1)
- # reveal (9)
- # sci (1)
- # shadow-cljs (26)
- # spacemacs (17)
- # sql (4)
- # testing (10)
- # tools-build (6)
- # tools-deps (16)
- # vim (9)
Hey all, does the :target :bundle
is only meant to be used for bundling code to be running in a browser? I'm trying to get a node script working with this, but after all is bundled node complains with:
out/index.bundle.js:848
window.CLOSURE_UNCOMPILED_DEFINES = { "cljs.core._STAR_global_STAR_": "global", "cljs.core._STAR_target_STAR_": "bundle" };
^
ReferenceError: window is not defined
at Object.<anonymous> (out/index.bundle.js:848:1)
My build.edn
is this:
{:main hello.core
:output-to "out/index.js"
:output-dir "out"
:target :bundle
:closure-defines {cljs.core/*global* "global"}
:browser-repl false}
And I bundle and run it all with:
clj -M:cljs -co build.edn -v -c && npx esbuild ./out/index.js --bundle --platform=node --outfile=./out/index.bundle.js && node out/index.bundle.js
Is it possible to tell the compiler to use, say, global
instead of window
in the output?
Is it possible to tell the compiler to use, say, global
instead of window
in the output?
@micheal.ocathain Hey! I think the #babashka channel is more suited for this maybe :)
Of course it is - apologies all! Amazing tool @U04V15CAJ !
I want to use an esm-only npm package in Electron and was going to bundle the resulting clojurescript with webpack/esbuild so that the esm imports
are transpiled to cjs requires
.
If I use the :target :nodejs
then the resulting JS uses a require
to load an ESM dependency and that fails with Error [ERR_REQUIRE_ESM]: require() of ES Module blah-blah from main.js not supported. Instead change the require of blah-blah in main.js to a dynamic import() which is available in all CommonJS modules.
This is all happening in the Electron main process, not the renderer, thus there's no window
and the :bundle
target doesn't quite fit the purpose as it stands now.
I've got a sample repo with a minimal example here: https://github.com/eploko/cljsbuild-for-esm-node-lab
Hello! I have a simple question regarding a specific case of extern’ing. I am able to use clojurescript to generate a single file which works great. Here is the simplistic cljs:
(ns part1-add.core)
(defn ^:export add [a b] (+ a b))
I then compile the project using advanced optimizations (with --target node) in order to generate a single file (main.js). After parsing/squinting, I can see that my exported function is now called ‘z’. I then paste the entire main.js at the bottom of a JS file which invokes my ‘z’ function and outputs it the result to my console - all great.
My question is the following: is it possible to use some form of ‘extern’ declaration to protect the function add
from being optimized so that it can be called as is? My two key needs are 1) a single file (working) and 2) protect one name..Sorry for my verbosity, and thanks for any comment.That export
should already be enough to prevent it from being renamed.
I don't use Node myself so no clue here, but perhaps --target node
somehow messes the export up.
note that ^:export
doesn't really prevent renaming - it just ensures that the desired exported name is also available
@U050B88UR and @U2FRKM4TW Thanks for your replies…I suppose I could try creating an externs file but don’t know what to point it at.
I am still new at cljs…alternatively, is there a way to do simple (no renaming) optimization into a single file?
So do you really not have part1_add.core.add
available from JS, at run time? Don't inspect JS code for that - try it in run time.
@U050B88UR, oh hang on. I may simply have missed it…Will try again.
awrigh’! This worked:
clj -M -m cljs.main --target node --optimizations simple --output-to out/main.js -c part1-add.core
Thanks for your help!
Ideally I would like to optimize away most of the stuff, but still be able to call part1_add.core.add as is - with simple optimization my file is large but still workable. Maybe I will find a way to extern the protected name away… Thanks again..
Did you confirm that by looking at the resulting main.js
or did you actually check in run time?
I looked at main.js in both ’simple and ’advanced: it is easy to find in ’simple, but doesn’t exist in ’advanced. Instead, ‘advanced emits:
...function Ke(a,b){return a+b}var Le=["part1_add","core","add"],Me=aa;Le[0]in Me||"undefined"==typeof Me.execScript ...
$ node
Welcome to Node.js v16.13.1.
Type ".help" for more information.
> require('./out/main.js')
{}
> app.a_b.add(1, 2)
3
I send my js file to an external grader which runs it - that’s how I know which works/doesn’t
Yes, it works indeed! Cool. I will now try invoking the require inside the stub…hang on 🙂
The problem is, I need to invoke part1_add.core.add from the same file which generates the module. I will try adding to it
require('part1_add.core');
> same file which generates the module
Not sure I follow. Is your JS file actually calling clj -M -m cljs.main yada-yada
? Or what do you mean?
I copy-paste the contents of ‘optimized’ main.js into a js file. The js file has a pre-existing function which invokes part1_add.core.add function which should be made available by requiring’ ‘part1_add.core’?
Your usage scenario seems to be drastically different from the usual ones for some reason.
I am submitting my file to an external grader on a remote site. The grader chews it up….Yes, indeed drastically different 🙂
So you need to have a single JS file. Why not generate that file with CLJS in whole? You can require Node modules from CLJS code just fine.
OK, but I thought that’s what I was doing basically? main.js is it. I only paste its contents into the stub code that uses it.
var readline = require('readline');
process.stdin.setEncoding('utf8');
var rl = readline.createInterface({
input: process.stdin,
terminal: false
});
rl.on('line', readLine);
require( 'part1_add.core');
function readLine (line) {
if (line !== "\n") {
var a = parseInt(line.toString().split(' ')[0], 10);
var b = parseInt(line.toString().split(' ')[1], 10);
// console.log(z(a, b));
console.log( part1_add.core.add(a,b));
process.exit();
}
}
//....main.js pasted here
The above works fine in ’simpleIt would be nice if an in-memory only module was possible - it doesn’t sound unreasonable
It should work as is because a JS file is first read and then evaluated - the order of definitions shouldn't matter.
What error do you get when you use part1_add.core.add
?
Error: Cannot find module 'part1_add.core'
Require stack:
- /tmp/tmp153tl8fn/part1_advanced-optimized.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:982:15)
at Function.Module._load (internal/modules/cjs/loader.js:864:27)
at Module.require (internal/modules/cjs/loader.js:1044:19)
at require (internal/modules/cjs/helpers.j
...
Unbelievable but true! I worked - I don’t know what changed with my earlier tries without the require ??
Will have to learn the intricacies of CLJS compilation, externs and node.js - cool stuff 🙂
Thanks again @U2FRKM4TW!