Node.js 學習日記--番外 No.2 隱藏設定與資料( .env )

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。

dotenv - 環境變數設定

這篇使用 No.1 文章的文件載點, dotenv 需要安裝這套件,但文件的 package 已經有資訊了, 到時候需要使用 .env 的環境變數這環境變數在 node.js 上已經有內建了。

  1. 在 contact.js 上面開起套件新增一個套件

    1
    2
    3
    4
    5
    6
    7
    var express = require('express');
    var router = express.Router();
    var csrf = require('csurf');
    var csrfProtection = csrf({ cookie: true });
    var nodeemailer = require('nodemailer');
    //新增 dotenv
    require('dotenv').config();
  2. 在根目錄也就是 email_init 資料夾下面新增一個 .env 檔案,沒有檔名只有副檔名,依照下面這樣寫入

    1
    2
    gmailUser = 自己的Email
    gmailPass = 自己的Email密碼
  3. 在 contact.js 修改一段成下列程式碼

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    router.post('/post', csrfProtection, function(req, res) {
    var transport = nodeemailer.createTransport({
    service:'Gmail',
    //寄件者是誰
    auth:{
    //因為這個資料是機密所以不被他人看到所以抓取.env的內容
    user: process.env.gmailUser,
    pass: process.env.gmailPass
    }
    });
  4. 像 .env 檔案並不會上傳到 github 之類的網站,這些網站都會有一個類似 env 的機制, HEROKU 就有一個機制可以保密機密資料。
    六角學院擁有


connect-flash - 資料暫存設計

如何比對使用者填寫表單資料格式是否正確,一樣 如果沒有有安裝請先安裝,這邊提供 package 檔案裡有 connect-flash 資訊了。

  1. 請先開啟 app.js 檔案並且開啟2個套件且加入一些程式碼,沒有寫上去的資料都不用去動。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var flash = require('connect-flash');
    var session = require('express-session');
    //
    app.use(session({
    secret: 'mysuoercat',
    resave: true,
    saveUninitialized: true
    }));
    app.use(flash());
  2. 開啟 contact.js 新增,新增的內容都寫在註解下面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    router.get('/', csrfProtection, function(req, res) {
    res.render('contact',{
    csrfToken: req.csrfToken() ,
    //設定一個名為 errors 的資料,下面會設定處發後你鍊帶入什麼資訊
    errors: req.flash('errors')
    });
    });
    router.get('/review', function(req, res) {
    res.render('contactReview');
    });
    router.post('/post', csrfProtection, function(req, res) {
    //下判斷
    if(req.body.username == ''){
    //如果 username 欄位空值那就會跑出一個 errors 的變數並帶入資料
    req.flash('errors','姓名不能為空');
    //之後並轉址到 /contact
    return res.redirect('/contact');
    };
    var transport = nodeemailer.createTransport({
    service:'Gmail',
    auth:{
    user:process.env.gmailUser,
    pass:process.env.gmailPass
    }
    });
    var mailoptions = {
    form:'"我是帥哥"<liuconing@gmail.com>',
    to : 'pp840405@gmail.com',
    subject: req.body.username + '寄了一封信',
    text: req.body.description
    };
    transport.sendMail(mailoptions,function(error,info){
    if(error){
    return console.log(error);
    }
    res.redirect('review');
    });
    });
  3. 判斷有下好之後網頁並不會顯示 errors 裡面得資料,所以也要到 contact.ejs 去新增。

    1
    2
    3
    4
    5
    6
    <h1>聯絡我們</h1>
    <%= errors %>
    <div>
    <label for="username">姓  名:</label>
    <input type="text" name="username" id="username"/>
    </div>

這套件是建立一個暫存資料的區域,只會占用極小部分記憶體一旦網頁再度重新整理這段資料就會消失,除非在觸發它的程式才會再度啟動。

結語

基本上 node.js 的一些基礎就到這邊,如果有學到其他東西我會視情況在這分享,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 學習日記--番外 No.1 電子郵件發送功能

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。

電子郵件發送功能實作

請下載範例檔案然後安裝 package 資訊裡面的套件。
然後把自己的 Gmail 設定允許低安全性應用程式
接下來會使用到 nodemailer 已經放到 package 資訊裡面了。

接下來打開 routes 裡面的 contact.js 檔案作資料寫入

  1. 載入 nodemailer 模組
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    var express = require('express');
    var router = express.Router();
    var nodeemailer = require('nodemailer')
    router.get('/', function(req, res) {
    res.render('contact');
    });
    router.get('/review', function(req, res) {
    res.render('contactReview');
    });
    router.post('/post', function(req, res) {
    var transport = nodeemailer.createTransport({
    //使用哪種電子郵件
    service:'Gmail',
    //由誰寄件資訊
    auth:{
    user:'設定自己email',
    pass:'自己email密碼'
    }
    });
    //發信內容
    var mailoptions = {
    //寄件者是誰(這邊設定自己)
    form:'"我是帥哥"<liuconing@gmail.com>',
    //收件者的信箱(可多個)
    to : 'pp840405@gmail.com',
    //信 標題
    subject: req.body.username + '寄了一封信',
    //信 內容
    text: req.body.description
    };
    transport.sendMail(mailoptions,function(error,info){
    if(error){
    return console.log(error);
    }
    res.redirect('review');
    });
    });
    module.exports = router;

CSURF - 阻擋跨站攻擊

CSRF
需要建立一個組檔機制以免 Server 會被攻擊,需要用到 csurf ,在 express 產生器內鍵就有件置這個套件了,後面範例可用 postman 來去模擬攻擊有沒有成功阻擋。

csurf官網

  1. 打開 contact.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    var express = require('express');
    var router = express.Router();
    var csrf = require('csurf');
    //需要載入的模組與開起參數
    var csrfProtection = csrf({ cookie: true });
    var nodeemailer = require('nodemailer')
    //依照官網要帶的參數 csrfProtection
    router.get('/', csrfProtection, function(req, res) {
    //依照官網要帶的參數 { csrfToken: req.csrfToken() }
    res.render('contact',{ csrfToken: req.csrfToken() });
    });
    router.get('/review', function(req, res) {
    res.render('contactReview');
    });
    //依照官網要帶的參數 csrfProtection
    router.post('/post', csrfProtection, function(req, res) {
    var transport = nodeemailer.createTransport({
    service:'Gmail',
    auth:{
    user:'設定自己email',
    pass:'自己email密碼'
    }
    });
    var mailoptions = {
    form:'"我是帥哥"<liuconing@gmail.com>',
    to : 'pp840405@gmail.com',
    subject: req.body.username + '寄了一封信',
    text: req.body.description
    };
    transport.sendMail(mailoptions,function(error,info){
    if(error){
    return console.log(error);
    }
    res.redirect('review');
    });
    });
    module.exports = router;
  2. contact.ejs 也需要帶入參數在 form 表單,下面完成後可以使用 postman 帶入 KEY 與 Value 值去 POST 資料看看能否傳送。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <form action="/contact/post" method="post">
    <input type="hidden" name="_csrf" value="<%= csrfToken %>">
    <h1>聯絡我們</h1>
    <div>
    <label for="username">姓  名:</label>
    <input type="text" name="username" id="username"/>
    </div>
    <div>
    <label for="email">電子郵件:</label>
    <input type="text" name="email" id="email"/>
    </div>
    <div>
    <label for="title">標  題:</label>
    <input type="text" name="title" id="title"/>
    </div>
    <div>
    <label for="description">訊息內容:</label>
    <textarea name="description" id="description" cols="30" rows="10"></textarea>
    </div>
    <div>
    <input type="submit" value="送出訊息" />
    </div>
    </form>

結語

已經懶的打這是啥第一天之類的了www
有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第三十天

Node.js 學習第三十天

第….第三十天,學!!!

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


session 講解

六角學院
六角學院擁有
六角學院擁有


session 開發環境設計

需要用到 session 的套件,先去安裝 express-session

1
npm install express-session

六角學院擁有

  1. 安裝好之後在 mycookie 資料夾的 app.js 啟用套件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    var express = require('express');
    var path = require('path');
    var favicon = require('serve-favicon');
    var logger = require('morgan');
    var cookieParser = require('cookie-parser');
    var bodyParser = require('body-parser');
    //啟用套件
    var session = require('express-session')
    var index = require('./routes/index');
    var users = require('./routes/users');
    var app = express();
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'ejs');
    app.use(logger('dev'));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cookieParser());
    app.use(express.static(path.join(__dirname, 'public')));
    //建立一個session
    app.use(session({
    secret: 'keyboard cat',
    resave: true,
    saveUninitialized: true
    }));
    app.use('/', index);
    app.use('/users', users);

    app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
    });

    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;

