0

I followed this guide on using webpack + clojurescript, https://clojurescript.org/guides/webpack. It works perfectly when compiled with :none or :whitespace, but when I compile with :advanced one of the objects hooked to the window ends up being imported as an undefined object, causing the app to crash.

I tried a couple of things, like defining and externs.js with the window object, but I find it hard to dig deeper on this.

This is my compiler arguments:

{:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"]
             :compiler
             {:output-to     "target/cljsbuild/public/js/app.js"
              :output-dir    "target/cljsbuild/public/js"
              :source-map    "target/cljsbuild/public/js/app.js.map"
              :optimizations :advanced
              :infer-externs true
              :pretty-print  false
              :npm-deps      false
              :foreign-libs [{:file "dist/index_bundle.js"
                              :provides ["react" "react-dom" "react-select" "react-table"]
                              :global-exports {react React
                                               react-dom ReactDOM
                                               react-select Select
                                               react-table ReactTable}}]}}

This is my index.js, entrypoint for webpack

// Here we define what we need.
// Webpack is gonna use this and produce a bundle.
// cljs will read this bundle and provide the namespaces for us.
import React from 'react';
import ReactDOM from 'react-dom';
import Select from 'react-select';
import ReactTable from 'react-table'

window.React = React;
window.ReactDOM = ReactDOM;
window.Select = Select;
window.ReactTable = ReactTable

The webpack config is as simple as

module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'index_bundle.js'
    }
}

The error I get is because on a file like this:

(ns foo
  (:require
   [react-table :as ReactTable]
   [reagent.core :as r]
   [clojure.string :as str]))
[...]
(r/adapt-react-class ReactTable)

ReactTable is bound to nil. I can confirm that on the js console window.ReactTable is also nil.

Simply changing :advanced to :whitespace on the compiler opts, and leaving everything else as-is, solves the issue. And in the js console, window.ReactTable is no longer nil.

Any ideas? :)

----- EDIT (adding workaround info) --------

I found that a possible work-around for this use case is to "split" the foreign-libs like this:

              :foreign-libs [{:file "dist/main.js"
                              :provides ["react" "react-dom" "react-select"]
                              :global-exports {react React
                                               react-dom ReactDOM
                                               react-select Select}}
                             {:file "dist/react_table.js"
                              :requires ["react" "react-dom"]
                              :provides ["react-table"]
                              :global-exports {react-table ReactTable}}]}}

adapting the webpack config to and entrypoints create two separate bundles, one with only ReactTable and the other with all others. I don't consider this to be a solution because the real problem was not identified. But doing so solves the issue.

Vitorqb
  • 130
  • 2
  • 6

1 Answers1

0

Definitely you're getting issues with advanced optimizations messing up with the names of the libraries you are using, but depending on your use case, you may not need to use Webpack at all (not sure if this is an option for you).

It seems the libraries you're using are popular enough to be covered under the CLJSJS project, so that if you find the versions that you need, you can add the libraries as regular dependencies in your project.clj file and it should just work. The packages from CLJSJS include the dependency information and the externs files conveniently packaged.

Finally, you may have stumbled in a bug in an older version of ClojureScript. Check if you are using the most recent version, or maybe one that is a bit older.

Denis Fuenzalida
  • 3,271
  • 1
  • 17
  • 22
  • Hi @Denis, I wanted to use webpack to have more control on the versions of the third party libraries, and also because I wanted to see it working (hehe). Furthermore, I wanted flexibility to use less known npm packages someday. Regarding the version, I'm using "1.10.520". I have also tried some previous versions thinking that it could have been a regression, but I had no luck. – Vitorqb Jul 09 '19 at 16:20
  • I edited the post adding a possible workaround I found, but still I have no idea why the original setup does not work. – Vitorqb Jul 09 '19 at 16:25