- Begin with scaffolding a create-react-app, then update your package.json build script (replace DIR_TO_PHX_APP with the path to your phoenix app)
"build": "react-scripts build && rm -rf DIR_TO_PHX_APP/priv/static/build && mv build DIR_TO_PHX_APP/priv/static/build",
This will move your prod build files to DIR_TO_PHX_APP/priv/static/build
on build
-
Run
npm run build
-
Time for some Elixir, first add a new function called
pwa
and disable the layout inlib/your_app_web/controllers/page_controller.ex
.
defmodule YourAppWeb.PageController do
use YourAppWeb, :controller
# Disable layout for pwa
plug :put_layout, false when action in [:pwa]
def index(conn, _params) do
render(conn, "index.html")
end
# The action that will serve the react app
def pwa(conn, _params) do
render(conn, "pwa.html")
end
end
- Open
lib/your_app_web/views/page_view.ex
and add this function.
def render("pwa.html", _assigns) do
Path.join(:code.priv_dir(:your_app), "static/build/index.html")
|> File.read!()
|> raw()
end
- Add these two plugs in
src/lib/your_app_web/endpoint.ex
plug(
Plug.Static,
at: "/",
from: {:your_app, "priv/static/build"},
gzip: false,
only: ~w(asset-manifest.json favicon.ico manifest.json service-worker.js)
)
plug(
Plug.Static,
at: "/static",
from: {:your_app, "priv/static/build/static"},
gzip: false
)
- Finally update your index route in
src/lib/your_app_web/router.ex
with your new pwa action
scope "/", YourAppWeb do
pipe_through(:browser)
# Original route
# get("/", PageController, :index)
# The new react driven route
get("/", PageController, :pwa)
end
- Done!
@ray-sh Awesome! Thanks for the feedback, I just updated the gist.