session 寫入資料

  1. 這邊在 index.js 寫死的資料
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var express = require('express');
    var router = express.Router();

    /* GET home page. */
    router.get('/', function(req, res, next) {
    //session
    console.log(req.session);
    req.session.userneme = "tom"
    req.session.email = "email"
    //cookies
    console.log(req.cookies);
    res.cookie('name','tom',{
    maxAge:10000,
    httpOnly:true
    })
    res.render('index', { title: 'Express' });
    });

    module.exports = router;

session 結合 from post 設計

下面程式碼可以在每個使用者登入帳號與密碼可以記錄到個人資料並不會被個人記錄可以使用兩個視窗去測試金鑰。

  1. 寫 ejs 接收資料設定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!DOCTYPE html>
    <html>
    <head>

    <link rel='stylesheet' href='/stylesheets/style.css' />
    </head>
    <body>
    <h1><%= userName %> <%= email %></h1>
    <form method="post" action="/">
    <input type="text" name="username" value="">
    <input type="text" name="email" value="">
    <input type="submit" value="送出">
    </form>
    </body>
    </html>
  2. 寫記錄表單邏輯

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var express = require('express');
    var router = express.Router();

    /* GET home page. */
    router.get('/', function(req, res, next) {
    res.render('index', {
    //傳送資料到 index.ejs 上
    userName: req.session.username,
    email: req.session.email
    });
    });
    router.post('/',function(req,res){
    req.session.username = req.body.username;
    req.session.email = req.body.email;
    //轉址到首頁
    res.redirect('/');
    })

    module.exports = router;

