Hey ya’ll! I’m building a single-page app backed by a Phoenix API. I don’t think I need
phoenix_html so I did
mix phoenix.new --no-html, but now I’m not sure where to put the single
index.html.eex page which references my CSS and JS.
- I don’t think I can put it under
web/static/assets because it’s not a static file. I think I need EEx and
<%= static_path() %> (which comes from the router, not phoenix_html) to reference my CSS and JS, which have dynamic filenames like
- If I put it under
web/templates/page I get an error:
(RuntimeError) Could not load Phoenix.HTML.Engine to use with .html.eex templates.
That error makes it sound like all
.eex templates require the
phoenix_html dependency, even if I’m not using any of its HTML helpers.
What am I missing? Again, I’ve got a JSON API that just needs a mostly-static HTML page to reference my CSS and JS. Thanks for any help!
IMO, the quickest solution here is to just add
phoenix_html back to your app (or create a new phoenix project, this time without the
--no-html flag). You might need it anyway later for something you don’t foresee. It’s an extra deps, but saves you from the trouble.
That said, you actually can call
static_path('js/app.js') from your router (as long as you keep the
import MyApp.Router.Helpers line on
web/web.ex), load the
index.html file as a string, and somehow inject the result of
static_path to the string (through
String.replace), and use
html conn, html_string to send the resulting string back to the client.
However, I think this approach circumvents the blazingly fast template caching that Phoenix has, though. I have no idea how it would affect the performance.
If I want to build a SPA, I usually built the client as a separate project, say as a Node.js front-end app with React and Webpack. Kind of a hassle, but there’s a lot of boilerplate templates that I can use and it’s not tied with the server’s stack. I haven’t build SPAs with Phoenix though, and if I do I might just go with the
phoenix_html approach to simplify things.
You can’t have an
html file without
phoenix_html unless you do something sort of hacky like Bobby said above.
Thanks for clarifying things Of my 3 options:
- Bring back
- Render a raw HTML string in the controller with
html(conn, str) using
- Build a separate front-end app
I’ll probably go with 1 for now but I am interested in benchmarking 2.
phoenix_html isn’t a large library, but I would rather not pay the memory overhead of including it, so long as it’s not offset by losing the efficiency of Phoenix’s template caching. Nathan Long has a great post on how Phoenix uses IOdata to make templates so fast, so perhaps I can take advantage of a similar approach. Thanks for suggesting and explaining that @bobbypriambodo.
As this is a one-person side project where I’m often adding JSON endpoints and corresponding React components at the same time, separate repos with 3 probably isn’t worth the additional complexity, though I agree, @sotojuan, that that would be the ideal, cleanest solution.
Thanks for the helpful responses!
There really is not much overhead there.
I support the idea of a separate repo and then just tossing your bundles in an S3 bucket. If you are using react but don’t want webpack headaches then create-react-app is the fastest way i’m aware of to get started. I did read the previous responses, so i’m aware of your benchmarking goals. Going with option one seems reasonable. I hope you find a setup that suites you best.