パパッとは作れてないです。
- はじめに
- バージョン情報
- 1.アプリのひな形を作る
- 2. SQLiteのインストール
- 3. SQLiteのGUIツールもインストール
- 4. データベースを設計する
- 5.コードを書く
- 6.動作確認
- つまづいたところ
はじめに
Express(JavaScriptベースのサーバサイドフレームワーク)に入門したくなったので、簡単なブログを作ってみます。Node.jsとnpmはインストールされている前提で進めていくので、インストールされてない方は公式サイトでインストールしてください。
なお、完成版のソースコードは、GitHubに置いています。
バージョン情報
- 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
<!DOCTYPE html> <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(); // sqlite3モジュールのインポート var sqlite3 = require('sqlite3'); var db = new sqlite3.Database('mydb.sqlite3'); // /write にgetメソッドでリクエストすると、write.ejsをレンダリング router.get('/', (req, res, next) => res.render('write')); // /write にpostメソッドでリクエストした時の処理 router.post('/', (req, res, next) => { // 投稿画面のフォームからタイトルと本文を取得 const title = req.body.title; const content = req.body.content; // 投稿日付を取得 const createdtime = new Date(); // 投稿記事をDBにinsertする db.run( 'insert into post (title, content, createdtime) values (?, ?, ?)', title, content, createdtime ); // ホーム画面(index.ejs)にリダイレクト 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'); // add this! // write.jsのロード var writeRouter = require('./routes/write'); var app = express(); // view engine setup 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); // add this! // アドレスの割当 app.use('/write', writeRouter); // catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page 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; -webkit-border-radius: 3px; -moz-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
<!DOCTYPE html> <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'); /* GET home page. */ router.get('/', (req, res, next) => { db.serialize(() => { // DBから投稿されたブログをすべて取得 db.all('select * from post', (err, rows) => { if (!err && rows) { // 改行コードを<br>に変換 const newRows = rows.map(row => { if (row.content) { row.content = row.content.replace(/\r?\n/g, '<br>'); } return row; }); console.log(newRows); // postsパラメータを渡した状態で、index.ejsをレンダリング 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
ボタンを押しておらず、変更が適用されていなかったのが原因だった
- テーブルを作った後に、DB Browser for SQLiteで