六角學院
由六角學院校長所整理

結語

已經寫了 30 天,那我就不用繼續按照規矩去寫了,有可能會寫其它資訊了也有可能啥都不寫吧(?),不過既然都要寫了或多或少都會寫一些,,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十九天

Node.js 學習第二十九天

到這最後幾天,看了一下課程表就知道一定會超過 30 天了,管它的繼續寫我打算 Node.js 了解後去找看看爬蟲的文章來學習。

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


Cookie

以下圖片由六角學院擁有
六角學院擁有1
六角學院擁有2

用 Google Chrome 去測試圖片中的範例程式碼
示範


接收前端的 Cookie 資料

  1. 首先使用 express-generator 套件建立一個 express 環境

    1
    2
    3
    4
    安裝 express 有 EJS 環境的資料夾
    express -e mycookie
    進入並安裝 package 內建的套件參數
    cd mycookie && npm install
  2. 到 index.js 去新增資料

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var express = require('express');
    var router = express.Router();
    /* GET home page. */
    router.get('/', function(req, res, next) {
    //撈到網頁的cookie資料
    console.log(req.cookies);
    //傳送cookie到前端資料
    res.cookie('name','tom',{
    //暫存時間千分之一秒
    maxAge:1000,
    //防止其他人取得cookie資料
    httpOnly:true
    })
    res.render('index', { title: 'Express' });
    });
    module.exports = router;

結語

就….超過 30 天繼續學囉,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十八天

Node.js 學習第二十八天

27 天跟 28 天寫在一起發送。

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


RESTful API todolist - Client AJAX

