README.md

Reaxt
=====

Use your *react* components into your elixir application, using webpack compilation, so :

- An isomorphic ready library (SEO/JS are now nice together), but with Elixir on the server side
- Just a Library, with a minimum constraint about your application organization and layout :
  - use any javascript compiled language
  - use any javascript routing logic or library
  - you can use JS React rendered component only for parts of your webpage
- Nice fluent dev workflow, with :
  - combined stacktrace : elixir | javascript
  - hot loading on both server and browser
  - NPM/Webpack as the only config for respectively dependencies/compilation
  - A cool UI to have an overview of your compiled javascript application
  - You do not have to think about the server side Javascript configuration, 
    just write a webpack conf for the browser, and it is ready to use.

## Usage ##

See https://github.com/awetzel/reaxt-example for a ready to use example
application, but lets look into details and requirements.

In your mix.exs, add the dependency and the custom compiler for webpack: 
- Add the `:reaxt` dependency to your project.deps and application.applications
- Add `compilers: [:reaxt_webpack] ++ Mix.compilers` to your project

In your config/config.exs, link the reaxt application to the
application containing the JS web app
- `config :reaxt,:otp_app,:yourapp`

Create the good directory and file layout:
- `MIXROOT/web`
- `MIXROOT/web/package.json` containing your app NPM dependencies
- `MIXROOT/web/webpack.config.js` containing only the client side
  logic, use "reaxt/style" instead of "style" loader to load your css.
  A typical output path is `../priv/static`.
- `MIXROOT/web/components` containing modules exporting React components

In your elixir code generating HTML :
- add `WebPack.header` in the `<head>`
- add a script with src `/your/public/path/<%= WebPack.file_of(:entry_name) %>` 

Then render your server side HTML :

```elixir
# if web/components/thefile exports the react component
Reaxt.render!(:thefile,%{it: "is", the: "props"})

# if web/components/thefile exports an object containing a react component
# at the key "component_key"

Reaxt.render!({:thefile,:component_key},%{it: "is", the: "props"})

# if you want to use javascript to dynamically find your component and initial props
# then thefile should exports a function(arg,callback) 
# which then call callback(handler,props)
# WARNING : your dynamically loaded component must have a displayName of
#           "componentFileName.componentProperty" or "componentFileName"
Reaxt.render!(:thefile,args,dyn_handler: true)
```

The function return a `%{html: html,css: css,js_render: js_render}`, you have to add in the html :
- the css `<style><%= render.css %></style>`
- the html in an identify block (`<div id="myblockid"><%= render.html %></div>`)
- the client side rendering call with `<script><%= render.js_render %>("myblockid")</script>`

For example, if you want a page entirely generated by the react
component exported at `web/components/app.js`, then in your elixir web server, send :

```elixir
EEx.eval_string("""
  <html>
  <head> <%= WebPack.header %>
    <style><%= render.css %></style>
  </head>
  <body>
    <div id="content"><%= render.html %></div>
    <script src="/public/<%= WebPack.file_of(:main) %>"></script>
    <script><%= render.js_render %>("content")</script>
  </body>
  </html>
""",render: Reaxt.render!(:app,%{my: "props"}))
```

Finally, you have to serve files generated by webpack :
```elixir
plug Plug.Static, at: "/public", from: :yourapp
```

Then `iex -S mix` and enjoy, but the best is to come.

## Custom Plug : Hot loading and WebPack web UI

When you serve files generated by webpack, use the plug
`WebPack.Plug.Static` instead of `Plug.Static`, it contains 
 an elixir implementation of react-dev-server, and a nice UI.

```elixir
  if Mix.env == :dev do 
    use Plug.Debugger
    plug WebPack.Plug.Static, at: "/public", from: :myweb
  else
    plug Plug.Static, at: "/public", from: :myweb
  end
```

Then go to http://yourhost/webpack to see a beautiful summary of
your compiled js application.

Then configure in your application configuration :
- `config :reaxt,:hot,true` to enable that:
  - server and client side JS will be compiled each time you change files
  - server side renderers will be restarted at each compilation 
  - client browser page will be reloaded, a desktop notification will be triggered
  - The `/webpack` UI will be automatically reloaded if it is on your browser
- `config :reaxt,:hot,:client` to enable the same hot loading, but
  with webpack module hot loading on browser to avoid full page reload
  - use the webpack loader `react-hot-loader` to load your
    component to enable automatic browser hot reloading of your components
  - the `reaxt/style` loader for your css enable hot reloading of your css

## Error management

JS exceptions and stacktraces during rendering are converted into
Elixir one with a fake stacktrace pointing to the generated javascript file.

This is really nice because you can see javascript stacktrace in the `Plug.Debugger` UI on exception.

## Perfs and pool management

The NodeJS renderers are managed in a pool (to obtain "multicore" JS rendering), so :

- `config :reaxt,:pool_size` configure the number of worker running permanently
- `config :reaxt,:pool_max_overflow` configure the maximum extension of the
  pool when query happens an it is full

A clever configuration could be : 

```elixir
config :reaxt,:pool_size, if(Mix.env == :dev, do: 1, else: 10)
```

For minification, remember that webpack compilation is launched by Mix, so you
can use `process.env.MIX_ENV` in your webpack config.

```elixir
{
  externals: { react: "React" },
  plugins: (function(){
    if(process.env.MIX_ENV == "prod") 
      return [new webpack.optimize.UglifyJsPlugin({minimize: true})]
    else
      return []
  })()
}
```