mljs / libsvm

LIBSVM for the browser and nodejs :fire:
https://mljs.github.io/libsvm/
BSD 3-Clause "New" or "Revised" License
82 stars 14 forks source link

Browser execution question #11

Closed nopbyte closed 6 years ago

nopbyte commented 6 years ago

Hi, As far as I can understand, the demos folder would be a starting point to create a Web application using React, etc.

I just wanted to ask if there are some instructions on how to compile a bundle for the browser alone. I just need a distribution bundle that I can include in a simple html site and instantiate the library.

This would make life easier for people to use it, if they are not so familiar with all the technologies used in your demo. I for one, am not an expert on React, so it would take me some time to understand your demo before I can put this on an existing website.

Thanks a lot,

nopbyte commented 6 years ago

Hi,

I have been trying to get a simple page to load one of the SVMs in the browser and I have had some issues since yesterday. First, I got emscripten (portable zip file) and installed it locally. After this, npm run build generates a dist folder.

I have tried to get this running in three different ways. My first attempt was to get the demo pages running.

Then, I tried to compile the demo pages by doing npm run demo-build and I got the following output:

ERROR in ./demos/app.js
Module not found: Error: Can't resolve '../dist/wasm/libsvm.asm.js' in '/home/dp/git/phd/others/libsvm/demos'
``
To get rid of the first error, I changed the second line in demos/app.js to be 
import '../dist/asm/libsvm.js';

But, I still get the following errors when attempting to build the demo pages:

``
> libsvm-js@0.1.3 demo-build /home/dp/git/phd/others/libsvm
> rimraf demo-dist && BABEL_ENV=production webpack -p --config webpack.production.js && cp demos/index.html demo-dist

Hash: c1631b500e41df004e61
Version: webpack 3.10.0
Time: 37407ms
                                 Asset       Size  Chunks                    Chunk Names
  b06871f281fee6b241d60582ae9369b9.ttf     166 kB          [emitted]         
                      0.hash.worker.js     267 kB          [emitted]  [big]  
                      2.hash.worker.js     571 kB          [emitted]  [big]  
                        hash.worker.js  985 bytes          [emitted]         
                           libsvm.wasm    88.2 kB          [emitted]         
  674f50d287a8c48dc19ba404d20fe713.eot     166 kB          [emitted]         
af7ae505a9eed503f8b8e6982036873e.woff2    77.2 kB          [emitted]         
 fee66e712a8a08eef5805a46892932ad.woff      98 kB          [emitted]         
                      1.hash.worker.js     406 kB          [emitted]  [big]  
  912ec66d7572ff821749319396470bde.svg     444 kB          [emitted]  [big]  
                         manifest.json  246 bytes          [emitted]         
                           0.bundle.js     639 kB       0  [emitted]  [big]  
                           1.bundle.js    81.1 kB       1  [emitted]         
                           2.bundle.js    6.53 kB       2  [emitted]         
                             bundle.js     591 kB       3  [emitted]  [big]  main
                                 sw.js    19.8 kB          [emitted]         
   [9] (webpack)/buildin/global.js 509 bytes {3} [built]
 [131] ./dist/asm/libsvm.js 444 kB {3} [built]
 [140] multi ./demos/app.js 28 bytes {3} [built]
 [141] ./demos/app.js 1.86 kB {3} [built]
 [162] ./dist/wasm/libsvm.wasm 57 bytes {3} [built]
 [279] ./wasm.js 175 bytes {1} [built]
 [280] ./asm.js 131 bytes {2} [built]
 [281] ./demos/bootstrap.js 1.01 kB {0} [built]
 [318] ./src/loadSVM.js 14.7 kB {1} {2} [built]
 [388] ./dist/wasm/libsvm.js 137 kB {1} [built]
 [394] ./demos/containers/App.js 4.05 kB {0} [built]
 [593] ./demos/containers/Benchmarks.js 3.9 kB {0} [built]
 [599] ./demos/store.js 452 bytes {0} [built]
 [610] ./demos/style.css 1 kB {0} [built]
 [623] ./demos/manifest.json 59 bytes {0} [built]
    + 622 hidden modules
Child serviceworker-plugin:
     1 asset
      [37] ./demos/sw.js 4.46 kB {0} [built]
      [38] (webpack)/buildin/global.js 509 bytes {0} [built]
        + 70 hidden modules
