前回の記事でEJSを使ってindex.ejsをレンダリングして表示するということを勉強しました
しかし、前回のやり方だとサーバーにアクセスしたら必ずindex.htmlしか表示されません
CSSファイルすら別にすることができませんでした
そこで、今回はクライアントがアクセスしたアドレスによって表示する内容を変えるということ
「ルーティング」について勉強していきましょう
ルーティングとは
我々がWebページにアクセスする際は、その知りたい情報によってアドレスをかえてサーバーにアクセスしています
こんにちは。
Kikuchannelへようこそ。
Kikuchannelはプログラミングの勉強のためのチャンネルです。
といったように、クライアントがアクセスしたアドレスによってサーバーはどういったコンテンツを表示するか定義しなければなりません
URLによって表示を分岐する必要があります
URLモジュールを利用する
URLを利用するには、サーバーがURLを見てアドレスを知る必要があります
URLには決まった書き方がありますが、それを解析して処理を分岐する必要があります
それを簡単に処理するためのモジュールがURLモジュールです
次はURLモジュールの説明をするためのサンプルコードです

※url.parseは非推奨とでると思います。現在はWHATWG URL APIを使用するようにと表示されていましたのでそのコードもサンプルとしてこのページの下のほうに置いておきます。よかったら参考にしてください。YouTubeのはめ込み動画の下にあります。
const url = require('url'); | |
const my_url = "http://localhost:3000/user?country=Japan&city=Tokyo"; | |
const url_Object = url.parse(my_url,true); | |
console.log(url_Object.host); | |
console.log(url_Object.pathname); | |
console.log(url_Object.search); | |
const queryData = url_Object.query | |
console.log(queryData.country); | |
console.log(queryData.city); |
これを実行すると、URLモジュールによってURLからどのような情報が解析されているかがよくわかると思います
2行目で適当なlocalhost:3000のURLを書いていますが
実行した結果がこちらです

