Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
locals_without_parens = [
plug: 1,
plug: 2
]

[
inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"],
locals_without_parens: locals_without_parens
]
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

* Support for esbuild

### Changed

* Updated poolboy, it itself now uses rebar3 to build.
Expand Down
36 changes: 36 additions & 0 deletions lib/app.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule Reaxt.App do
use Application
require Logger

def start(_, _) do
hot_reload_processes =
if Reaxt.Utils.is_hot?() do
hot_processes(Reaxt.Utils.bundler())
else
[]
end

base_processes = [
Reaxt.PoolsSup
]

children = Enum.concat(base_processes, hot_reload_processes)

result = Supervisor.start_link(children, name: __MODULE__, strategy: :one_for_one)
if Reaxt.Utils.is_webpack?(), do: Reaxt.Index.Generator.build_webpack_stats()

result
end

def hot_processes(:webpack) do
[
WebPack.Hot.Events,
WebPack.Hot.EventManager,
WebPack.Hot.Compiler
]
end

def hot_processes(_) do
raise "[Reaxt] Hot reload is not supported for the bundler #{inspect(Reaxt.Utils.bundler())}"
end
end
9 changes: 9 additions & 0 deletions lib/esbuild/esbuild.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Reaxt.Esbuild do
@moduledoc """
Utilities functions to fetch specific esbuild configs
"""

def esbuild_config do
Application.get_env(:reaxt, :esbuild_config, "build.js")
end
end
53 changes: 53 additions & 0 deletions lib/esbuild/tasks.esbuild.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
defmodule Mix.Tasks.Esbuild.Compile do
use Mix.Task

@shortdoc "Compiles Esbuild"

def run(_) do
{_logs, 0} = compile()
:ok
end

def compile() do
config = "./" <> Reaxt.Esbuild.esbuild_config()

System.cmd(
"node",
[config],
into: "",
cd: Reaxt.Utils.web_app(),
env: [{"MIX_ENV", "#{Mix.env()}"}]
)
end
end

defmodule Mix.Tasks.Compile.ReaxtEsbuild do
use Mix.Task.Compiler

def run(args) do
IO.puts("[Reaxt] Running Esbuild compiler...")
Mix.Task.run("reaxt.validate", args ++ ["--reaxt-skip-compiler-check"])

if !File.exists?(Path.join(Reaxt.Utils.web_app(), "node_modules")) do
Mix.Task.run("npm.install", args)
else
installed_version =
Poison.decode!(File.read!("#{Reaxt.Utils.web_app()}/node_modules/reaxt/package.json"))[
"version"
]

current_version =
Poison.decode!(File.read!("#{:code.priv_dir(:reaxt)}/commonjs_reaxt/package.json"))[
"version"
]

if installed_version !== current_version, do: Mix.Task.run("npm.install", args)
end

if !Reaxt.Utils.is_hot?() do
Mix.Task.run("esbuild.compile", args)
else
{:ok, []}
end
end
end
51 changes: 51 additions & 0 deletions lib/pool.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
defmodule Reaxt.PoolsSup do
@moduledoc """
Supervision of multiple :poolboy instances for the Server Side Rendering
"""
alias :poolboy, as: Pool

use Supervisor
require Logger

def transaction(pool_name, fct) do
Pool.transaction(pool_name, fct)
end

def start_link(arg) do
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
end

def init(_) do
pool_size = Reaxt.Utils.pool_size()
pool_overflow = Reaxt.Utils.max_pool_overflow()
server_dir = "#{Reaxt.Utils.web_priv()}/#{Reaxt.Utils.server_dir()}"
server_files = Path.wildcard("#{server_dir}/*.js")

if server_files == [] do
Logger.error(
"#server JS not yet compiled in #{server_dir}, compile it before with `mix webpack.compile`"
)

throw({:error, :serverjs_not_compiled})
else
children =
Enum.map(server_files, fn server ->
parsed_js_name =
server |> Path.basename(".js") |> String.replace(~r/[0-9][a-z][A-Z]/, "_")

pool_name = :"react_#{parsed_js_name}_pool"

args = [
worker_module: Reaxt.Render,
size: pool_size,
max_overflow: pool_overflow,
name: {:local, pool_name}
]

Pool.child_spec(pool_name, args, server)
end)

Supervisor.init(children, strategy: :one_for_one)
end
end
end
110 changes: 0 additions & 110 deletions lib/reaxt.ex

This file was deleted.

50 changes: 50 additions & 0 deletions lib/reaxt_error.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
defmodule Reaxt.Error do
@moduledoc """
Exception representing a Reaxt Error
"""
defexception [:message, :args, :js_render, :js_stack]

def exception({:handler_error, module, submodule, args, error, stack}) do
params = %{
module: module,
submodule: submodule,
args: args
}

%Reaxt.Error{
message: "JS Handler Exception for #{inspect(params)}: #{error}",
args: params,
js_stack: stack && parse_stack(stack)
}
end

def exception({:render_error, params, error, stack, js_render}) do
%Reaxt.Error{
message: "JS Render Exception : #{error}",
args: params,
js_render: js_render,
js_stack: stack && parse_stack(stack)
}
end

def exception(rest) do
%Reaxt.Error{
message: "JS Render Exception : #{inspect(rest)}",
args: "",
js_render: "",
js_stack: ""
}
end

defp parse_stack(stack) do
Regex.scan(~r/at (.*) \((.*):([0-9]*):[0-9]*\)/, stack)
|> Enum.filter(fn [_, function, url, _line] ->
String.contains?(url, "/priv") and function not in ["Port.next_term", "Socket.read_term"]
end)
|> Enum.map(fn [_, function, url, line] ->
{line, _} = Integer.parse(line)
[_, after_priv] = String.split(url, "/priv/", parts: 2)
{JS, :"#{function}", 0, file: ~c"#{Reaxt.Utils.web_priv()}/#{after_priv}", line: line}
end)
end
end
Loading