Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9360

【node.js + express + mongodb】記事管理アプリを作ってみた

$
0
0
概要 記事を投稿、管理できるアプリを作成した。機能としては、アカウント登録、ログイン機能、記事作成&編集&削除機能がある。見た目は以下のようになる。 見た目 見た目は以下のようになる。 ログイン画面:bootstrap使用。 登録画面 記事リスト:ページ分け、編集削除 記事詳細:書式がそのまま保存 記事投稿:リーチテキストエディタ使用 ソースコード ソースコードをgithubにアップした。 https://github.com/akikisai/Article-management-app 使用したライブラリー 使用したものやバージョンは以下になる。 "cookie-parser": "~1.4.4", "debug": "~2.6.9", "ejs": "~2.6.1", "express": "~4.16.1", "express-session": "^1.17.2", "http-errors": "~1.6.3", "moment": "^2.29.1", "mongodb": "^4.4.0", "morgan": "~1.9.1" 環境構築 まず環境構築を行う。 node.js環境構築 以下のリンクからnode.js推奨版をダウンロードし、特に何も変更せずインストーラーの流れに沿ってインストールする。これでnpmコマンドが使えるようになる。 node.jsダウンロードサイト mongoDB環境構築 以下のリンクの内容に沿って環境構築する。 mongoDB環境構築 mongoコマンドを打ってmongo shellが現れれば成功。 プロジェクト作成 デスクトップ上にプロジェクトを作成したい。まずcdコマンドで移動し、アプリケーションを素早く作成できるようにするためexpressをインストールする。 $ cd Desktop $ npm install express-generator -g textappというプロジェクトを作成する。この時デスクトップにtextappフォルダーが作られる。 その後textappフォルダーな中に入り、npm installで初期のパッケージを使用できるようにインストールする。 $ express -e textapp $ cd textapp $ npm install ※テキストエディタを使うが、ない場合visual studio codeもしくはatomが推奨。 visual studio code公式ページ Atom公式ページ Node.jsでは、変更を有効にするためにプロセスを再起動する必要があるが、nodemonを使用してプロセスを自動的に再起動するので、余分な手順を排除る。これをインストールする。 $ npm install nodemon -g package.jsonファイル内の"start": "node ./bin/www"を以下のように変更し、これでnodemonに対応できる。 "start": "nodemon ./bin/www" npm startでプロジェクト起動する。 $ npm start ファイル内にポートが3000と設定されていることがわかり、 binファイル > wwwファイル > var port = normalizePort(process.env.PORT || '3000'); ウェブサイトに以下のリンクを入力すると、 http://localhost:3000/ welcome to expressが表示される。 ここで注意したいのが、次の作業に当たり、npm startを入力したターミナルは閉じないこと。 mongoDBと接続 mongoDBの環境構築は済んでいて、ここでは新しいgit bashを開き、以下のコマンドでデータベース保存場所を決める。この場合C:\mongodb\dataに保存している。 $ mongod --dbpath "C:\mongodb\data" mongoDBと接続するためには、npm startを入力したシェルと、mongoコマンドを打って出てきたmongoシェルが同時に存在しなければならない。mongoコマンドを打って出てきたmongoシェルがあるということはmongoDBに接続成功。なお、ターミナルにおいてmongoシェルにうまく入力できない場合、windowsのコマンドプロンプトでも大丈夫。 $ mongo mongoDBとつなぎ、shell を使えるようになる。 データベースの中身を確認 >show dbs デフォルトはお以下のようになる。 admin 0.000GB config 0.000GB local 0.000GB textappというデータベース作成 use textapp userコレクションを作る。 db.createCollection('users'); コレクションを表示する。 show collections 正しく表示される。 mongoDBコマンド参考用 nodejsとmongodbを接続するために、mongodb nodejs driverを使う。 ※ほかにもMongooseを使用する方法がある、こっちのほうが人気らしい。 インストール含め使い方はmongodb nodejs driverドキュメント参照。 cd textappでtextappフォルダ内でmongodb nodejs driverをインストールする。 npm install mongodb --save ドキュメントの例を参考にし、mongodbに接続するコードを書く。ファイルの新規作成などの細かい手順は全部省略する(githubソースコードを見ればわかるので)この記事では主に機能についてまとめたい。 model/index.js var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://localhost:27017/textapp'; var dbName = 'textapp'; //データベースへ接続用関数 function connect(callback) {//関数化 MongoClient.connect(url, function(err, client) {//コールバック関数 //エラーの場合 if (err) { console.log('データベース接続エラー', err); //エラーじゃない場合 } else { //接続成功 var db = client.db(dbName); callback && callback(db); } }); } module.exports = { connect } 接続する機能を関数化し、あとで使えるようにする。 登録&ログイン ルーティング設定をする。 routes/index.js // 登録ページ router.get('/regist', function(req, res, next) { res.render('regist', {}) }); // ログインページ router.get('/login', function(req, res, next) { res.render('login', {}) }); 登録ページのコードは以下になる。 views/login.ejs <body> <div class="container"> <div class="login-container"> <div class="form-box"> <form action="/users/regist" method="post"> <input type="text" name="username" value="" placeholder="ユーザ名"> <input type="password" name="password" value="" placeholder="パスワード"> <button class="btn btn-info btn-block login" type="submit">登録する</button> </form> <div>アカウントをお持ちの場合、<br><a href="/login">ログイン</a>してください。</div> </div> </div> </div> </body> これにより、ユーザ名とパスワードは"/users/regist"へ送信される。 routes/users.js // 登録 router.post('/regist', function(req, res, next) { var data = { username: req.body.username, password: req.body.password }; // データの接続 model.connect(function(db) { //コレクションusersにデータ挿入する db.collection('users').insertOne(data, function(err, ret) { //登録失敗 if (err) { console.log('登録失敗'); res.redirect('/regist'); } else { //登録成功、ログインページへ res.redirect('/login'); } }); }) }) 送信されてきた情報はdataに格納され、データベースに接続し、照らし合わせることで登録成功か失敗か。ちなみにmongoDBインストール時、MongoDB compassをインストールしていれば、それを開いて、connectを押すことでmongoDBへ接続でき、GUI画面で登録された情報は実際あるのかを確認できる。mongoDB compass参考 ログインページのコードは以下のようになる。 views/login.ejs <body> <div class="container"> <div class="login-container"> <div class="form-box"> <form action="/users/login" method="post"> <input name="username" type="text" placeholder="ユーザ名"> <input name="password" type="password" placeholder="パスワード"> <button class="btn btn-info btn-block login" type="submit">ログイン</button> </form> <div>アカウントをお持ちでない場合、<a href="/regist">作成</a>できます。</div> </div> </div> </div> </body> これにより、ユーザ名とパスワードは"/users/login"へ送信される。 routes/users.js // ログイン router.post('/login', function(req, res, next) { var data = { username: req.body.username, password: req.body.password } //データベースに接続する。 model.connect(function(db) { //コレクションに同じデータがあるか、あればログイン成功。 db.collection('users').find(data).toArray(function(err, docs) { if (err) { //ログイン失敗→もう一回ログインページへ res.redirect('/login'); }else { //調べたdocsの結果が0以上であれば成功 if (docs.length > 0) { // ログイン成功 session保存 req.session.username = data.username;//ユーザーネームをセッションに保存 res.redirect('/'); } else { res.redirect('/login'); } } }) }) }) 送信されてきた情報はdataに格納され、データベースに接続し、照らし合わせることでログイン成功か失敗か。失敗したらもう一度ログインページへ行く。また、上のコードでsessionを使用している。これはログイン状態を保存するため(毎回ログインするのはめんどくさいので) sessionを使うためまずexpress-sessionをインストールする。textappフォルダ内で以下のコマンドを実行する。使い方はexpress-sessionドキュメント参照。 $ npm install express-session -S 最初に設定をする。 app.js var session = require('express-session'); //セッション app.use(session({ secret: 'sai textapp',//何でもよい resave: false, saveUninitialized: true, cookie: { maxAge: 1000 * 60 * 20 } //cookie有効時間=ログイン有効期間 })) ここでのログイン有効期間を20分とした。また上のログインが成功した場合ユーザ名をsessionに格納される。もしsessionにユーザ名がある場合、ログインせずにホームぺーズへ飛ぶことができるようになる。ユーザ名がニア場合、かつログインページと登録ページ以外ならば、ログインページへ戻る。これでログインしていない状態だとホームページは見れない。 app.js // sessionの中身判定 app.get('*', function(req, res, next) { var username = req.session.username; //パスを判断したいので宣言 var path = req.path; //ログインページと登録ページ以外で、ユーザ名なければログインページへ飛ぶ。 if (path != '/login' && path != '/regist') { if (!username) { res.redirect('/login'); } } next(); }) ログアウト ヘッダーに投稿ボタンとログアウトボタンを配置する。 views/bar.ejs <li class="header_navi_item"><a href="/users/logout"><span>ログアウト</span></a></li> ログアウトするには簡単で、sessionの中身を空っぽにしてlogin画面へ飛べばよい。 routes/users.js //ログアウト router.get('/logout',function(req,res,next){ req.session.username = null; res.redirect('/login'); }) 記事投稿 ホームページに投稿するボタンを用意する。投稿画面/writeへ飛ぶ。 views/index.ejs <li class="header_navi_item"><a href="/write"><span>投稿する</span></a></li> write画面を作っていく。 views/write.ejs <body> <%- include('bar', {username: username}) %> <div class="article"> <form action="/article/add" method="post"> <input type="text" name="title" placeholder="タイトル" value=""> <textarea name="content" class="xheditor" id="mytextarea"></textarea> <input type="submit" value="投稿"> </form> </div> </body> なお、ここでのbarはbar.ejsで、ヘッダーを作ります。ヘッダーは数画面同じものを使うので便利さを求めて別々にbar.ejsとして作り、includeによって呼び出して使う。この場合usernameを求めているので、routes/index.ejsの router.get('/write', function(req, res, next) {})の中身にはusernameを取得しusernameを返す必要がある。そうするとusernameがbar(ヘッダー)のユーザ名のところに格納し、一番上の見た目のようにユーザ名が表示される。 ここで、投稿するためにリッチテキストエディターを実装したい。 リッチテキストエディタとは、HTMLを知らなくても文字、画像、表などをツールボタンを使って作成・編集することができるもの。実際にコピーしたものを投稿内容欄に張り付けても書式が残る。 今回使用するのはTinyMCEというもの。公式ページの始め方参照はこちら やや古いですがとても分かりやすいTinyMCE使い方記事はこちら なお、ほかのリーチテキストエディタを使いたい場合、リッチテキストエディタ一覧を参考して、各自調べてください。 ドキュメント通りにコードを書く。バージョン古くなるかもしれないので必ずドキュメント参照推奨。ドキュメントのやり方だと、 <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> http://から始まって直接読み込むことができるので便利ですが、今回はTinyMCEを直接ダウンロードページからDownlord TinyMCE SDK nowをクリックし、ダウンロードして解凍して中身のファイルをtextapp/public/javascriptsの中にいれ、リンクは代わりにtinymce.min.jsを適切なパスで読み込む。今回の例では javascripts/tinymce_5.10.3/tinymce/js/tinymce/ の中に存在する。 write.jsのheadタグ内をいじる。2つのscriptタグを追加した。 views/write.ejs <head> <title>記事作成</title> <%- include head %> <script src="javascripts/tinymce_5.10.3/tinymce/js/tinymce/tinymce.min.js" referrerpolicy="origin"></script> <script> tinymce.init({ selector: 'textarea', language: 'ja' }); </script> </head> 言語を日本語化にしたいので、TinyMCE言語パッケージページからjaを見つけ、ダウンロードする。解凍したlangsフォルダの「ja.js」を「tinymce/」にある「langsフォルダ」へ移動する。 うえのようにlanguage: 'ja'と記入すれば完成。 記事投稿するので、データベースに新しいコレクションを追加。 mongo shellで以下のコマンドを入力し、articlesコレクションを作る。 use textapp db.createCollection('articles'); 次は実際に記事書いたら、記事を投稿する機能を持つボタンを作る。ここで入力内容はformの/article/addへ行く。ということで作成していく。 routes/article.js // 追加 router.post('/add', function(req, res, next) { //データを受け取る var data = { title: req.body.title,//タイトル content: req.body.content,//記事内容 username: req.session.username,//ユーザ名 id: Date.now()//時間 //データベースに接続し、データを挿入する model.connect(function(db) { db.collection('articles').insertOne(data, function(err, ret) { if(err) { console.log('文件发布失败', err) //失敗、もう一回記事投稿ページ res.redirect('/write') } else { //成功、ホームページへ res.redirect('/') } }) }) } }) 正しく入っているかどうか、Mongo shellで確認するか、MongoDB compassで確認する。 記事表示(ホームページ) まずroutes/index.jsの"/"へ飛ぶ時の処理を編集する。 時間を扱いたいので、gitbashでtextapp内においてmomentをインストール。 npm install moment -S 公式ドキュメントはこちら routes/index.js /* ホームページ*/ router.get('/', function(req, res, next) { var username = req.session.username; //データベース接続 model.connect(function(db) { // すべての記事を調べる。 db.collection('articles').find().toArray(function(err, docs) { var list = docs; //ここでマップを使って、時間を表しているidを日付形式に変換し、timeと名付ける。  list.map(function(ele, index) { ele['time'] = moment(ele.id).format('YYYY-MM-DD HH:mm:ss') res.render('index', { username: username, data: list }); }) }) }); 次に記事表示画面を作る。取得されたitemの中に必要な情報が入っている。 views/index.ejs <% list.map(function(item,index){ %> <div class="row"> <span><%= index+1 %></span> <span><%= item.username %></span> <span><%= item.title %></span> <!-- 定義したtimeを使用している。--> <span><%= item.time %></span> <span> <a href="">編集</a> <a href="">削除</a> </span> </div> <% }) %> 記事リストページ分け 記事が多い場合、ページ分けして1ページに何個記事表示できるかを設定。 routes/index.jsやviews/index.jsを編集する。 routes/index.js /* ホームページ*/ router.get('/', function(req, res, next) { var username = req.session.username; //フロント側で今は何ページ目にいるかデータを受け取る、なければ1 var page = req.query.page || 1; var data = { total: 0,//トータル何ページ必要か curPage: page,//現在あるページ数 list:[]//今表示しているページの記事リスト } var pageSize = 2;//表示しているページに記事何個ひょうじするか model.connect(function(db) { // すべての記事を調べる。 db.collection('articles').find().toArray(function(err, docs) { //全部の記事数÷1ぺ時に表示する記事数=トータル何ページ必要か //Math.ceil() 関数は、引数として与えた数以上の最小の整数を返す data.total = Math.ceil(docs.length / pageSize) // 今のページの記事リストを調べる。 model.connect(function(db) { // sort() limit() skip() //降順で、一回に調べる記事数を限定(2)、スキップする個数(1ページ目なら(1-1)*2で0,スキップせず最初から2つ調べる) db.collection('articles').find().sort({_id: -1}).limit(pageSize).skip((page-1)*pageSize).toArray(function(err, docs2) { //時間変換 docs2.map(function(ele, index) { ele['time'] = moment(ele.id).format('YYYY-MM-DD HH:mm:ss') }) data.list = docs2 res.render('index', { username: username, data: data }); }) }) }) }) }); 記事を分ける際、必要な情報は、 total: トータルで何ページ必要か cuiPage: 現在あるページ数 (ここでは必要ないが後で削除機能のために使う) list: 今表示しているページの記事のリスト page: フロント側で今は何ページ目にいるかデータ pageSize: 1ページに表示したい記事数 であり、取得した記事数によって、 total =記事数÷pageSize(小数の場合大き目の整数に変換) views/index.js <body> <%- include('bar', {username}) %> <div class="list"> <!-- ページ分け、何ページ目 --> <div class="pages"> <% for(let i=1; i<=data.total; i++) { %> <!-- ここでクリックすると今いる何ページ目かが"/"にわたり、そのページ内容を表示したい--> <a class="pages_style" href="/?page=<%= i %>"><%= i %></a> <% } %> </div> <div class="row"> <span>順番</span> <span>作者</span> <span>タイトル</span> <span>公開日</span> <span> <i class="fa-solid fa-pen-to-square"></i> </span> </div> <!-- 記事リスト --> <% data.list.map(function(item,index){ %> <div class="row"> <span><%= index+1 %></span> <span><%= item.username %></span> <span><%= item.title %></span> <span><%= item.time %></span> <span> <a href="">編集</a> <a href="">削除</a> </span> </div> <% }) %> </div> </body> for文でdata.totalを使用し、実際のページ数を表示。また、ページボタンに今のいるページ何番目かを意味するpageを"/"に渡しているので、この情報を使って表示すべき記事を選出し、data.listに格納される。 記事削除 views/index.jsの削除のところを下のように直す。 削除するために必要な情報は、記事のidはもちろん、もう1つは今何ページ目にいるかという、pageが必要。なお、?id=&page=のところ、 ?の後ろにはURLパラメータが来ていて、この値を行先に渡すイメージ。 views/index.js <a href="/article/delete?id=<%=item.id%>&page=<%=data.curPage%>">削除</a> routes/article.jsも編集。 routes/article.js // 記事削除 router.get('/delete', function(req, res, next) { var id = parseInt(req.query.id) var page = req.query.page //接続 model.connect(function(db) { //idで調べる db.collection('articles').deleteOne({id: id}, function(err, ret) { if (err) { console.log('削除失敗'); } else { console.log('削除成功'); } //リダイレクトする res.redirect('/?page='+page); }) }) }) なおこの状態では、たとえ削除したページに記事が1つもなくても、表示できるので、不適切である。これを直すため、routes/index.jsに判定条件を追加する。 routes/index.js /* ホームページ*/ router.get('/', function(req, res, next) { var username = req.session.username; //フロント側で今は何ページ目にいるかデータを受け取る、なければ1 var page = req.query.page || 1; var data = { total: 0,//トータル何ページ必要か curPage: page,//現在あるページ数 list:[]//今表示しているページの記事リスト } var pageSize = 2;//表示しているページに記事何個ひょうじするか model.connect(function(db) { // すべての記事を調べる。 db.collection('articles').find().toArray(function(err, docs) { //全部の記事数÷1ぺ時に表示する記事数=トータル何ページ必要か //Math.ceil() 関数は、引数として与えた数以上の最小の整数を返す data.total = Math.ceil(docs.length / pageSize) // 今のページの記事リストを調べる。 model.connect(function(db) { // sort() limit() skip() //降順で、一回に調べる記事数を限定(2)、スキップする個数(1ページ目なら(1-1)*2で0,スキップせず最初から2つ調べる) db.collection('articles').find().sort({_id: -1}).limit(pageSize).skip((page-1)*pageSize).toArray(function(err, docs2) { //記事がなければ if (docs2.length == 0) { //前のページに戻る、最小1 res.redirect('/?page='+((page-1) || 1)) } else { //記事があれば、時間の処理をする。 docs2.map(function(ele, index) { ele['time'] = moment(ele.id).format('YYYY-MM-DD HH:mm:ss') }) data.list = docs2 } res.render('index', { username: username, data: data }); }) }) }) }) }); 記事編集 writeへ飛ぶ。同じくidとcurPageが必要。 views/index.js <a href="/write?id=<%=item.id%>&page=<%=data.curPage%>">編集</a> router.get('/write', function(req, res, next) {})は以下のようになる。 routes/index.js // 投稿&編集ページ router.get('/write', function(req, res, next) { var username = req.session.username || '' var id = parseInt(req.query.id) var page = req.query.page var item = { title: '', content: '' } if (id) { // idがあれば編集 model.connect(function(db) { db.collection('articles').findOne({id: id} , function(err, docs) { if (err) { console.log('失败') } else { item = docs item['page'] = page res.render('write', {username: username, item: item}) } }) }) } else { // idがなければ追加 res.render('write', {username: username, item: item}) } }) また、write画面も編集する。 views/write.ejs <body> <%- include('bar', {username: username}) %> <div class="article"> <form action="/article/add" method="post"> <input type="hidden" name="id" value="<%- item.id %>"> <input type="hidden" name="page" value="<%- item.page %>"> <input type="text" name="title" placeholder="タイトル" value="<%= item.title %>"> <textarea name="content" class="xheditor" id="mytextarea"><%- item.content %></textarea> <% if (item.id) { %> <input type="submit" value="編集"> <%} else {%> <input type="submit" value="投稿"> <%}%> </form> </div> </body> ボタンもif文でidがあれば編集、なければ投稿と表示。 また、編集をするためにpageとidを渡さなければならない。 編集成功したらpageに飛びたいので。 <input type="hidden" name="id" value="<%- item.id %>"> <input type="hidden" name="page" value="<%- item.page %>"> hidenを使って見えなくし、配置する。 /article/addのところも編集する。同じくidで編集する。 routes/article.js // 追加、編集 router.post('/add', function(req, res, next) { var id = parseInt(req.body.id) if (id) { //編集 var page = req.body.page var title = req.body.title var content = req.body.content model.connect(function(db) { db.collection('articles').updateOne({id: id}, {$set: { title: title, content: content }}, function(err, ret) { if (err) { console.log('編集失敗', err) } else { console.log('編集成功') res.redirect('/?page='+page) } }) }) } else { //追加 var data = { title: req.body.title, content: req.body.content, username: req.session.username, id: Date.now() } model.connect(function(db) { db.collection('articles').insertOne(data, function(err, ret) { if(err) { console.log('失败', err) res.redirect('/write') } else { res.redirect('/') } }) }) } }) 記事表示 タイトルのところに行先を設定。 view/index.ejs <span><a href="/detail?id=<%=item.id%>"><%= item.title %></a></span> 記事表示ページを作成する。 view/detail.ejs <!DOCTYPE html> <html lang="ja"> <head> <title><%=item.title%></title> <%- include head %> </head> <body> <%- include('bar', {username: username}) %> <div class="detail"> <div class="title"><%=item.title%></div> <div class='desc'> <span>作者:<%=item.username%></span> <span>投稿日:<%=item.time%></span> </div> <div class="content"><%-item.content%></div> </div> </body> </html> routes/index.jsにもコードを追加する。 routes/index.js // 記事詳細ページ router.get('/detail', function(req, res, next) { var id = parseInt(req.query.id) var username = req.session.username || '' model.connect(function(db) { db.collection('articles').findOne({id: id}, function(err, docs) { if (err) { console.log('失败', err) } else { var item = docs item['time'] = moment(item.id).format('YYYY-MM-DD HH:mm:ss') res.render('detail', {item: item, username: username}) } }) }) }) これでタイトルを押したら、該当記事の詳細を確認できる。 その他 このままだと、実はほかの人でも他人の記事を編集&削除できる。これはまずいので、変えていく。やり方は簡単、以下のように修正すればいい。 views/index.ejs <!-- 記事リスト --> <% data.list.map(function(item,index){ %> <div class="row"> <span><%= index+1 %></span> <span><%= item.username %></span> <span><a href="/detail?id=<%=item.id%>"><%= item.title %></a></span> <span><%= item.time %></span> <span> <% if (item.username===username) { %> <a href="/write?id=<%=item.id%>&page=<%=data.curPage%>">編集</a> <a href="/article/delete?id=<%=item.id%>&page=<%=data.curPage%>">削除</a> <%} else {%> <span class="grey">編集</span> <span class="grey">編集</span> <%}%> </span> </div> <% }) %> ここではif文を使って判定している。usernameはsessionから取得した今ログイン中のユーザ名、item.usernameとはそれぞれの記事の作者名である。一致しなければ編集&削除ができない。 デプロイ(公開) まだ未公開ですが、EC2で公開したいと思っていて、以下の記事参考になりそうなのでいったんメモしておきます。 ec2 【AWS】EC2とは?概要から使い方までざっくり解説(実践あり) node.js [[AWS] 手順に沿った画像付きでAmazon EC2にNode.js, Express環境の構築する] チュートリアル: Amazon EC2 インスタンスでの Node.js のセットアップ AWS EC2でNodeを動作させる mongodb MongoDB CommunityEditionをAmazonLinuxにインストールします 途中までやっていた。コマンドメモ↓↓ $ ssh -i textapp-key.pem ec2-user@18.183.176.255 $ ssh -i textapp-key.pem ec2-user@18.183.176.255 $ sudo yum update $ sudo yum install git gcc-c++ make openssl-devel $ nvm install v16.14.0 $ nvm alias default v16.14.0 $ npm install express-generator -g npm WARN deprecated mkdirp@0.5.1: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) $ npm update -g mkdirp $ npm install -g npm@8.5.3 $ git clone https://github.com/akikisai/Article-management-app.git $ ls -a $ cd Article-management-app/ $ npm install $ grep ^NAME /etc/*release /etc/os-release:NAME="Amazon Linux" $ cd /etc/yum.repos.d $ sudo touch mongo-org-5.0.repo $ sudo su # vi mongo-org-5.0.repo [mongodb-org-5.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/5.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc :wq! # sudo yum install -y mongodb-org exclude=mongodb-org,mongodb-org-database,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools # ps --no-headers -o comm 1 systemd # sudo systemctl start mongod # sudo systemctl status mongod Active: active (running) since Sat 2022-03-05 12:30:03 UTC; 29s ago $ mongosh >use textapp >db.createCollection('users'); >db.createCollection('articles'); $ cd Article-management-app/ node ./bin/www 躓いた。。もう少しいろいろ試したい。 問題点 今回は機能を作ってみるだけにしましたが、まだしっかりとしたエラー処理を書いていなく(ユーザ名判定など) マークダウンにも対応させたいと思っていて、全然新しい機能を追加する余地はあるが、今回は一旦締め切りにする。

Viewing all articles
Browse latest Browse all 9360

Trending Articles