現在寫一支 JS 檔案去操控資料庫的資料

  1. 在 index.ejs 上增加 dataset

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!DOCTYPE html>
    <body>
    <h1>代辦事項</h1>
    <input type="text" name="content" id="content">
    <input type="submit" id="send" value="儲存">
    <ul id = "list">
    <% for(itme in todoslist){ %>

    <li><%- todoslist[itme].content %> <input type="button" data-id="<%- itme %>" value="刪除"></li>

    <% } %>
    </ul>
    <script src="/js/all.js"></script>
    </body>
  2. 開啟先前新增的 all.js 檔案,做新增顯示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    var send = document.getElementById('send');
    var content = document.getElementById('content');
    var list = document.getElementById('list');

    send.addEventListener('click',function(e){
    //撈輸入框的值
    var str = content.value;
    var xhr = new XMLHttpRequest();
    xhr.open('post',"/addTodo");
    xhr.setRequestHeader('Content-type','application/json');
    //寫content是要把資料丟到req.body.content裡面
    var todo = JSON.stringify({'content':str});
    xhr.send(todo);
    xhr.onload = function(){
    var origindata = JSON.parse(xhr.responseText);
    if(origindata.success == false){
    alert(origindata.message)
    return;
    }
    var data = origindata.result;
    var str = ''
    for(itme in data){
    str += '<li>'+data[itme].content+'<input type="button" data-set="'+itme+'" value="刪除"></li>'
    }
    list.innerHTML = str;
    }
    });
  3. 增加刪除邏輯

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    list.addEventListener('click',function(e){
    if(e.target.nodeName !== "INPUT"){
    return;
    }
    //
    var id = e.target.dataset.id;
    var xhr = new XMLHttpRequest();
    xhr('post','/removeTodo');
    xhr.setRequestHeader('Content-type','application/json');
    var removeTodo = JSON.stringify({'id':id});
    xhr.send(removeTodo);
    xhr.onload = function(){
    var origindata = JSON.parse(xhr.responseText);
    var data = origindata.result;
    var str = ''
    for(itme in data){
    str += '<li>'+data[itme].content+'<input type="button" data-set="'+itme+'" value="刪除"></li>'
    }
    list.innerHTML = str;
    }
    })

結語

這章 express + firebase 結合的就到這邊了,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十七天

Node.js 學習第二十七天

原本預計 19 號能回到家完成當天的日記,結果開車長途太累了梳洗一番就去睡,所以 27 跟 28 天的日記都在 20 號完成。

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


RESTful API todolist - 新增資料 API

傳送 API 到前端給前端去處理 API 資料。

  1. 新增一個 addTodo 的 POST 路由,前面設定請自行增加。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    //前面設定請自行增加
    //首頁路由
    app.get('/',function(req,res){
    //連到 firebase data
    firdata.ref('todos').once('value',function(snapshot){
    //把資料庫裡面的值取出來並指定到 list
    var data = snapshot.val();
    var list = data.title;
    //取出來後執行 render 並帶入title有list值
    res.render('index',{"title":list});
    })
    });

    //新增邏輯
    app.post('/addTodo', function(req,res){
    //撈存在req.body的cotent資料
    var content = req.body.content;
    var contentRef = firdata.ref('todos').push();
    contentRef.set({'content':content}).then(function(){
    firdata.ref('todos').once('value',function(snapshot){
    //小細節,傳送內容寫這樣前端比較好去做判斷
    res.send({
    "success":true,
    "result":snapshot.val(),
    "message":"讀取成功"
    });
    })
    })
    });

    // 監聽 port
    var port = process.env.PORT || 3000;
    app.listen(port);
  2. 使用 postman 去做測試
    新增測試畫面


RESTful API todolist - 刪除資料 API

做刪除邏輯撰寫

  1. 一樣前面設定自行寫入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //刪除邏輯
    app.post('/removeTodo',function(req,res){
    //取得firebase的隨機KEY
    var _id = req.body.id;
    firdata.ref('todos').child(_id).remove().then(function(){
    firdata.ref('todos').once('value',function(snapshot){
    res.send({
    "success":true,
    "result":snapshot.val(),
    "message":"刪除成功"
    });
    })
    })
    });

    // 監聽 port
    var port = process.env.PORT || 3000;
    app.listen(port);
  2. 一樣使用 postman 去測試,key值那邊要打 id , value 需要複製隨機 KEY 去測試
    刪除測試畫面


RESTful API todolist - EJS init

