Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Introducing AdonisJS - Routes & Controllers
Aman Virk
Aman Virk

Posted on

     

Introducing AdonisJS - Routes & Controllers

Let's start dipping our toes in the code now by creating some routes and controllers.

For anyone unaware of the term routing. In terms of web development, it is a mapping of URLs and their handlers that you want your app to handle. URLs outside of this mapping will result in a 404.

Defining routes

Routes in AdonisJS are defined inside thestart/routes.ts file. Using this file is a convention and not a technical limitation. Let's open the file and replace its contents with the following code snippet.

importRoutefrom'@ioc:Adonis/Core/Route'Route.get('/',async()=>{return'This is the home page'})Route.get('/about',async()=>{return'This is the about page'})Route.get('/projects',async()=>{return'This is the page to list projects'})
Enter fullscreen modeExit fullscreen mode
  • We begin by importing theRoute module.
  • Using theRoute.get method, we define a total of 3 routes.
  • A typical route accepts aroute pattern and ahandler to respond to the requests.
  • In the above example, the handler is an inline function. Later we will look into using controllers as well.
  • Finally, the return value of the function is sent back to the client making the request.

Let's give this code a try by visiting the URLs for the registered routes.

Supported data types

You can return most of the Javascript data types from the route handler and AdonisJS will properly serialize them for you.

Route.get('/',async()=>{// return 28// return new Date()// return { hello: 'world' }// return [1, 2, 3]// return false// return '<h1> Hello world </h1>'})
Enter fullscreen modeExit fullscreen mode

HTTP Context

Every route handler receives an instance of the HTTP context as the first parameter. The context holds all the information related to the current request, along with theresponse object to customize the HTTP response.

Route.get('/',async(ctx)=>{console.log(ctx.inspect())return'handled'})
Enter fullscreen modeExit fullscreen mode

Following is the output of thectx.inspect().

If you are coming from a framework like express, then there is noreq andres objects in AdonisJS. Instead you have access toctx.request andctx.response.

Also note that the API ofrequest andresponse is not compatible with express and neither it is a goal for us.

The HTTP context has an extendible API and many AdonisJS packages add their properties to the context. For example: If you install the@adonisjs/auth module, it will add thectx.auth property.

Using controllers

Controllers in AdonisJS are vanilla ES6 classes stored inside theapp/Controllers/Http directory. You can create a new controller by running the following ace command.

node ace make:controller TodoController# CREATE: app/Controllers/Http/TodosController.ts
Enter fullscreen modeExit fullscreen mode

Let's open the newly created file and replace its contents with the following code snippet.

import{HttpContextContract}from'@ioc:Adonis/Core/HttpContext'exportdefaultclassTodosController{publicasyncindex(ctx:HttpContextContract){return'Hello world from the todos controller'}}
Enter fullscreen modeExit fullscreen mode

How should we now go about using this controller inside our routes file?
Let's begin with zero magic and simply import the controller inside the routes file. Open thestart/routes.ts file and add another route using the controller.

importRoutefrom'@ioc:Adonis/Core/Route'importTodosControllerfrom'App/Controllers/Http/TodosController'Route.get('/todos',(ctx)=>newTodosController().index(ctx))
Enter fullscreen modeExit fullscreen mode

Visit thehttp://localhost:3333/todos URL and you will surely see the return value from the controller method.

Lazy loading controllers

Now, imagine an app with 40-50 controllers. Every controller will also have its own set of imports, making the routes file a choke point.

Lazy loading is the perfect solution to the above problem. Instead of importing all the controllers at the top level, we can lazily import them within the route's handler.

importRoutefrom'@ioc:Adonis/Core/Route'Route.get('/todos',async(ctx)=>{constTodosController=(awaitimport('App/Controllers/Http/TodosController')).defaultreturnnewTodosController().index(ctx)})
Enter fullscreen modeExit fullscreen mode

Now, theTodosController is only loaded when the request for the/todos route comes in. Since the import/require statements are cached in Node.js, you don't have to worry about reading the same file multiple times from the disk.


Are are you happy with the above code?
I am personally not. There is too much boilerplate and you would expect a framework to do a better job here and cleanup things for you and AdonisJS does that.

Replace the previously written route with the following code snippet.

Route.get('/todos','TodosController.index')
Enter fullscreen modeExit fullscreen mode

This is the recommended way of referencing controllers within your routes file.

  • We already know that your controllers are inside theapp/Controllers/Http directory and hence there is no need to define the complete path.
  • You only need to define the file name and the method to be called on the exported class.
  • Behind the scenes, AdonisJS will lazily import the controller. Creates an instance of it and executes the referenced method.

What about the type safety?
The verbose implementation has the extra benefit of being type safe. This is something missing when using the string based expression. Or I will say, it is missing for now.

We need two things to achieve type safety when referencingcontroller.method as a string expression.

  1. The ability to tokenize the expression and create a full path to the controller and its method. This is achievable withTypescript 4.1 beta release. Here is aproof of concept for the same.
  2. Next is the ability to have anImport type with support for generics. There is anopen issue for it and I am positive that it will make its way to the Typescript in the future, as it adheres to the Typescript design goals.

To summarize, we bet in the future of Typescript and decided to remove all the extra boilerplate required to reference controllers within the routes file and expose a simple to use API.

Wrap up

Alright, let's wrap up this post. In the next post, we will begin designing the web page for our todo app.

Meanwhile, lemme share some code examples for commonly required tasks that you may perform when creating a web app.

Render views

Render views using the AdonisJStemplate engine

Route.get('todos',async({view})=>{returnview.render('todos/index',{todos:[{id:1,title:'Writing an article',isCompleted:false}],})})
Enter fullscreen modeExit fullscreen mode

Modify outgoing response

Route.get('/',async({response})=>{response.redirect('/to/a/url')response.status(301)response.header('x-powered-by','my-app-name')response.cookie('foo','bar')})
Enter fullscreen modeExit fullscreen mode

Stream files from the disk

Route.get('/',async({response})=>{response.download('/path/to/some/file.txt')})
Enter fullscreen modeExit fullscreen mode

Read request data

Route.get('/',async({request})=>{console.log(request.url())console.log(request.method())console.log(request.cookie('cookie-name'))// request body + query stringconsole.log(request.all())// get a single file & validate it tooconstavatar=request.file('avatar',{size:'2mb',extnames:['jpg','png','jpeg'],})// All uploaded files as an objectconsole.log(request.allFiles())})
Enter fullscreen modeExit fullscreen mode

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
badasscoder profile image
Badasscoder
Ivan Wang is from Cocos Islands where he works as an Vue Js Developer at Daily Syntax. He has 1 year of experience with Vue Js.
  • Location
    Cocos Islands
  • Work
    Vue Developer at Daily Syntax
  • Joined

how to use imported routes.
user-routes.ts
admin-routes.ts

routes.ts -- default
import user, admin ................... routes to routes.ts

but how to use them in routes group in routes.ts file

CollapseExpand
 
gajen007 profile image
Gajen Dissanayake
  • Joined

Outdated

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Joined

More fromAman Virk

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp