     (when-not public-dir
       (throw (ex-info "missing :public-dir" {})))
 
-    (doseq [{:keys [default output prepend source-map-name name js-name] :as mod} modules]
-      (let [target
-            (io/file public-dir js-name)
-
-            out
-            (if default
-              (str unoptimizable output)
-              output)
-
-            out
-            (if (:web-worker mod)
-              (let [deps (:depends-on mod)]
-                (str (str/join "\n" (for [other modules
-                                          :when (contains? deps (:name other))]
-                                      (str "importScripts('" (:js-name other) "');")))
-                     "\n\n"
-                     out))
-              out)
-
-            out
-            (str prepend (foreign-js-source-for-mod state mod) out)]
-
-        (io/make-parents target)
-        (spit target out)
-
-        (log state {:type :flush-module
-                    :name name
-                    :js-name js-name
-                    :js-size (count out)})
-
-        (when source-map-name
-          (spit target (str "\n//# sourceMappingURL=" cljs-runtime-path "/" (file-basename source-map-name) "\n")
-            :append true))))
-
-    (flush-manifest public-dir modules)
-
-    (when (:source-map state)
-      (flush-source-maps state))
-
-    ;; with-logged-time expects that we return the compiler-state
-    state))
+    (let [{modules :optimized
+           :as state}
+          (if (not= :inline bundle-foreign)
+            (-> state
+                (create-foreign-bundles)
+                (flush-foreign-bundles))
+            state)]
+
+      (doseq [{:keys [default output prepend source-map-name name js-name] :as mod} modules]
+        (let [target
+              (io/file public-dir js-name)
+
+              out
+              (if default
+                (str unoptimizable output)
+                output)
+
+              out
+              (if (:web-worker mod)
+                (let [deps (:depends-on mod)]
+                  (str (str/join "\n" (for [other modules
+                                            :when (contains? deps (:name other))]
+                                        (str "importScripts('" (:js-name other) "');")))
+                       "\n\n"
+                       out))
+                out)
+
+              out
+              (if (= :inline bundle-foreign)
+                (str prepend (foreign-js-source-for-mod state mod) out)
+                (str prepend "\n" out))]
+
+          (io/make-parents target)
+          (spit target out)
+
+          (log state {:type :flush-module
+                      :name name
+                      :js-name js-name
+                      :js-size (count out)})
+
+          (when source-map-name
+            (spit target (str "\n//# sourceMappingURL=" cljs-runtime-path "/" (file-basename source-map-name) "\n")
+              :append true))))
+
+      (flush-manifest public-dir modules)
+
+      (when (:source-map state)
+        (flush-source-maps state))
+
+      ;; with-logged-time expects that we return the compiler-state
+      state)))
 
 (defn load-externs [{:keys [externs build-modules] :as state}]
   (let [default-externs


;; FIXME: manifest should be custom step
(defn flush-manifest [public-dir modules]
  (spit (io/file public-dir "manifest.json")
    (json/write-str (map #(select-keys % [:name :js-name :entries :depends-on :default :sources]) modules))))

(defn foreign-js-source-for-mod [state {:keys [sources] :as mod}]
  (->> sources

           (com.google.javascript.jscomp.deps JsFileParser)
           (java.util.logging Level)
           [java.util.concurrent Executors Future]
           (com.google.javascript.jscomp ReplaceCLJSConstants CompilerOptions CommandLineRunner)
           (java.security MessageDigest)
           (javax.xml.bind DatatypeConverter))
  (:require [clojure.data.json :as json]
            [clojure.java.io :as io]
            [clojure.set :as set]