新增跟刪除邏輯寫好之後就只是把 firebase 資料放到首頁上去顯示,剩下的邏輯在去寫一個 JS 用網頁做刪除動做。

  1. 更改 app.js 首頁內容

    1
    2
    3
    4
    5
    6
    7
    8
    //首頁路由
    app.get('/',function(req,res){
    //連到 firebase data
    firdata.ref('todos').once('value',function(snapshot){
    var data = snapshot.val();
    res.render('index',{"todoslist":data});
    })
    });
  2. 更改 index.ejs 的內容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <body>
    <h1>代辦事項</h1>
    <input type="text" name="content" id="content">
    <input type="submit" id="send" value="儲存">
    <ul id="list">
    <% for(itme in todoslist){ %>
    <li><%- todoslist[itme].content %> <input type="button" value="刪除"></li>
    <% } %>
    </ul>
    <script src="/js/all.js"></script>
    </body>

結語

有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十六天

Node.js 學習第二十六天

因為 18 號跟 19 號人會在外面,所以在 19 號的可能會晚一天發送。

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


EJS 整合 Firebase

在連到 127.0.0.1:3000 的時後就會去跑在路由指定首頁的function

  1. 在首頁路由那邊去設定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    var express = require('express');
    var app = express();
    var engine = require('ejs-locals');
    var bodyParser = require('body-parser');
    //firbase 設定
    var admin = require("firebase-admin");
    var serviceAccount = require("./expresssdemo-firebase-adminsdk-9pn15-8407d41fa7");

    admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://expresssdemo.firebaseio.com"
    });
    //連到 firebase 的 data
    var firdata = admin.database();

    app.engine('ejs',engine);
    app.set('views','./views');
    app.set('view engine','ejs');
    //增加靜態檔案的路徑
    app.use(express.static('public'))

    // 增加 body 解析
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({extended:false}))

    //首頁路由
    app.get('/',function(req,res){
    //連到 firebase data
    firdata.ref('todos').once('value',function(snapshot){
    //把資料庫裡面的值取出來並指定到 list
    var data = snapshot.val();
    var list = data.title;
    //取出來後執行 render 並帶入title有list值
    res.render('index',{"title":list});
    })
    })

    // 監聽 port
    var port = process.env.PORT || 3000;
    app.listen(port);
  2. 完成後去更改 index.ejs 資料

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    </head>
    <body>
    <h1><%- title %></h1>
    </body>
    </html>

RESTful API todolist - EJS 版型設計

修改 index.ejs 檔案,修改完後在 public 資料夾內新增 js 資料夾與底下的 all.js 檔案並在檔案內下 console 或者 alert 去測是有沒有讀取到檔案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1><%- title %></h1>
<input type="text" name="content" id="content">
<input type="submit" id="send" value="儲存">
<ul>
<li>測試顯示<input type="button" value="刪除"></li>
</ul>
<script src="/js/all.js"></script>
</body>
</html>

結語

前面都有學過的內容,不太熟悉的話去翻一下前面學的就可以了,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十五天

Node.js 學習第二十五天

要把 firebase 跟 node 的 express 做結合了。

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


Express 整合 Firebase 流程

首先去下載這支檔案node-expressFirebase-init,這支檔案為六角學院擁有,再來可以去看這支檔案的 package 檔案資料有安裝哪些套件,再來去 firebase 新增一個專案並且去設定 -> 服務帳戶 複製 SDK 設定程式碼貼上 app.js 檔案與下載產生新的私密金鑰並放在 node-expressFirebase-init 資料夾內。
firebase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var express = require('express');
var app = express();
var engine = require('ejs-locals');
var bodyParser = require('body-parser');
//firbase 設定
var admin = require("firebase-admin");
//路徑更改成自己的私密金鑰
var serviceAccount = require("./expresssdemo-firebase-adminsdk-9pn15-8407d41fa7");

admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://expresssdemo.firebaseio.com"
});

app.engine('ejs',engine);
app.set('views','./views');
app.set('view engine','ejs');
//增加靜態檔案的路徑
app.use(express.static('public'))

// 增加 body 解析
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}))

//路由
app.get('/',function(req,res){
res.render('index');
})
// 監聽 port
var port = process.env.PORT || 3000;
app.listen(port);

