Archived

This forum has been archived. Please start a new discussion on GitHub.

Anyone using react with icejs?

Hi All,

I'm experimenting a little with react (javascript frontend framework) and thought it'd be good exercise to get some simple proof of concept icejs + react apps going.

One of the popular ways to bootstrap a react app is with facebooks create-react-app project, which deals with a lot of the vagaries of dealing with node + webpack, so I thought I'd start from there.

!https://github.com/facebookincubator/create-react-app1.

To try to get going I've done the following ( I hope the below represents a minimal complete example, running on linux)

0/ Installed the project with sudo npm install -g create-react-app
1/ Created a basic application. with create-react-app my-app
2/ Added ice as a dependency in the package.json of the resulting project.

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-scripts": "1.0.17",
    "ice": "^3.7.0",    <--- Ice Imported here, 2 lines added to default
    "slice2js": "^3.7.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

3/ In the projects src/App.js have attempted to import ice.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import ice from 'ice';  // <--- Ice Required here ( line added to default template)

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Fit like!</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

4/ Try running the project with the build in webserver with npm start

Webpack throws up a friendly stacktrace describing the problem that's occurred. At first blush it looks like some problem with bundling/imports.

I debugged the offending line with the chrome developer tools and it looks like the object that is being passed in for 'm' isn't of the desired type

Also of note there are a few errors in the node console complaining about the use of require.

./node_modules/ice/src/IceStorm/IceStorm.js
463:76-83 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

./node_modules/ice/src/Ice/Metrics.js
536:76-83 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

./node_modules/ice/src/Ice/EndpointInfo.js
65:76-83 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

I'm just wondering if anyone has come across similar + if there's a workaround. React has become very popular so I think having Ice able to interact with it easily would be a big win. Have to admit my knowledge of bundlers on the js side is very minimal so I'm not really sure what the next steps for debugging would be :-(

Cheers,

A.

