nedpals / vex

Easy-to-use, modular web framework built for V
https://nedpals.github.io/vex
MIT License
338 stars 28 forks source link

Future of Vex #5

Open nedpals opened 4 years ago

nedpals commented 4 years ago

Let me tell you this straight: the Vex web framework is pretty much limited right now. Indeed, some of it's features simplifies the creation of web apps written on V such as routing and the concept of middlewares. But despite all of that, they are still useless which brings us here to this issue of the future of Vex and how we are going to solve of it despite some issues and limitations the V compiler has right now.

This issue will be updated frequently

  1. The Vex web framework borrows ideas from Express.js and to the real OG of this pattern - Sinatra from Ruby. They give you the power to start building your backend/web app server without too much boilerplate as seen from other frameworks like Rails. In V, this is absolutely the right pattern for the semantics of the language as you just insert functions into get, post handlers and you're done! But in reality, like I said earlier, due to the current limitations Vex faces, there are some edge cases wherein you cannot easily use. Like this:
    
    import vex.server as vex
    struct Blog {
    db Db
    }

fn (blog Blog) get_index(req vex.Request, res mut vex.Response) { // assume we have queried the posts res.send(posts, 200) }

fn main() { s := vex.new() // assume we have initiated the blog struct s.get('/blog', blog.get_index) s.serve(8000) }

In this snippet, we would like to use `blog.get_index` when the `/blog` route hits into our server. However, the V compiler treats it as something other than a function which scratches our head. Indeed it's a wonderful thing to have but it might never been solve in this current state. Instead, Vex proposes a new change: the framework will do the context processing which includes initializing and injecting the request and the response data and you will take care the rest on how would you process the rest. However, you will still gonna register your routes as they will be used later when there is a matching route from the request. It works likes this:
```v
import vex.server as vex

struct Blog {
    db Db
}

fn (blog Blog) get_index(req vex.Request, res mut vex.Response) {
      // assume we have queried the posts
      res.send(posts, 200)
}

fn (app App) handle_req(ctx mut vex.Context) {
   // assume we have initiated the blog struct

   // middlewares will be removed tho :((

    // the match statement will look for the appropriate route based on the pattern given, nothing else found, it returns an error.
    match ctx.current_route {
        '/blog' {
            blog.get_index(ctx.req, mut ctx.res) // it works!
        }
        else {
            ctx.res.send('Not found', 404)
        }
    }
}

fn main() {
    s := vex.new()
    s.register('get', '/blog')
   // or you can use this as well s.get('/blog')
    s.create(handle_req, 8000)
}

In this proposed change, the code is working indeed. But here's another catch which will be talking about in point number 2.

  1. As you may have seen, we might have finally solved the problem in the framework. But no you're wrong because we created another problem this time. You see the Blog struct initiated (assume it had one as the comment says) inside the handle_req function? Everytime there is a request coming from the client, that Blog struct had to initialize again which is not our main goal for this one.

The current DB example in our examples is not suitable and satisfied enough if you are constantly mutating the data/structs of your backend which bogs me this question: How are we gonna be able to share resources (like existing structs, DB, and etc.) within a single Vex server instance despite the current limitations in our compiler? Some of the code lying inside it were "patched" for vweb in order for it to run like the feature we want to have right now.

  1. HTML Templating is really a need right now. Most people who are gonna be using the services written on V and using Vex will surely be needing an HTML content. Client-side template handling like the valval framework does is something a user might decide instead of reinforcing it.

  2. The concept of having small, modular apps and connecting it to the main server is a pretty interesting problem to tackle. It's more or less similar to microservices (I haven't tried it yet so pardon my ignorance) that's been the talk of the town in the past couple of years. Vex (as well as other frameworks) should be a great thing to have development-wise but I haven't think of a great design on how to connect multiple apps into one vex instance. One would be connecting through a so-called "group routes" or into a single, main App struct so other ones can connect to it as well. But who knows? This is a tough decision to make as it can rewrite the whole API or something a whole new thing might happen in the code.

  3. I'm planning to separate the router as a module. Fun fact, v-mime, which is a module I created for identifying MIME types, is originally gonna be part of the Vex framework as a submodule. Anyways, my router implementation isn't that good enough so feel free to fork and improve the code. As time passes by, new features might be put into modules, and eventually Vex will be set of modules/toolkit for building your own web framework (or should I say "be a mother of all web frameworks" not to be ambitious though hahahaha)

I was planning to release a new version today, but it's too risky so might as well just share to you the things that might happen in the future releases, as well as the things that I'm struggle with right now. The "new unreleased" code is available in the experimental branch of the repository and feel free to submit any suggestions to it. Thank you,

[Updated: 9:10PM (+8 Manila) - added HTML templating section]

ylluminate commented 4 years ago

As you may have seen from Alex's response in Discord:

s.get('/blog', blog.get_index)

I need this in V UI as well, so it'll be supported soon.

smartiniOnGitHub commented 3 years ago

Another great and modern web framework (but for Node.js) is Fastify and it has another central concept which is a modular architecture/extensibility via plugins, maybe something similar could be useful even here. Some other info in its Plugins Guide. Hope this helps. Thanks for Vex, it's an interesting framework. Bye