kbrw / reaxt

Use React template into your Elixir application for server rendering

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Integration with Phoenix server

emilingerslev opened this issue Β· comments

reaxt seems to be able to integrate with phoenix, since both example and phoenix is based on cowboy.

There is though a collision between the chosen node directory for reaxt, web and how phoenix use the same directory.
I'll suggest making the web folders name/location configurable through an environment setting.
Also, I don't now if there are any other issues getting reaxt to run with phoenix

Hello Emilingerslev, actually it is not so easy to make these folder configurable. A previous issue #1 talked about this. I would be happy if you find an acceptable solution.

Phoenix provides useful combination of plugs, however I personally use reaxt for pretty big project without the need to use phoenix since in an isomorphic context, the UI state management is done in javascript - which makes the uses of a server framework less useful.

Moreover, the JS / template / assets part of Phoenix is redondant with the "webpack/npm/react" approach of reaxt (but still they can be used side by side).

Currently if you do not use the compiler ":reaxt_webpack" neither the hot loader (and manually npm install /path/to/deps/reaxt/priv/commonjs_reaxt and webpack compile), there is no constraint to use a directory named "web".

I will add when I found some time if you cannot PR it the feature to configure this "web" directory in the compiler.

The only constraint which is very difficult to overcome (without painful and dangerous hacks) is the hardcoded directory for react component (currently components) because of the webpack handling of dynamic require.

Thanks for the in-depth answer. I somehow did not see the #1 issue, which is clearly related.
I did try to start the PR. I hit a few problems with understanding it all, though (still a bit new to Elixir, sorry), but I will gladly help, maybe with a few pointers to where to go. I summed up a few questions/problems:

  • First I wanted to get an overview of where the different directory paths is used, but the web/components directory is still confusing me. Where is it actually specified that when you call React.render that it will look in web/components?
  • I had trouble getting the WebPack.Plug.Static and Plug.Static to work with Phoenix. It seems plugs are handled a bit different by Phoenix, so at the moment I've only got it to work by implementing WebPack.Plug.Static as a Phoenix controller.
  • It seems that the Phoenix.Endpoint's steals the /webpack/events

To give others an easier start with phoenix and reaxt and have a test project I've created reaxt-phoenix-example. It isn't there yet, but I'll fix it when I know how to πŸ˜ƒ

By the way I kind of agree with you on the usage of phoenix is kind of strange when you got reaxt. A few reasons could be:

  • Phoenix has a lot of logging improvements, API building tools and other developer experience improvements over plain cowboy.
  • Phoenix is very easy to get started with because of the generators.
  • Some applications will have both plain web pages and SPA built on reaxt. This would be make the reaxt/phoenix combo shine.

I forgot to mention that my own intent is to use reaxt on a big project. I know of at least another of my friends that could use reaxt for a project, so I would like to help getting project a bit easier to get started with.
Of cause including helping fixing any issues. Looked into exos too. Both reaxt and exos are pretty cool projects. Nice work πŸ˜ƒ

I've gotten pretty far with the PR for using any directory for the web_app part of reaxt. I'll make the PR soon, but just walked through the phoenix example again and hit another question:

  • What is the web/index.js doing, and why is it needed? Can it be used for something?
// all the components or ./components/**/* are added to the entry by the reaxt compiler
// so here no need to do more
console.log("hello world, app entry point")

I've created the PR #7

Hello again, I agree with you about Phoenix being a good thing to develop the API, I personally use my own stack with ewebmachine that s why it was not so obvious.

I think you have to understand the main principles of reaxt to understand better the important of paths :

  • the idea is to generate both server and client side javascript with only one configuration for the client, the server configuration being handled by reaxt (that's the main problem in isomorphic apps)
  • to do that, we use webpack because it is a very good tool to handle assets/js generation :
    • a directory has to be managed with "npm", the project "reaxt/priv/commonjs_reaxt" has to be installed with npm. The : reaxt_webpack compiler handle this doing npm install //reaxt/priv/commonjs_reaxt if node_module/reaxt is not present
    • commonjs_reaxt contains the server side webpack.config which is actually a modification of the client side webpack.config :
var client_config = require("./../../webpack.config.js")
client_config.entry = "reaxt/react_server"
client_config.output = { path: '../priv', filename: 'server.js' }
client_config.target = "node"
client_config.externals = {}
module.exports = client_config
  • Elixir side GenServer renderer are actually "Exos" processes which launch the generated priv/server.js

Here the path to the "client" webpack.config is hardcoded ( ./../../ ) the question is : require is compile time for webpack, so it must be static someway.

  • the entry point of the server side JS is "react_server.js", which has to know where are the components which can be called to require them require("./../../components/"+module) same problem as before, this require is expanded at compile time by webpack to include all the javascripts file of the "components" directory. So if we want to change that, we have to precompile the "react_server.js" which is not a good idea :)

WebPack.Plug.Static is meant to be use only for dev :

  • providing the same feature than "Plug.Static" (serve files at a given dir) but waiting the end of the running compilation before serving the file.
  • adding a server-side event endpoint /webpack/events to allows some javascript to listen compilation event from the server
  • adding a UI to see a summary of the webpack compiled files : /webpack
  • serving the commonjs_react/webpack_client.js file which listen server side event to reload the javascript on client side after each compilation !!! here the path is also hardcoded to : web/node_modules/reaxt/webpack_client.js which seams to be a bad idea.

I think the best option to allow directory customization is to change only the name web to allow another name, but keep the same directory tree structure with relative paths.

I will look at your PR this evening

The index.js is the client side entry of the webpack generated JS. So you can use the file you want, and put what you want also, it is specific to your application.

The idea is that all the component/* JS are "required" by default to allow reaxt renderer to work. But the other webpack "entries" can be customized if you want.

I actually got the issue right now that I wan't to render the react root myself. Is that what I can do with the index.js?

The current PR will only allow changing the name of directory and not change the structure, since that would require a lot (like you said πŸ˜ƒ).

While getting a bit more into how Phoenix works I've found out how to use the plug supplied with reaxt. It seems to work perfectly, so with the PR the example should work great. I'll of cause update the example asap.

With the latest PR merged in, this should be doable. I'll find time to update the reaxt.phoenix repo. But I guess that being said, this issue could be closed?

Yes thank you again I close the issue, I have just published reaxt 0.3.1 with the addition. I have also update plug because its API has changed a little bit.

That awesome! πŸ‘ I'll find time to update https://github.com/ingerslevio/reaxt-phoenix-example