Comments

  • xdm
    xdm La Coruña, Spain

    You are importing the NodeJS modules, but you should be using the browser libraries, you also need to use EcmaScript 5 of the browser libraries because the build step of create-react-app doesn't correctly handle EcmaScript 6
    First install the babel polyfill module in you application

    cd my-app
    npm install babel-polyfill
    

    And then update your imports to use the correct libraries

    import '../node_modules/babel-polyfill/dist/polyfill.js'
    import '../node_modules/ice/lib/es5/Ice.js'
    
  • Thanks for that!! Seems to have got past the first hurdle.

    No more errors, but it looks like the import is behaving strangely.

    I tried a few iterations of trying to import Ice by name etc. but the only way I seem to be able to refer to Ice (and eyeballing the source Ice.js) is by referring to it as window.Ice.

    Also, I've tried making progress by importing a slice2js generated js file.

    If I create a simple Foo.ice file and run slice2js over it, I get an error similar to this in the built-in webserver.

    Also looking through the forums I saw there was an option to get slice2js to emit es6 import/export statements. I tried adding that directive to the .ice file and now the error appears as ...

    None of these errors occur if I just import js files directly from an HTML file, but the disadvantage is that dependencies have to be stated out in the clear and the slice dependencies would be easily downloadable ( and reverse-engineerable ) by a malicious individual, hence the desire to go for a bundler of some sort.

    I guess my question now has to be, is it reasonable to expect to be able to bundle an ice application with Webpack or is this just being unrealistic+relying on unsupported functionality? I can appreciate I may be asking more a javascript question than an ice question - experiments with the javascript module system thus far have left me frankly a little bamboozled!

    If you had any best practice recommendations for how best to deploy Ice for js applications would be grateful. The demos are great but they don't really give a feel for how one could realistically deploy a production application.

    Cheers,

    A.

  • xdm
    xdm La Coruña, Spain

    Hi,

    The generate code use this wrapper function to detect if it running on NodeJS or on a Web Browser

    (typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
     typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
     typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
    

    In a browser this is the global object, but when build the code with webpack it wraps it in a function and call it with a different this breaking the code.

    We will check if is possible to improve this wrapper to also work with webpack

    If you had any best practice recommendations for how best to deploy Ice for js applications would be grateful. The demos are great but they don't really give a feel for how one could realistically deploy a production application.

    The demos actually create minified versions with all bundle dependencies, and transpiled the code to es5, we will try to improve the documentation to show how to do that with a standalone project

  • Great - thanks for the response!

    Cheers,

    A.

  • xdm
    xdm La Coruña, Spain

    Hi,

    One option to pack the generated code is to use es6 module mapping for the generated code, and keep Ice library as external dependency.

    In your Slice files add [["js:es6-module"]] metadata

    With webpack you can use something like:

    // webpack.config.js
    const path = require('path');
    
    module.exports = {
      entry: './main.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
      },
      externals: {
          "ice": "window"
      }
    };
    

    see https://webpack.js.org/configuration/externals/

    With rollup

    // rollup.config.js
    export default {
        input: 'main.js',
        output: {
            file: 'bundle.js',
            format: 'iife',
            globals: {
                ice: 'window'
            }
        },
        external: ['ice'],
    };
    

    see https://rollupjs.org/

    Then you will need to include Ice library in your html using the script tag, for production I think the best is to use cdnjs libraries https://cdnjs.com/libraries/ice you can use a local copy from (node_modules/ice/lib) during development if you need to work offline.

    Regarding create-react-app the problem I see is that seems that it does not allow to setup the externals used by webpack. I might be wrong about this last point as I have not look very deep into it.

  • Thanks I'll have a look into this as a means of packaging my generated code.

    I'm making a tactical retreat from attempting to bundle the app for the meantime. I think trying to achieve these two goals at the same time ( getting ice+react working, as well as getting bundling working), is biting off too much at once.

    I've got a simple example with a python server calling back to a browser client + rendering state changes as a result of callbacks into react components. ( So a lot further than I was previously!).

    One additional issue I found was that I can't implement a servant as an ES6 class inside a file that's being run through babel (Babel is a necessary step in react apps to perform jsx -> js transpilation) . I have to implement the servant inside a separate js file and import it from the HTML ( i.e ensuring no transpilation is performed on it), much the same way as I'm currently doing for my slice2js-generated .js files.

    (unknown) Uncaught TypeError: Class constructor  cannot be invoked without 'new'
        at new MyListener (<anonymous>:25:114)
        at <anonymous>:74:10
        at i (http://localhost:3000/vendor/babel-standalone.js:23:29575)
        at r (http://localhost:3000/vendor/babel-standalone.js:23:30084)
        at e.src.n.(anonymous function).error (http://localhost:3000/vendor/babel-standalone.js:23:30399)
        at XMLHttpRequest.n.onreadystatechange (http://localhost:3000/vendor/babel-standalone.js:23:29842)
    

    So really I think in principle it's just bundling (and maybe some associated transpilation issues that I'm having now).

    The good news though is that ice + react seem to be happy to interact with each other. I'm trying to find an idiomatic means of getting callbacks from a server to flow into react components. First very rough cut is here. https://github.com/smandy/ice_react I'll try tidying it up to get something cleaner. If anyone's tried getting data flowing from ice into react would be keep to compare notes :-)

    Cheers,

    A.

  • xdm
    xdm La Coruña, Spain
    edited December 2017

    Glad you are making progress, regarding babel I'm pretty sure you can use it because Ice is itself use it for both the libraries and demo applications, we write everything as ES6 and use babel to transpile the code to ES5

  • Thanks + yes that's a good point! I'll study how the demos are building for clues as to what I'm doing wrong.

    Cheers,

    A.

  • Just been reading up a bit more. I didn't realise react was shifting emphasis towards rollup away from webpack. Was your decision to use rollup versus webpack based on technical merit/familiarity/other? Rollup might be the way to go if it's react friendly and doesn't screw up the imports of ice modules the way webpack is currently doing.

    Cheers,

    A.

  • xdm
    xdm La Coruña, Spain

    We pick rollup because was lightweight but webpak is a fine alternative and both do a great job. Webpack doesn't screew the imports you just need to configure Ice as a external library and use es6-modules for the generated code as show in the example above.