Lightweight Elixir web framework?

I’ve already used Phoenix several times, but I’m interested in your thoughts about Elixir frameworks similar to https://javalin.io or http://sparkjava.com/ if there is any. I can’t find too much info about this, I only find info about Phoenix.

1 Like

Using just Plug as your web server may be enough in a lot of cases.

Most (all?) Elixir libraries designed to be used in a web app provide a plug out of the box. So if you find Plug lacking some functionality you need, it shouldn’t be too hard to find a library that implements it.

4 Likes

You can pass options like --no-ecto, --no-brunch, --no-html to mix phx.new in order to leave out parts of Phoenix you don’t need. What exactly is not lightweight enough for you about Phoenix?

9 Likes

Do you think something like this? https://m.alphasights.com/simple-web-servers-with-plug-and-cowboy-34f7a174f252

I already used this for implementing a RESTful API using a Neo4j db. Pretty neat. I just wanted to checkout if there was any alternatives out there and give them a try.

1 Like

Phoenix is already a lightweight framework :003:

We do have other frameworks in Elixir, but I would say that generally they exist to offer different styles of development.

Also, in case you didn’t know, Phoenix has been described as ‘more than just a web framework’ in the sense that it can be used as a thin layer inside an Elixir app… multiple times :101:

If that interests you, the legendary Dave Thomas goes into detail about it in his online course.

9 Likes

I’ve built myself a “lightweight web framework” with plug+cowboy for Nerves devices pretty frequently for things like configuration utilities. Once you build in ecto and templating, you’ve essentially got yourself what you get from mix phx.new --no-ecto --no-brunch but it doesn’t have the same level of maturity/usability as the phx.new version.

That being said it isn’t particularly hard, and it can be kept to about one/two + templates which is nice.

5 Likes

As a note to anyone implementing .eex templating with just plug, don’t use the default eex engine, it’s quite inefficient since it just concatenates binaries – instead, either write your own .eex engine or use phoenix’s one for html to handle the templates as iodata.

It’s also important to understand what exactly is the goal of “lightweight”, if it’s to reduce complexity, then plug won’t offer much against phoenix, especially if you use --no-* flags as people above have mentioned; if it’s to improve performance, then from my benchmarks with tsung for websockets and wrk for http/1.1 from last year, the biggest improvements were not from picking plug or phoenix, but from changing the underlying webserver from cowboy to something, well, more performant (like a modified version of elli).

modified version elli?

The most important modifications in terms of usability and performance that I made were:

  • for http/1.1: support for plug. Since plug is modeled to work well with cowboy, elli needed to be modified a bit to work both with plug and metrics collection callbacks. A simple way to add plug integration into elli without forking elli would be to “handover” the request to a plug adapter in elli_http:handle_request, but then some request timings would be lost.

  • for websockets (websockets support is not included with elli, actually, but rather comes in an extension): that extension was again modeled after cowboy and used :inet.setopts(socket, active: :once) which was inefficient for big messages, so instead I :inet.setopts(socket, active: false) the socket whenever a packet arrived, and read it with :gen_tcp.recv “manually” untill it was over, and switched back into active: :once only then. Not sure if the current cowboy’s websockets implementation has this “optimization”. Seems like it doesn’t and stream’s read_body still uses messaging (in addition to then sending messages once again from the socket process to the stream process? not sure) which is quite less efficient than :gen_tcp.recv.

5 Likes

Also check out Raxx and Raxx.Kit (kind of a boilerplate for Raxx I think). They’re on roughly the same abstraction level as Plug, but have a bit of a different philosophy. :slight_smile:

5 Likes

Agree to, respectfully, disagree. :smile:

It may be lightweight for the machine, i.e. performant.
I don’t believe it to be lightweight in terms of concepts to learn or conventions assumed.

Most of the concepts and conventions are very helpful but hard to work around if you are going a different direction. An issue that is standard for anything that hopes to be “batteries included” Frameworks vs libs + from scratch

2 Likes

I would love to hear examples about this in regards to Phoenix. I.e. something you wanted to take into a different direction and it is getting in your way.

