13 ms·
Elixir, Phoenix, Absinthe, GraphQL, React, and Apollo
- em_jones 7y agoI've just been trying to get back into elixir recently, myself. I'd done some basic crud 'helloworld' stuff when I first tried about a year into professional development. I've since had the Fortune to spend time learning about cloud native apps, distributed service patterns, and supporting infrastructure (spring cloud, pcf, vanilla k8s, gcp) and now returning to elixir having at least better understanding of what erlang and OTP offers. I'm super excited to see I'm not alone in finding this sort of stack is worth fiddling with(although, I tend to pick Vue when not using angular for work). Thanks for posting this!! For those interested in what resources I'm leaning on: The Manning 'Elixir in Action' and the Pragmatic Programmer's graphql texts along with exercism. Anybody else have any preferred resources for these technologies?
- bdibs 7y agoIf you're interested in the Phoenix Framework you should check out "Programming Phoenix: Productive |> Reliable |> Fast". It's written by the creator of Phoenix (Chris McCord) and the creator of Elixir (José Valim), and it's a fantastic intro to Phoenix.
- Intermernet 7y agoLink: https://pragprog.com/book/phoenix14/programming-phoenix-1-4 https://pragprog.com/book/phoenix14/programming-phoenix-1-4
- em_jones 7y agoThis has been on my radar. I'll have to add it to my queue on Safari. Thanks for the rec!!
- thegabez 7y agoI liked this "Elixir For Programmers" by Dave Thomas https://codestool.coding-gnome.com/courses/elixir-for-programmers https://codestool.coding-gnome.com/courses/elixir-for-progra...
- mercer 7y agoI can recommend this one too! It skips right over the boring stuff and focuses on the (Dave-Thomas-flavored-) good parts. Definitely worth it if you're already somewhat proficient in Elixir.
- nickjj 7y agoI almost exclusively learned the basics of Elixir / Phoenix by looking at the source code of https://changelog.com https://changelog.com which is at https://github.com/thechangelog/changelog.com https://github.com/thechangelog/changelog.com. Major kudos to them for open sourcing their platform. It covers like 50+ common web dev features. I pretty much skimmed the docs to get the ultra basics, looked at that source while I was building my own app and then asked questions when I got really stuck. Even managed to sneak in some refactoring on their code base a few days into learning Elixir. It's super approachable without much more if you have some type of programming background beforehand.
- em_jones 7y agoThis is a sweet shout-out. Thanks!
- bigbassroller 7y agoI am pretty much in the same boat. My resources have been Programming Phoenix first edition. I am now going back and reading Programming Elixir and then re read Programming Phoenix 1.4 and then the GraphQL book by same publisher.
- AlchemistCamp 7y agoI'm a big fan of both the Manning and Pragprog books. Even if you've worked at it a bit already, you'll probably get something out of doing the first dozen or so challenges on my channel as well: https://youtu.be/G3JRv2dHU9A?t=595 https://youtu.be/G3JRv2dHU9A?t=595
- adamnemecek 7y agoOk, for backend, I’m deciding between rust with actix, jvm (kotlin + akka/quasar) or elixir. I kinda know the theoretical differences but I’m curious what hn thinks. Has someone actually deployed things in some of these. I do have preference towards rust but maybe there’s something better.
- bdibs 7y agoThat really depends on what you're building.
- adamnemecek 7y agoWhen would erlang,jvm be preferable over actix.
- dilatedmind 7y agorust is still figuring out async, so it's not as good a fit as say go or elixir. If you are specifically making a graphql backend, idk why you would anything but node, since it has the most mature ecosystem.
- adamnemecek 7y agoI mean actix just hit 1.0 and I don’t think it impacted them one bit.
- qaq 7y agoThe ecosystem is not really mature.
- skosch 7y agoThey're all wonderful, established technologies and all very capable of making concurrency relatively painless. At this stage, you should go with whatever you would be most productive in: do you already know one of the languages? If so, go with that one (always be shipping!). If not, how much do you like the syntax of each? How much do you rely on static types? How mature are the third-party libraries you're going to be relying on? I've been building software using the exact stack described in the linked article for the last three years. I don't think about my backend very much, it mostly just works. Most of the work is on the front end. Elixir/Phoenix/Absinthe have been almost completely frustration-free. I'm sure Rust and Kotlin are great too.
- sergiotapia 7y agoWhen you get to the absinthe part you lose me. It's the same gut feeling I had when I see Redux where it works but it was created at the very beginning of this entire workflow discovery and better tools/approaches have since come out.
- AWebOfBrown 7y agoCan you elaborate on what they are, for the curious?
- chrisco255 7y agoRedux is still a solid choice. Apollo is used more often now because it handles a lot of GraphQL optimization but it's by no means a panacea. And sometimes, despite being an advocate of Apollo, I miss the simplicity of Redux.
- diNgUrAndI 7y ago> I also find a lot of joy in its pattern matching and its pipe operator. It’s refreshing writing heavily functional code that still approaches the beauty of ruby, and I find that it drives me to think clearly about my code and write fewer bugs as a result. This. I use Elixir everyday. While it feels 'refreshing' to use pattern matching, sometimes it gets over-used, as a simple swtich-case statement is easier to read. Same with pipe operator. I found newbie programmers tend to pipe for the pipe's sake, and write functions just to form the 'shape' of pipe, but the data shape changes are not easy to see and inspect.
- jaequery 7y agoDoesn’t pattern matching lead to either more verbose code or a duplicate code? Most of the time?
- hdra 7y agoIt could, when its used "wrong", though thats usually a result of trying to fit pattern matching where there are other more idiomatically way to express a code. I wouldn't say "most of the the time", its more of a common beginner's mistake. Pattern matching allows you to express the code in a more declarative way, and usually would result in a more succinct code.
- hestefisk 7y agoGood read. Curious about Elixir. Why would one use this over ‘plain old’ Erlang / OTP apart from the Rubyesque syntax, which might appeal to RoR devs?
- schneidmaster 7y agoIt's 100% the syntax. It appeals to ruby devs and also I think it's a lot easier to grok in general. But you can write Erlang code directly in an Elixir file, you can use Erlang libraries directly in Elixir, and Elixir compiles to the same BEAM instructions that Erlang does, so there's functionally no difference in terms of capabilities or what happens when they run.
- qaq 7y agowell better unicode support too
- SteveGregory 7y agoThis is not totally true. It’s not 100% syntax. Elixir has one additional and widely used feature: macros. In Elixir, as in Lisp, you can transform your code as a data structure into new code. This is importantly used in Ecto, the de-facto object data mapper in Elixir. It’s also used in Absinthe, a library from the posted link for making GraphQL APIs.
- schneidmaster 7y agoYeah, this is fair. I was mentally lumping certain language features under "syntax" but that's not really accurate.
- ramchip 7y agoProtocols are also an important feature. `IO.inspect`, `Enum`, etc. are very nice additions.
- elcritch 7y ago
- swyx 7y agogreat write up. shall we dub this the PAAGER stack?
- Intermernet 7y agoAPGEAR
- macintux 7y ago> much friendier syntax for developers This drives me batty. More familiar? Sure. “Friendlier” is very subjective.
- draw_down 7y agoYeah, well, a subject wrote that.
- sugarpile 7y agoDoes anyone here who is working with elixir professionally have a sense of what kind of mastery is needed to jump into an elixir dev role? I've used it on and off for ~4 years at this point and in a few side projects (most recent one using everything in the title, weirdly enough) but can't really tell if I'm "qualified" to look for a job in it. It's this weird loop of "I've only done something as a hobby so I'm not qualified to do it professionally" vs "If I don't use it professionally I'll never be qualified to do so". Same goes for react.
- benwilson-512 7y ago> "I've only done something as a hobby so I'm not qualified to do it professionally" Definitely don't let this hold you back. As long as you're up front about where you are, and are willing to learn, lack of professional experience with a particular language is by no means a deal breaker.
- simonw 7y agoSmart teams hire great engineers and trust them to get good with the stack at hand. Don't get hung up on how much experience you have with a particular stack when looking for jobs. I've hired Rails developers for Django roles and seen them get productive within weeks. If you've used Elixir on-and-off for four years you have more experience than the majority of engineers who might be considered for an Elixir role.
- srndh 7y ago> I've hired Rails developers for Django roles and seen them get productive within weeks. What did you like about the Rails developer that you chose the person for the role? Basically, I want to know irrespective of the language, how do I show my "quality as an engineer"?
- volkk 7y agooh it's simple, you just have to invert a binary tree
- 7y ago
- rossenberg79 7y agoWhy is Elixir always being paired with Phoenix? Can’t I just have a backend API running on Elixir and a javascript front end to interact with it? I’d prefer a simple React, Postgres, Elixir stack (REP).
- notamy 7y agoBecause Phoenix is the web framework for Elixir. It's easier to just use phx instead of rolling your own solution around Plug / Cowboy.
- bitcrusher 7y agoYep! Just use Plug. There’s no need to drag the entire Phoenix stack in. https://hexdocs.pm/plug/readme.html https://hexdocs.pm/plug/readme.html
- out_of_protocol 7y agoThen you'll need to create own version of migrations, routing, configure asset building pipeline etc etc etc. Phoenix have everything in place, without need to re-implement lots and lots of basics
- Xixi 7y agoA bit pedantic, but migrations are provided by Ecto [1], not by Phoenix. You don't need Phoenix to use Ecto. https://hexdocs.pm/ecto/Ecto.html https://hexdocs.pm/ecto/Ecto.html
- out_of_protocol 7y agoWell, you'll still need to add Ecto, configure it to use separate configs for prod/dev/test environments etc - so point still stands :)
- ramchip 7y agoI have an app like that, but I found it convenient to use Phoenix anyway as it provides test helpers, a nice router, an efficient template (EEx) compiler with escaping, etc. I just ignore the parts I don't need. Phoenix LiveView looks super interesting for simplifying this further: https://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript https://dockyard.com/blog/2018/12/12/phoenix-liveview-intera...
- benwilson-512 7y agoHey folks! Co-Author of Absinthe here, happy to answer any questions about it. The post here is good, although these days we recommend using Dataloader vs Absinthe.Ecto. Dataloader really extends the idea behind Absinthe.Ecto while providing in request caching, pluggable backends, and easier query manipulation.
- schneidmaster 7y agoGood to know, thanks! I wasn't familiar with Dataloader, I'll have to check it out :)
- bnchrch 7y agoI can second this, we've been using dataloader in production for almost 2 years now. Fantastic library.
- AlchemistCamp 7y agoI've got an app with back-end oauth-based login. I had a bit of a headache integrating the sessions with Absinthe and finally arrived on this in my Context module: ``` def call(conn, _) do context = build_context(conn) Absinthe.Plug.put_options(conn, context: context) end def before_send(conn, %Absinthe.Blueprint{} = blueprint) do if blueprint.execution.context[:logout?] do Auth.drop_current_user(conn) else conn end end defp build_context(conn) do with ["Bearer " <> token] <- get_req_header(conn, "authorization"), {:ok, data} <- MyApp.Token.verify(token), %{} = user <- get_user(data) do %{current_user: user} else _ -> %{} end end # rest of the file ``` Then made a Logout middleware that sets logout? to true in the resolution context. Is digging into the Blueprint as in the code above necessary? Is there a simpler way of solving this?
- stephan83 7y agoElixir and OTP are really nice, but I'm frustrated by the type system, even with typespecs. I finally gave in and started learning Haskell. I would still choose Elixir/Phoenix for some web apps though.
- RexM 7y agoHave you checked out Gleam? https://gleam.run https://gleam.run
- lame88 7y agoExpect a long journey if you’re trying to get to the state where you can make a web app. I am making a conjecture here but from my limited but nontrivial experience it seems libraries in the applications ecosystem of haskell apply the most advanced features they know of to solve their problems. That would normally be fine, but they do not abstract away this complexity; due to the type system’s rigor, these choices are propagated to you as the consumer of the library because you have to consume the library in a way that satisfies whatever advanced type features they have. So the end result is that to get anything done like make a basic Yesod web app you have to be at an advanced level. I feel i benefitted from learning the structural and type theoretic aspects (monads etc) of Haskell but I also am glad i ditched it after some time because the investment just did not seem worth it anymore after a certain point. Anyway just my perspective, hope its helpful if you find similar difficulties. Right now I’m checking out Scala as an alternative, but i’ve just started so I can’t offer any comparison other than I know it is less rigorous.
- stephan83 7y agoThank you for the input. Maybe I will never get to the point where I can comfortably make a web app, but learning the language has been a fun experience so far. I've heard good things about Scala and Akka.
- jsjohnst 7y ago> I am making a conjecture here but from my limited but nontrivial experience it seems libraries in the applications ecosystem of haskell apply the most advanced features they know of to solve their problems. Apologies to others for the “me too” reply, but I wanted to let you know you aren’t alone, I also feel this way. It’s intellectual masturbation (without any reward/benefit), IMHO.
- yeskia 7y agoLoved this deep dive - appreciate you going step by step and explaining each part.
- schneidmaster 7y agoThanks! Glad you enjoyed it :)
- onebot 7y agoI have just starting learning Elixir and Phoenix. It seems like a solid replacement for Rails. But I keep getting hung up on performance. With React, it seems like you are developing more API back-end, then web server back-end (if that makes sense). But when you look at the performance compared to Go and the steeper learning curve, why not just use Go? Kubernetes really solves the share-nothing let-it-fail aspect. Obviously, Erlang/Elixir are hands-down a good fit for fault tolerant distributed systems where performance may not be as critical or you can use NIF. But outside chat and a few other use-cases, not sure the majority of web services falls into this. However, the functional code is so nice. Anyways, any input on how to convince engineering leadership how Elixir might be better than Go would be helpful.
- iends 7y agoFor non-stateful services, it seems very difficult to me to convince people to use Erlang/Elixir over Go. It also seems to me that Go is going to be more maintainable over time than Elixir. Also, Elixir has smaller corporate backing compared to Go. fwiw, I work at a telecommunications company and I've had no success convincing anybody to use either Go or Erlang/Elixir over Java (& Clojure).
- onebot 7y agoThat’s ironic considering that Erlang was designed for telecommunications. But I think statefulness is the right context between the two. Why do you think Go would be more maintainable?
- iends 7y agoI realize dialyxir exists, but I think a lack of static typing can lead to some maintainability issues over long term. At least this is my experience working on a 6 year old JavaScript codebase.
- pdimitar 7y agoYou seem to list political / culture / habitual phenomena here. Care to list technical argumentation instead?
- johnnyji 7y agoNice! This is 1 for 1 the exact tech stack we use at Distru :D
- hliyan 7y agoGreat article. One point though (not aimed at the author). The majority of engineering articles I see today are along the lines of "X with Y, using Z", where X, Y, Z are specific products, frameworks or libraries, often trademarks. I rarely see more generic engineering/architecture topics such as: [virtual DOM based / string based client side templating] with [JSON/Protobuf] over [REST/Websocket] with a [compiled / interpreted / JIT compiled / virtual machine based] backend runtime, built on [RDBMS/NoSQL/hybrid] etc. Am I alone in feeling this way?
- ngngngng 7y agoI'm actually writing a tutorial series aimed at programming beginners where we implement things in multiple languages/frameworks side by side. I think it's a great way to learn concepts of software engineering instead of just memorizing conventions.
- byproxy 7y agoI like this idea. Especially if you give a high-level overview of software design concepts.
- srndh 7y ago> we implement things in multiple languages/frameworks side by side. please do post the link.
- amatecha 7y agoYeah this actually sounds awesome, do you have anything live/bookmark-able yet?
- ngngngng 7y agoI have the first few lessons 90% completed but not published yet. You can bookmark my personal site natemeye.rs since they will initially be posted there before I move them to their own location.
- mercer 7y ago
- AlchemistCamp 7y agoThe project I've been working on the past couple of months is a very similar stack to this—Phoenix, Absinthe, Apollo, React, Redux. The main difference is I've been using TypeScript and the Absinthe resolvers are using Dataloader.
- TN1ck 7y agoHow's the integration of Apollo and TypeScript? Do you like the stack and would you recommend it?
- AlchemistCamp 7y agoBoth apollo-client and react-apollo ship with definitions in their npm packages, so using TypeScript with Apollo isn't a problem. I don't like the stack. It's way too heavy. If I were building everything again now, I'd go with a standard Phoenix app and ditch Redux for sure and hold off on fullblown front-end frameworks and Graphql. I'd ship v1 with Phoenix, UJS and Turbolinks, and it would take 1/4 the time. Then, if the project grew to where it needed and could support a larger team, I'd bring in Absinthe, Apollo and then finally Vue. My main recommendation would be to keep things as simple as possible for as long as possible. Use something like Phoenix or Rails or Laravel and get stuff shipped.
- xlii 7y agoStack described above is the one I’ve been working on for professionally for the last year and I wouldn’t recommend it. Main reason is the absurd amount of complexity with costs heavily outhweighting benefits gained from the solution. For example, simple task of adding new entity consists off: On backend: creating migration, creating data entity (Ecto), writing structure module (sanitization, validation, basic logic, if needed), mounting queries, writing input mutation(s), writing output query/queries, unit testing On frontend: creating component, creating form, writing graphql queries, writing mutation, wrapping components/queries in components, connecting query to components, providing action handlers for inputs, unit testing, integration testing Now I have authors list. And even though I am full stack I haven’t yet spent even single minute on having Proper UX Design set in place. Oh, do we need to add author’s birthdate? Dang, let me adjust all of that. In my opinion technical debt accumulates faster than in other solutions. GraphQL is complex. React (done right) is complex. Apollo is complex (Elixir is simple, yet it’s only one cog). Deciding on doing file upload in GraphQL led me to a rabbit hole, which took at least a week to dug out from. When trying to find the source of all development issues my thoughts go towards GraphQL. Maybe it is too complex or we didn’t had enough experience in it? Yet it was really nice to work with when all the backend and frontend boilerplate was already written. It makes sense, even though requires some heavy thought behind it. Maybe it’s Apollo, which locks in one of two specific trains of thought, or Absinthe, which requires side-hacks in order to get some bit more advanced features working with Apollo, like file uploads or query batching. From a perspective I’d say this is just too much. Every single part of this stack adds overhead to the other parts. Maybe if I had more specialized team members it would get easier, but being only 3 of us, with me, as a full stack, constantly switching between all of that was a tiresome, low-productive effort. Right now we’re disassembling app to a classic REST-app and we’re seeing development speed increase on week-to-week basis, even though we had to scrap most of the frontend. I guess there would be some benefit on having the write up of all of it, since it doesn’t even scratch the surface of the year of development issues with this stack, but even in this very "short" form it may serve for a word of warning that this stack is not necessarily something you want to care for.
- molteanu 7y agoThanks for this. I'm not a web dev, but yes, after seeing the 3rd or 4th "and then we do this" I've just started scrolling towards the end of the post and got bored fairly quickly. My thoughts exactly: this seems way too complex for creating just a few pages; too many dependencies, too many things to remember and update.
- kuon 7y agoI just started a new app, and I decided to try Phoenix LiveView. It's really simpler and easier to work with. It won't work well with all kind of apps, especially those with offline support, but for many many apps/website it is a good fit. The last app I did was a mobile app written in Elm with Phoenix. I can't recommend Elm enough, it makes JS much easier to work with. For communication I used a simple REST oriented API. While I understand why GraphQL exists, I think it is a major addition in complexity for little to no benefits. I tried it, wrote half a project with it, but they removed it. When things gets complex (for example, let's say the user.email field can be redacted under some conditions) your endpoint becomes really hard to manage. GraphQL certainly have a use for large API with graph oriented datasource (well, like facebook), but it is a specific use case.
- andrewingram 7y agoHm, I disagree on the last point. GraphQL's utility has nothing to do with whether you have a graph-oriented database. The "graph" part is merely talking about the means by which queries traverse the type system. Since REST APIs can easily be modelled as a GraphQL schema, they have a lot of overlap in utility. Basically, if you need "API-driven" front-end, the only thing that might make harder than REST for a given language is lack of libraries. If you don't need API-driven, then just do things the traditional way, or try Phoenix LiveView. The one caveat is that GraphQL (especially with Relay) maps exceptionally well do the component-based way of building things. So if you've chosen that paradigm, GraphQL might still be a good fit, even if you're just building a website.
- beckler 7y agoI want to like Elm, but every time I try to pick it up it's always my biggest time sink.
- mercer 7y agoCould you elaborate? I'm on the fence about Elm mostly because of 'ecosystem issues' (single dev, various complaints about communication, etc.), but more than once I've almost started a project because I figured the practical benefits would still be worth it.
- sntran 7y agoIt always bugs me that, with Absinthe, you have to define Ecto schema and GraphQL schema separately, when most of the time, they are very similar. Can Absinthe somehow figure out from Ecto?
- pdimitar 7y agoAlways wanted something like that as well. I am guessing until we get something like `clojure.spec` -- true typing, even if gradual (but at least not a success-typing) -- then it's not happening anytime soon.