ホスト名:localhost:3000
pathname:/user
query:?country=Japan&city=Tokyo
queryのcontry:Japan
queryのcity:Tokyo
と、URLがバラバラにされて解析されているのがわかると思います
これをパース処理とよびます
URLモジュールをつかうことで簡単にURLをパース処理して、パス名を抽出したり
query(クエリ)を抽出したりすることができるのです
ちなみに、queryはご存じですか?
queryとは
サーバーへ受け渡すためのデータをURLの末尾に付け加えることができます。
?名前=値
の形でURLの末尾に記述します。
複数のデータがある場合は&をつかって複数個記述します。
これによってサーバーへデータを送ることができるようになります。
requestのURLによって処理を分岐させる
あとは、URLによって処理を分岐するだけです
以下が今回のサンプルコードです
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title><%=title%></title> | |
<link type="text/css" href="./style.css" rel="stylesheet"> | |
</head> | |
<body> | |
<header> | |
<h1><%=title%></h1> | |
</header> | |
<div role="main"> | |
<p>This is Kikuchannel.</p> | |
<p>こんにちは、今日は<%=today%>です。</br> 今日も一日がんばろう!</p> | |
</div> | |
</body> |
const http = require('http'); | |
const fs = require('fs'); | |
const ejs = require('ejs'); | |
const moment = require('moment'); | |
const url = require('url'); | |
moment.locale('ja'); | |
let datetoday = moment().format('LL'); | |
const index = fs.readFileSync('./index.ejs','utf8'); | |
const sample = fs.readFileSync('./sample.ejs','utf8'); | |
const style_css =fs.readFileSync('./style.css','utf8'); | |
var server = http.createServer(getFromClient); | |
server.listen(3000); | |
console.log('Server start!'); | |
console.log(datetoday); | |
function getFromClient(req,res){ | |
var url_parts = url.parse(req.url); | |
console.log(url_parts) | |
switch(url_parts.pathname){ | |
case '/': | |
var content = ejs.render(index,{ | |
title:'Kikuchannel', | |
today:datetoday, | |
}); | |
res.writeHead(200, {'Content-Type':'text/html'}); | |
res.write(content); | |
res.end(); | |
break; | |
case '/sample': | |
var content = ejs.render(sample,{ | |
title:'introduction', | |
today:datetoday, | |
}); | |
res.writeHead(200, {'Content-Type':'text/html'}); | |
res.write(content); | |
res.end(); | |
break; | |
case '/style.css': | |
res.writeHead(200, {'Content-Type':'text/css'}); | |
res.write(style_css); | |
res.end(); | |
break; | |
default: | |
res.writeHead(404, {'Content-Type':'text/plain'}); | |
res.end('no page...'); | |
break; | |
} | |
} | |
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title><%=title%></title> | |
<link type="text/css" href="./style.css" rel="stylesheet"> | |
</head> | |
<body> | |
<header> | |
<h1><%=title%></h1> | |
</header> | |
<div role="main"> | |
<p>I'm Kiku.</p> | |
<p>こんにちは、今日は<%=today%>です。</br> 今日も一日がんばろう!</p> | |
</div> | |
</body> |
header h1 { | |
font-size: 60pt; | |
background-color: darkcyan; | |
color: #eee; | |
text-align: left; | |
margin: 50px; | |
} | |
body { | |
font-size: 14pt; | |
color: #999; | |
margin: 5px; | |
} |
上からindex.ejs、app.js、sample.ejs、stylesheet.cssです
サーバーにアクセスしたときの処理をする関数がapp.jsの
function getFromClient(req,res){…}
の部分です
このreqの部分にURLが入っています
それをURLモジュールでパース処理しています
var url_parts = url.parse(req.url); その内容をオブジェクト型の配列で変数に格納しています
パス名によって分岐をしますので
switch(url_parts.pathname){分岐処理}
switchを使い条件分岐をしています
パス名によってレンダリングするファイルを変更しています
CSSファイルもこうすることで読み込まれて反映されています
実は、この処理をしないとCSSファイルをリンクさせてもアクセスしないので、CSSは反映されません
今回はURLモジュールを使ったルーティングの基礎を勉強しました
YouTubeもよろしくお願いします!
※url.parseは非推奨とでると思います。現在はWHATWG URL APIを使用するようにと表示されていましたのでそのコードもサンプルとしてここに置いておきます。よかったら参考にしてください。
const http = require('http'); | |
const fs = require('fs'); | |
const ejs = require('ejs'); | |
const moment = require('moment'); | |
moment.locale('ja'); | |
let datetoday = moment().format('LL'); | |
const index = fs.readFileSync('./index.ejs','utf8'); | |
const sample = fs.readFileSync('./sample.ejs','utf8'); | |
const style_css =fs.readFileSync('./style.css','utf8'); | |
var server = http.createServer(getFromClient); | |
server.listen(3000); | |
console.log('Server start!'); | |
console.log(datetoday); | |
function getFromClient(req,res){ | |
var url_parts = new URL(req.url,'http://localhost:3000'); | |
console.log(url_parts) | |
switch(url_parts.pathname){ | |
case '/': | |
var content = ejs.render(index,{ | |
title:'Kikuchannel', | |
today:datetoday, | |
}); | |
res.writeHead(200, {'Content-Type':'text/html'}); | |
res.write(content); | |
res.end(); | |
break; | |
case '/sample': | |
var content = ejs.render(sample,{ | |
title:'introduction', | |
today:datetoday, | |
}); | |
res.writeHead(200, {'Content-Type':'text/html'}); | |
res.write(content); | |
res.end(); | |
break; | |
case '/style.css': | |
res.writeHead(200, {'Content-Type':'text/css'}); | |
res.write(style_css); | |
res.end(); | |
break; | |
default: | |
res.writeHead(404, {'Content-Type':'text/plain'}); | |
res.end('no page...'); | |
break; | |
} | |
} |
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title><%=title%></title> | |
<link type="text/css" href="./style.css" rel="stylesheet"> | |
</head> | |
<body> | |
<header> | |
<h1><%=title%></h1> | |
</header> | |
<div role="main"> | |
<p>This is Kikuchannel.</p> | |
<p>こんにちは、今日は<%=today%>です。</br> 今日も一日がんばろう!</p> | |
</div> | |
</body> |
{ | |
"name": "samplecode", | |
"version": "1.0.0", | |
"description": "", | |
"main": "app.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"ejs": "^3.1.6", | |
"moment": "^2.29.1" | |
} | |
} |
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title><%=title%></title> | |
<link type="text/css" href="./style.css" rel="stylesheet"> | |
</head> | |
<body> | |
<header> | |
<h1><%=title%></h1> | |
</header> | |
<div role="main"> | |
<p>I'm Kiku.</p> | |
<p>こんにちは、今日は<%=today%>です。</br> 今日も一日がんばろう!</p> | |
</div> | |
</body> |
header h1 { | |
font-size: 60pt; | |
background-color: darkcyan; | |
color: #eee; | |
text-align: left; | |
margin: 50px; | |
} | |
body { | |
font-size: 14pt; | |
color: #999; | |
margin: 5px; | |
} |
動画も作りましたのでこちらもぜひ参考になさってください。
コメント
app.jsを実行してからブラウザに「loaclhost:3000」を入力して、下記の一つ目のUrlオブジェクトが表示されるのは理解できるのですが、二つ目のUrlオブジェクトが表示されるのはなぜでしょうか。
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: null,
pathname: ‘/’,
path: ‘/’,
href: ‘/’
}
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: null,
pathname: ‘/style.css’,
path: ‘/style.css’,
href: ‘/style.css’
}
こんばんは。
自分の書いているindex.ejsのコードを見ていただくと、7行目にlink type=”text/css” href=”./style.css” rel=”stylesheet”とあるんですが、ここでcssファイルを読み込んでいるから、/style.cssが二つ目のURLオブジェクトに表示されています。
要するに
①localhost:3000にアクセスする path”/”
②index.ejsがレンダリングされる
③style.cssが読み込まれる path”/style.css”
という流れです。
index.ejsのコードの7行目を消してみると2つ目のURLオブジェクトは読み込まれないため、ログには表れないはずです。よろしければ一度試してみてください(一応自分も確かめてみました笑)。
ご回答ありがとうございました。
という文で、どういう処理がおこなわれるのか具体的につかめました。
今後ともよろしくお願いいたします。
先ほどの文中で、下記の文を〈〉で囲ったら表示されなくなってしまったようです。
link type=”text/css” href=”./style.css” rel=”stylesheet”