完成後先去安裝 package 設定的套件再安裝 firebase 的套件, firebase-admin 。

1
2
npm install
npm install firebase-admin --save


Firebase - once、set 寫入讀取資料

複習前面 firebase ,先再 firebase 新增 todos 子節點然後再新增 content:”hello” 的資料。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var express = require('express');
var app = express();
var engine = require('ejs-locals');
var bodyParser = require('body-parser');
//firbase 設定
var admin = require("firebase-admin");
var serviceAccount = require("./expresssdemo-firebase-adminsdk-9pn15-8407d41fa7");

admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://expresssdemo.firebaseio.com"
});

var firdata = admin.database();
firdata.ref('todos').onec('value',function(snapshot){
console.log(snapshot.val());
})

app.engine('ejs',engine);
app.set('views','./views');
app.set('view engine','ejs');
//增加靜態檔案的路徑
app.use(express.static('public'))

// 增加 body 解析
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}))

//路由
app.get('/',function(req,res){
res.render('index');
})

// 監聽 port
var port = process.env.PORT || 3000;
app.listen(port);


Firebase - then 設計思維

把資料寫入後主動回傳資料確定有寫入來做任何事情。

1
2
3
4
5
6
7
//由於一些設定過於太長,所以這邊不顯示設定,
var firdata = admin.database();
firdata.ref('todos').set({'title':'hello,tom'}).then(function(){
firdata.ref('todos').once('value',function(snapshot){
console.log(snapshot.val());
})
})

結語

開始做結合了,前面學習有結果了不用再枯燥的練習了,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十四天

Node.js 學習第二十四天

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


POST AJAX JSON 格式

改成傳送 JSNO 格式。
因為有這兩段資料才可以用 form 表單跟 JSON 格式

1
2
3
4
//內容支援JSON格式
app.use(bodyParser.json());
//解析表單內容({物件設定})
app.use(bodyParser.urlencoded({extended:false}));

更改 all.js 的內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//抓DOM元素
var send = document.getElementById('send');
var content = document.getElementById('content');

send.addEventListener('click',function(e){
e.preventDefault();
//撈content值
var str = contet.value;
//開啟XML設定
var xhr = new XMLHttpRequest();
//POSY模式 指定/searchAJAX路由
xhr.open('post','/searchAJAX');
//傳送格式
xhr.setRequestHeader('Content-type','application/json');
//傳送JSON字串格式
var data = JSON.stringify({"content":str,"list":[1,2,3]});
//傳送資料
xhr.send(data);
//console看資料
xhr.onload = function(){
console.log(xhr.responseText);
}
})

postman 測試 JSON 格式, x-www-form-urlencoded 改成 raw 任何格式再把 Text 改成 JSON
範例


Router 進階設定

以路徑來講一個使用者頁面會分成照片、自我介紹、設定、工具..等,之類的東西每個又是一個頁面那如果把那些路徑都寫在同一支 JS 檔案下面那資料量會很雜,因為你不一定只有使用者頁面肯定會有購物車或者登入頁面,所以這次學的是如何把每個路由都分開管理。

  1. 首先用一支乾淨的 app.js 設定。

    1
    2
    3
    var express = require('express');
    var app = express();
    app.listen(3000);
  2. 比如你 127.0.0.1:3000/user 這個路由下面有 proflie 跟 photo 路徑那就先新增一個資料夾 routes 好方便管理各種路由,然後在新增一支 user.js 管理 user 路由的 JS 檔案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //一樣要開啟 express 功能 
    var express = require('express');
    //開啟Router功能
    var router = express.Router();

    //用這功能來GET
    //因為是user下面的路徑所以不用在這邊指定user
    router.get('/profile',function(req,res){
    res.send('你進入到profile頁面');
    console.log('有人造訪profile頁面');
    });
    router.get('/photo',function(req,res){
    res.send('你進入到photo頁面');
    console.log('有人造訪photo頁面');
    });

    //放到exports
    module.exports = router;
  3. 之後在 app.js 新增,完成後在去執行檔案看是否成功。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //原本有的
    var express = require('express');
    var app = express();
    //新增後
    //接收在routes料夾的user檔案
    var user = require('./routes/user');

    //開始跑user底下的資料是否跟使用者輸入的網址符合
    app.use('/user',user);

    //原本有的
    app.listen(3000);

