EJS Rendering HTML & CSS in Deno using View Engine 🚀
Tags: deno, webdev, node
Published: 2020-05-28 05:01:32

<p>Rendering HTML or CSS might a cumbersome process as Deno is still in its initial release and there not many plugins to use to serve HTML or CSS files. So still only a few libraries support full rendering support one of them is <a href="https://deno.land/x/view_engine">view-engine</a>. View engines provide view-engine middleware so users could pass this middleware into their application server and easily render the HTML and CSS. So without further ado lets get started… </p>

<p>
First of all, we need to create three files "app.ts", "index.ejs", "./static/style.css". Our file structure gonna look like this.
</p> 

<pre>
./
|-index.html
|-app.ts
|-static/
   |-style.css
</pre>
<p>
First, we set up our app we need to write the following code inside the app.ts file.

We need to import some libraries for this example we are going to import Oak which provides a server layer for our application and view-engine which provides a layout to paint our website.
</p>
<pre>
import { Application, Router,send } from "https://deno.land/x/oak/mod.ts";
import {viewEngine,engineFactory,
adapterFactory} from "https://deno.land/x/view_engine/mod.ts";
</pre>
<p>
In the first statement of where we require oak in which we are calling "Application" class which provides application-layer like middleware and listen to a port. While the "Router" Class will provide routes layer so we can create many routers and easily segregate the URL as we want. The "send" will help us to provide and the static file we want to serve.

After importing we need to initialize our Application and Router by using this code.
</p>
<pre>
const app = new Application();
const router = new Router();
</pre>
<p>
After initializing the application we need to configure our application to use view engine for the sake of this post we are using EJS templating engine to server HTML. You can also use other rendering engines like Denjuck or Handlebars if you prefer.
</p>
<pre>
const ejsEngine = await engineFactory.getEjsEngine();
const oakAdapter = await adapterFactory.getOakAdapter();
</pre>
<p>
After setting our view engine boilerplates we need to pass a middleware for serving static folder inside our web browser.
</p>
<pre>

app.use(async (ctx,next) => {
 await send(ctx, ctx.request.url.pathname,{
  root: `${Deno.cwd()}/static`
   })
 next();
});

</pre>
<p>
Now we can pass view engine as middleware in our app with following code:
</p>
<pre>

app.use(viewEngine(oakAdapter,ejsEngine));

</pre>
<p>
The major portion of our boilerplate has been completed now we can set up our router for this example we only use one route to the root of the URL can serve any other route you want.
</p>

<pre>

router.get("/",(ctx)=>{
 ctx.render('index.ejs',{data: {msg:"World"}}
 });

//Adding middleware to require our router
app.use(router.routes());
app.use(router.allowedMethods());

</pre>
<p>
Our app.ts file is finally completed we only need to serve our app using the following statement :
</p>
<pre>
console.log('App is listening to port: 8000');
await app.listen({port:8000});
</pre>
<p>
If you miss any step or don't able to follow our code here is the full code we have written so far in the "app.ts" file.
</p>
<pre>

// Requiring modules 

import { Application, Router,send } from "https://deno.land/x/oak/mod.ts";

import {viewEngine,engineFactory,
adapterFactory} from "https://deno.land/x/view_engine/mod.ts";

// Initiate app

const app = new Application();

const router = new Router();

// Setting up boilerplate for view-engine

const ejsEngine = await engineFactory.getEjsEngine();

const oakAdapter = await adapterFactory.getOakAdapter();

// Allowing Static file to fetch from server

app.use(async (ctx,next) => {
 await send(ctx, ctx.request.url.pathname,{
  root: `${Deno.cwd()}/static`
   })
 next()
});

// Passing view-engine as middleware

app.use(viewEngine(oakAdapter,ejsEngine));

// Creating Routes

router.get("/",(ctx)=>{
 ctx.render('index.ejs',{data: {msg:"World"}}
 });

// Adding middleware to require our router

app.use(router.routes());

app.use(router.allowedMethods());

// Making app to listen to port

console.log('App is listening to port: 8000');

await app.listen({port:8000});

</pre>
<p>
For our "index.ejs" file we can simply add HTML tags into it which looks finally like :
</p>
<pre>
&lt;html&gt;
 &lt;head&gt;
  &lt;link rel="stylesheet" href="/style.css"&gt;
  &lt;title&gt; Serving HTML and CSS &lt;/title&gt; 
 &lt;/head&gt;
 &lt;body&gt;
  &lt;h1&gt; Hello &lt;%= data.msg %>&lt;/h1&gt; 
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>
In EJS the object msg we passed in the app.ts file we can require this by using EJS syntax <%= data.msg %>.

For our final step, we need to create a style.css file inside the static file and you can code anything you want inside it relating to CSS.
</p>
<pre>

body{
 background-color: red;
}

</pre>
<p>
Now we have to test our application to write this code inside the terminal.</p>

<pre>
deno run --allow-net --allow-read app.ts
</pre>

<p>
We need to - allow-net so that our module can be download and - allow-read tag so that our server could able to send the static file. So finally we create a deno application that will serve HTML as well as CSS using View Template Engine.
</p>

{% youtube awboDcBudYQ %}