The only one on top of my mind is getting connection parameters in your sockets, but that is being fixed for v1.4.

7 Likes

It’s interesting that you brought this up - I’ve been wondering for a long time why Elixir doesn’t have a sinatra clone - almost every language (especially “ruby descendants/inspired” languages) has some some form of sinatra clone.

I’m also perfectly happy with phoenix and think it’s light weight enough, I can restructure folders etc. however I like but I often think about building a sinatra clone for fun and for getting more used to macros :grin:

1 Like

I think it’s precisely because of what José suggested: Phoenix doesn’t really get in your way when you build your application.
It doesn’t force you to write your code a certain way or use specific libraries for things that are unrelated to its core functionality (serving HTTP and Websocket requests).

3 Likes

True that - one of the many reasons I really like phoenix.

Sometimes I still think that a sinatra like library might be nice (although as many people here mentioned you can just use plug instead) - i.e. for teaching or really small projects (let’s say a little chat bot).

I probably underestimate the effort to make a good sinatra clone though :slight_smile:

I think, in a way, Plug.Router already exposes a sinatra-like DSL, so there’s no separate package - most people looking for something like that find it enough.

4 Likes

This might be of interest to you if you want to build something using Plug. German Velasco is a great guy, I used to work with him at thoughtbot, and he breaks it down very nicely:

Build your very own Web Framework in Elixir

7 Likes

Some people might have inferred from the OP’s post that Phoenix wasn’t a lightweight framework, whereas I think the general consensus is that it is :slight_smile:

Had they asked for a ‘simpler’ framework I might have asked in what way since Phoenix itself can be used in various ways; from a simple (albeit more majestic) monolith (so pretty easy for anyone coming from Rails to jump into), to the default (more ideal) path using Contexts and pushing the Phoenix is not your app mantra, and then of course this can be taken to the extreme, where Phoenix is used as a layer (or a number of layers) inside an Elixir app which itself is built as a series of components (as per Dave’s course). I actually really love that Phoenix is flexible like this and I can definitely see me using it in all three of those ways for different kinds of apps :003:

I probably would have also included links to RaxxKit as something worth looking at, but in all honesty I really do not know enough about it other than it seeming to be more like Ruby’s Hanami which is comprised of several micro-libraries (I can see the benefit of something like that in Ruby, but am, as of yet, unsure where it fits in the Elixir world). Perhaps you can help with that - I don’t think you ever got around to answering my questions about it which would definitely help people see why it was created, where it fits into the Elixir landscape, its pros, cons, and when someone might want to use it over other frameworks :023:

2 Likes

This might be of interest to you if you want to build something using Plug.

It would be quite less efficient than the default phoenix setup since he used the default EEx engine for templates which just concatenates binaries instead of using iolists. It’s the mistake I’m seeing most often when people try using plug.

Still, a great introduction.

1 Like

The comparison to Hanami is probably quite good as I have been following that projects development . HoweverI’m not trying to make a phoenix vs Raxx case here.

Raxx.Kit obviously has it’s own set of assumptions/conventions and as I mention whenever possible I have been using both in production for over a year now and each has their place.

What I find more curious is the goal of phoenix to be both lightweight and batteries included. Trying to optimise for both has always seamed ambitious to me and prone to compromise even if that compromise is just mixed messaging. Anyway the consensus is not with me here and I am happy to let that continue.

I will answer your question in that thread

1 Like

At work we toyed a bit with just Plug+Cowboy for “HTTP API” style apps, but everything turned out a bit differently. The last couple of projects, we just generated a Phoenix app with all the --without options, then take an axe and kill the foo_web/foo stuff, remove everything else we don’t need, and then have something that - if needed - can grow back into something full-fledged but it simple, minimal, and understandable; developers that just did a Phoenix read-through will know where to find everything but it’s still very light-weight. Just checked one project, cloc says there’s 125 LOC in the Phoenix bits.

One of these days, I’m gonna whip up something that just generates this minimal thing :slight_smile:

4 Likes