express-generator

這是快速建立應用程式架構。
下面連結都有說明如何安裝與指令。
express-generator

  1. 先全域安裝 express-generator

    1
    npm install express-generator -g
  2. 建立 EJS 服務跟創建 project 資料夾

    1
    express -e project
  3. CMD 移動到 project 資料夾與安裝模組

    1
    2
    cd project
    npm install
  4. 執行它的功能與檢視 127.0.0.1:3000 (預設3000埠)

    1
    npm start

說明裡面的 app.js 一些的功能服務,都寫在中文註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var express = require('express');
var path = require('path');
//單獨放icon使用
var favicon = require('serve-favicon');
//紀錄資料日誌
var logger = require('morgan');
//接收cookie資料做解析
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//管理routes
var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// 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;

package.json 的一些資料說明
1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"name": "project",
"version": "0.0.0",
"private": true,
"scripts": {
//可以設計指令 這是開啟下面路徑的服務
"start": "node ./bin/www",
//自訂指令 npm run starts 做開啟,內建省略 run
"starts":"node ./bin/www"
},
"dependencies": {
"body-parser": "~1.18.2",
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"ejs": "~2.5.7",
"express": "~4.15.5",
"morgan": "~1.9.0",
"serve-favicon": "~2.4.5"
}
}

結語

基本上 express 的功能就到這個段落,下一個是把前面學的做整合,有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。

Node.js 的 30 天學習日記--第二十三天

Node.js 學習第二十三天

還有一個禮拜就三十天了,真的會趕不上啊,玩樂時間太多了XDDD

如果在看的過程中有任何錯誤歡迎寫 E-MAIL: pp840405@gmail.com 提醒我錯誤。


POST AJAX 前後端介接原理

用 AJAX 的方式讓前端要到資料後不用換頁就能顯示資料

  1. 新增一個 post 的 /searchAJAX 路由

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    var express = require('express');
    var app = express();
    var engine = require('ejs-locals');
    //取得 body-parser 套件
    var bodyParser = require('body-parser')
    app.engine('ejs',engine);
    app.set('views','./views');
    app.set('view engine','ejs');
    app.use(express.static('public'));
    // body 解析
    //內容支援JSON格式
    app.use(bodyParser.json());
    //解析表單內容({物件設定})
    app.use(bodyParser.urlencoded({extended:false}));
    app.get('/',function(req,res){
    res.send('你進入到首頁');
    console.log('有人造訪首頁')
    });
    //新增搜尋頁 讀取search.ejs
    app.get('/search',function(req,res){
    res.render('search');
    });
    app.post('/searchList',function(req,res){
    console.log(req.body);
    res.redirect('search');
    });
    app.post('/searchAJAX',function(req,res){
    console.log(req.body);
    res.send('hello!!');
    });

    //監聽 port
    var port = process.env.PORT || 3000;
    app.listen(port);
  2. 把 search.ejs 改成這樣

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    </head>
    <body>
    <!-- 資料移動到/searchList路由上 用post方式 -->
    <form action="/searchList" method="post">
    <input type="text" name="content" id="content" value="">
    <input type="submit" id="send" value="送出">
    </form>
    <script src="/js/all.js"></script>
    </body>
    </html>
  3. 在 public 資料夾裡面新增一個 js 資料夾在裡面又新增一個 all.js 檔案。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //抓DOM元素
    var send = document.getElementById('send');
    var content = document.getElementById('content');

    send.addEventListener('click',function(e){
    e.preventDefault();
    //撈content值
    var str = contet.value;
    //開啟XML設定
    var xhr = new XMLHttpRequest();
    //POSY模式 指定/searchAJAX路由
    xhr.open('post','/searchAJAX');
    //傳送格式
    xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    //組合字串
    var data = 'content='+ str;
    //傳送資料
    xhr.send(data);
    //console看資料
    xhr.onload = function(){
    console.log(xhr.responseText);
    }
    })

結語

有任何問題歡迎寫 MAIL: pp840405@gmail.com 一起共同討論。