Child worker:
               Asset       Size  Chunks                    Chunk Names
    0.hash.worker.js     267 kB       0  [emitted]  [big]  
    1.hash.worker.js     406 kB       1  [emitted]  [big]  
    2.hash.worker.js     571 kB       2  [emitted]  [big]  
      hash.worker.js  985 bytes       3  [emitted]         main
       [0] ./node_modules/babel-loader/lib!./benchmark/worker.js 453 bytes {3} [built]
       [1] ./benchmark/browser.js 2.3 kB {0} [built]
       [2] ./benchmark ^\.\/.*\-benchmark\.js$ 276 bytes {0} [built]
      [13] (webpack)/buildin/global.js 509 bytes {0} [built]
     [128] ./src/loadSVM.js 14.7 kB {1} {2} [built]
     [139] ./src/util.js 2.01 kB {1} {2} [built]
     [218] (webpack)/buildin/module.js 517 bytes {1} {2} [built]
     [302] ./asm.js 131 bytes {2} [built]
     [306] ./dist/asm/libsvm.js 444 kB {2} [built]
     [307] ./wasm.js 175 bytes {1} [built]
     [308] ./dist/wasm/libsvm.js 137 kB {1} [built]
     [309] ./benchmark/iris/cross-validation-benchmark.js 940 bytes {0} [optional] [built]
     [311] ./benchmark/iris/grid-search-benchmark.js 2.95 kB {0} [optional] [built]
     [315] ./benchmark/iris/util.js 823 bytes {0} [built]
     [316] ./benchmark/iris/precomputed-cv-benchmark.js 1.25 kB {0} [optional] [built]
        + 332 hidden modules

    ERROR in 0.hash.worker.js from UglifyJs
    Unexpected token: name (Matrix) [0.hash.worker.js:330,6]

The second attempt, with my very limited knowledge on the subject was to use webpack to bundle just your the library. So what I did was to create a webpack.config like this:

'use strict';
module.exports = {
  entry: "../wasm.js",
  output: {
    filename: "bundle.js",
    library: 'SVM',
    libraryTarget:'window'
  },
  resolve: {
      extensions: ['.js'],
      alias: {
          react: 'preact-compat',
          'react-dom': 'preact-compat',
      }
  },
  module: {
      rules: [
          {
              exclude: [/node_modules/, /libsvm\.asm\.js$/],
              test: /\.jsx?$/,
              loader: 'babel-loader'
          },
          {
              test: [/\.wasm(\?v=[0-9]\.[0-9]\.[0-9])?$/, /libsvm\.asm\.js$/, /libsvm\.js\.mem$/],
              loader: 'url-loader',
              query: {
                  name: '[name].[ext]',
                  limit: 1
              }
          }
      ]
  },
  node: {
      fs: 'empty'
  }
}

This compiles successfully, but then when I created a simple HTML like this:

<html>
  <body>
    <script src="bundle.js"></script>
    <script>
          console.log('SVM '+window["SVM"])
          console.log(JSON.stringify(Object.keys(window["SVM"])))
          var SVM = window["SVM"].then(function(d){
            console.log('ok')
          });
    </script>
  </body>
</html>

I get this error:

bundle.js:13220 Uncaught (in promise) TypeError: libsvm.cwrap is not a function
    at window.SVM.module.exports (bundle.js:13220)
    at window.SVM.module.exports.libsvm.isReady.then.l (bundle.js:13207)
    at <anonymous>
As my goal is to just run a simple HTML page with libsvm I also tried to create a new target in the Makefile to use emscript to create a simple HTML page, but in that case I am getting 
``libsvm.js:1 Uncaught ReferenceError: require is not defined`` in any case.

Then, my third idea (again with very limited knowledge) was to try to get ecmscripten to generate an HTML file for me.

So I created entries like this on the Makefile:

html-wasm: js-interfaces.c svm.o libsvm/svm.h
        mkdir -p $(BUILD_DIR)/wasm; $(CC) $(CFLAGS) js-interfaces.c svm.o -o $(BUILD_DIR)/wasm/index.html --pre-js src/wasmPreJS.js -s -s BINARYEN_ASYNC_COMPILATION=1 -s BINARYEN=1 -s "BINARYEN_METHOD='native-wasm'" -s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS=$(EXPORTED_FUNCTIONS)

After doing make html-wasm and running the site on a webserver I got "index.js:1 Uncaught ReferenceError: module is not defined" in the emscripten demo site. I am using Chrome 62.0 in Debian.

I know that probably some of my attempts may not make too much sense if someone already knows about these technologies, but I am having a hard time to get this running :(

Any help would be appreciated. Thanks!

nopbyte commented 6 years ago

Ok, I have figured out two things:

one, there seems to be a bug in the Makefile which prevents emscript from including the cwrap function. I fixed it and created a PR https://github.com/mljs/libsvm/pull/12

Also, I created a small tutorial and demo in a new folder called browser-lib on how to build a bundle and use it as a library from an HTML file in a forked repo here https://github.com/nopbyte/libsvm/tree/tutorial-html in case it can be merged in this repository.

Feel free to close this issue after you have decided whether or not to merge my contributions as the problem is solved now.

stropitek commented 6 years ago

Thanks a lot for contributing! I'll have a look at the PR over the weekend.

stropitek commented 6 years ago

Hey @nopbyte

FYI, the package now includes a build for the browser.

https://github.com/mljs/libsvm/issues/13