Phoenix 1.7 with Angular

Right now I have a project that is split between a frontend written in Angular and served by AWS Amplify and a Phoenix backend that runs inside AWS EC2.

I would like to move the Angular project inside Phoenix so the backend itself would serve the Angular frontend files making my deployment and infrastructure simpler.

I can only find old tutorials for webpack on how to do it, I was wondering if someone already did something like that with the new Phoenix and can share some insights.

Btw, my idea is to let the Angular app handle its own routes, so I believe in the end I only need one dumb controller to load the Angular code and then Angular should take over the rest.

I also, if possible, would like to keep the Angular project file structure as-is, meaning that I would probably just have a assets/frontend with the whole project inside it.

What have you tried so far? It should be about:

  1. Drop your angular app into assets/js
  2. Update esbuild (?)/npm to build the package and dump it in to priv/static/js
    • its a long while since I touched angular, not sure if esbuild can handle it alone.
    • if you want to use assets/frontend you will have to adjust some paths to match, add static/frontend to your endpoint static paths, etc.
  3. Write some basic controller and template to boostrap the app.

There probably isn’t much written about it because I don’t think there is much to write :slight_smile:. Perhaps an open market for you!

e: I do remember seeing a blog post yonkers ago about passing any full request down to a SPA’s router, but can’t recall the whole details.

Probably you could do:

#router.ex

# may pay to separate "default landing" and "specific page" into separate actions
get "/", AppController, :index
get "/app/*path, AppController, :direct 

Then in the action you can do something like

def direct(conn, params) do
  # honestly forget the exact syntax here, probably you can use ~H
  render("app.html", path: Enum.join(params["path], "/"))
end
<html>
  <div data-router-init-path={@path} />

This way, (assuming angular apps don’t use url fragments anymore), you can go to myapp.com and get the app, navigate via angulars router to myapp.com/user/settings and refresh and land back on the correct angular view.