Skip to content

Instantly share code, notes, and snippets.

@swannodette
Last active April 11, 2020 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swannodette/919ef8fb51e7ee91b5f3ab643c4b3e55 to your computer and use it in GitHub Desktop.
Save swannodette/919ef8fb51e7ee91b5f3ab643c4b3e55 to your computer and use it in GitHub Desktop.
Transitive Foreign Dependencies 2

Add a new :target option, :bundle. When this target is set :nodejs is true and :nodejs-rt is false. We want to take advantage of the fact that the :nodejs target emits Node.js require for libs found in node_modules. :nodejs-rt false clarifies that we are not actually going to target the Node.js runtime.

The :bundle target always generates an index.js file, it need only be created once.

The contents of index.js looks like the following:

import "output-dir/output-to.js";

When using higher levels of optimization output-dir/output-to.js is just the final concatenated file. When using :none optimizations the contents of output-dir/output-to.js looks much as it does today:

import {npmDeps} from "./deps-rt.js";

var CLOSURE_UNCOMPILED_DEFINES = {};
var CLOSURE_NO_DEPS = true;
if(typeof goog == "undefined") document.write('<script src="out/goog/base.js"></script>');
document.write('<script src="out/goog/deps.js"></script>');
document.write('<script src="out/cljs_deps.js"></script>');
document.write('<script>if (typeof goog == "undefined") console.warn("ClojureScript could not load :main, did you forget to specify :asset-path?");</script>');
document.write('<script>goog.require("clojure.browser.repl.preload");</script>');
document.write('<script>goog.require("foo.core");</script>');

window.require = function(lib) {
   return npmDeps[lib];
}

One difference is ./deps-rt.js. This file is generated by analyzing the dependency graph from the :main namespace to determine which libs come from node_modules:

module.exports = {
  npmDeps: { react: require("react") ... }
}

This allows REPL session (require ...) of libraries from node_modules.

Hopefully it should be clear now that any tool that handles Node.js require can build ClojureScript - webpack, metro, etc.

ClojureScript Libs that Depend on Node Modules

Nothing to do. deps.cljs support for :npm-deps makes this work. Before building just run:

clj -m cljs.main --install-deps

Advanced Compilation

:bundle target + :advanced optimizations will automatically imply :infer-externs true.

Full Advanced Compilation

While this won't magically work, the door is always open for people to try advanced compilation. Simply drop :target :bundle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment