パパッとは作れてないです。
はじめに
Express(JavaScriptベースのサーバサイドフレームワーク)に入門したくなったので、簡単なブログを作ってみます。Node.jsとnpmはインストールされている前提で進めていくので、インストールされてない方は公式サイト でインストールしてください。
なお、完成版のソースコードは、GitHubに置いています。
github.com
バージョン情報
npm: 5.6.0
Node.js: 8.11.3
Express: 4.16.0
エディタは Visual Studio Code を使用
1.アプリのひな形を作る
Expressアプリケーションのひな形を作成してくれるライブラリであるExpress Generator を使って、アプリの基本部分を作成していきます。
# Express Generatorをグローバルインストール
npm i -g express-generator
Express Generator のインストールが完了したら、下記のコマンドでアプリを作成します。
# ex-blogのところには、アプリ名を入れてください
express -e ex-blog
-e
というオプションがついていますが、これは「テンプレートエンジンにEJSを使用する」という意味です。-e
を省略すると、テンプレートエンジンにJadeが採用された状態でアプリケーションが作成されます。
下記コマンドを実行すると、アプリが起動するので、ブラウザを立ち上げて、http://localhost:3000/
を入力してください。「Express」とブラウザに表示されれば、雛形の作成は完了です。
cd ex-blog
npm i
# アプリ起動
npm start
2. SQLiteのインストール
データベースについては、環境構築とか設定が楽そうなのでSQLiteを使います。公式サイト に行って環境(OSとかの)にあったやつをダウンロードしてください。
3. SQLiteのGUIツールもインストール
GUIツールもついでに落としましょう。OSにあったインストーラをダウンロードしてください。DB Browser for SQLite
4. データベースを設計する
DB Browser for SQLite を起動して「New Database」ボタンをクリックすると、データベースファイルの保存ダイアログが現れるので、mydb.sqlite3
という名称で、ex-blog
フォルダの配下に新規作成してください。
データベースファイルを作成したら、投稿したブログを保存する用のテーブルを作成しましょう。設定については、下記の画像を参考にしてください。テーブル名をpost
に設定しています。
上記の画像では、id
のTypeをINTEGER
に設定して右側に見えるチェックボックスをすべてONにしていますが、こうすることでid
がオートインクリメントの主キーになります。
注意点ですが、テーブルの作成に限らず、データベースの設定が終わったら「Write Changes」ボタンを押すのを忘れないようにしてください。押さないと変更が適用されません。
最後にターミナルでアプリケーションフォルダ(ex-blog
)をカレントディレクトリに設定して、SQLite3モジュールをインストールすると、ExpressからSQLiteにアクセスする準備が完了します。
npm i sqlite3
5.コードを書く
Express Generator が作成した雛形のプログラムファイル・テンプレートファイルを更新して、ブログを作っていきます。
5-1. 記事の投稿画面を作る
まず、views/write.ejs
ファイルを新規作成して、下記のように記入してください。このテンプレートファイルは、記事投稿画面として使用されます。
views/write.ejs
< html >
< head >
< title > Express Blog</ title >
< link rel = 'stylesheet' href = '/stylesheets/style.css' />
</ head >
< body >
< h1 > 新しい記事を投稿</ h1 >
< form action = "/write" method = "POST" >
< table >
< tr >
< th > Title</ th >
< td >
< input type = "text" class = "title-input" name = "title" />
</ td >
</ tr >
< tr >
< th > Content</ th >
< td >
< textarea name = "content" ></ textarea >
</ td >
</ tr >
< tr >
< th ></ th >
< td >
< button type = "submit" > 投稿</ button >
</ td >
</ tr >
</ table >
</ form >
</ body >
</ html >
続いて、記事投稿画面のルーティングスクリプト(投稿画面に遷移した時の処理)を作成していきます。routes/write.js
ファイルを新規作成してください。
routes/write.js
var express = require('express' );
var router = express.Router();
var sqlite3 = require('sqlite3' );
var db = new sqlite3.Database('mydb.sqlite3' );
router.get('/' , (req, res, next) => res.render('write' ));
router.post('/' , (req, res, next) => {
const title = req.body.title;
const content = req.body.content;
const createdtime = new Date ();
db.run(
'insert into post (title, content, createdtime) values (?, ?, ?)' ,
title,
content,
createdtime
);
res.redirect('/' );
} );
module.exports = router;
記事投稿画面へのルーティングを追加するために、app.js
にも修正を加えます。(add this!とコメントされている部分を追加すればOKです。)
app.js
var createError = require('http-errors' );
var express = require('express' );
var path = require('path' );
var cookieParser = require('cookie-parser' );
var logger = require('morgan' );
var indexRouter = require('./routes/index' );
var writeRouter = require('./routes/write' );
var app = express();
app.set('views' , path.join(__dirname, 'views' ));
app.set('view engine' , 'ejs' );
app.use(logger('dev' ));
app.use(express.json());
app.use(express.urlencoded({ extended: false } ));
app.use(cookieParser());
app.use(express.static (path.join(__dirname, 'public' )));
app.use('/' , indexRouter);
app.use('/write' , writeRouter);
app.use(function (req, res, next) {
next(createError(404));
} );
app.use(function (err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env' ) === 'development' ? err : {} ;
res.status (err.status || 500);
res.render('error' );
} );
module.exports = app;
レイアウトもテキトーに整えましょう
public/stylesheets/style.css
body {
padding : 50px ;
font : 14px "Lucida Grande" , Helvetica , Arial , sans-serif ;
}
a {
color : #00B7FF ;
}
input [ type = "text" ],
textarea {
width : 400px ;
padding : 0.8em ;
outline : none ;
border : 1px solid #DDD ;
border-radius : 3px ;
border-radius : 3px ;
border-radius : 3px ;
font-size : 16px ;
}
textarea {
width : 600px ;
height : 200px ;
}
input [ type = "text" ] :focus ,
textarea :focus {
box-shadow : 0 0 7px #3498db ;
border : 1px solid #3498db ;
}
button {
border :solid 1px #ccc ;
padding :15px 30px ;
margin : 20px 0 ;
font-family :Arial , sans-serif ;
font-size :1.2em ;
text-transform :uppercase ;
font-weight :bold ;
color :#333 ;
cursor :pointer ;
}
この段階で、npm run start
コマンドでアプリを起動した後に、http://localhost:3000/write
にブラウザでアクセスすると、こんな感じの画面が表示されるはずです。
記事投稿画面
5-2. 記事の閲覧画面(ホーム画面)を作る
続いて、投稿した記事を閲覧する画面の方も作っていきましょう。テンプレートファイルのviews/index.ejs
を下記のように書き換えてください。
views/index.ejs
< html >
< head >
< title > Express Blog</ title >
< link rel = 'stylesheet' href = '/stylesheets/style.css' />
</ head >
< body >
< h1 > Express Blog</ h1 >
< a href = "/write" > Write </ a >
<% for (var i= 0; i < posts.length; i++) {%>
< h2 ><%= posts[i].title% ></ h2 >
< p ><%- posts[i]. content %></ p >
<% } %>
</ body >
</ html >
ポイントとしては、posts[i].content
の部分で、改行タグ<br>
を出力するために<%= %>
ではなく、エスケープなしで展開してくれる<%- %>
を使っている部分に若干注意が必要です。
< h2 ><%= posts[i].title% ></ h2 >
< p ><%- posts[i]. content %></ p >
記事閲覧画面のルーティングスクリプトも書き換えます。DBからの記事一覧取得と改行コードを改行タグ<br>
に変換する処理を行なっています。
routes/index.js
var express = require('express' );
var router = express.Router();
var sqlite3 = require('sqlite3' );
var db = new sqlite3.Database('mydb.sqlite3' );
router.get('/' , (req, res, next) => {
db.serialize(() => {
db.all('select * from post' , (err, rows) => {
if (!err && rows) {
const newRows = rows.map(row => {
if (row.content) {
row.content = row.content.replace(/\r?\n/g , '<br>' );
}
return row;
} );
console.log(newRows);
res.render('index' , { posts: newRows } );
}
} );
} );
} );
module.exports = router;
6.動作確認
これでいったん完成です。npm run start
コマンドの後にブラウザでhttp://localhost:3000/
下記のような、ブログのホーム画面が表示されるはずです。
ホーム画面
記事の投稿画面から記事を投稿して、ホーム画面に記事が表示されるかなども確認してみてください。
つまづいたところ
アプリから、DBのpost
テーブルを呼び出す処理でno such table
みたいなエラーが出まくる
テーブルを作った後に、DB Browser for SQLiteでWrite Change
ボタンを押しておらず、変更が適用されていなかったのが原因だった