Võ Duy Tạo Lorem ipsum Trang 2 MỤC LỤC Lời nói đầu 5 Cách học đúng cách 5 Yêu cầu trình độ 6 Liên hệ với tác giả 6 Phần 1 Giới thiệu 7 Giới thiệu ứng dụng blog sẽ xây dựng 7 Node js là gì? 8 Cài đặt N.
Võ Duy Tạo Lor MỤC LỤC Lời nói đầu Cách học cách Yêu cầu trình độ Liên hệ với tác giả Phần 1: Giới thiệu Giới thiệu ứng dụng blog xây dựng Node.js gì? Cài đặt Node.js Tạo server Nodejs 10 Hiểu request response 12 Phần 2: Giới thiệu NPM Express 15 Cài đặt Custom Package với NPM 15 Giới thiệu Express 18 Tổng kết 24 Phần 3: Bước đầu tạo web app với Express 25 Tải web template 25 Tự động khởi động server thay đổi mã nguồn 26 Npm start 27 Tạo thư mục public chứa tệp static 27 Tạo Page routes 30 Tổng kết 30 Phần 4: Templating Engine 31 Giới thiệu Template engine 31 Layout 33 Tổng kết 35 Phần 5: Giới thiệu MongoDB 36 Kiến trúc MongoDB 37 Cài đặt MongoDB 37 Kết nối quản lý MongoDB với Robo 3T 39 Trang Cài đặt Mongoose 40 Kết nối MongoDB từ Node.js 40 Định nghĩa Model 40 Tạo action CRUD với Mongoose model 41 Tổng kết 43 Phần 6: Ứng dụng MongoDB vào dự án 44 Lưu liệu Post vào Database 47 Hiển thị danh sách Post 48 Hiển thị liệu động với Template engine 49 Hiển thị nội dung Post 51 Thêm Fields Schema 52 Tổng kết 53 Phần 7: Tạo tính upload ảnh với Express 54 Tổng kết 58 Phần 8: Tìm hiểu Express Middleware 59 Middleware tùy chỉnh 59 Tạo đăng ký Validation middleware 60 Tổng kết 61 Phần 9: Refactoring theo mơ hình MVC 62 Giới thiệu mơ hình MVC 62 Tiến hành Refactoring 63 Tổng kết 66 Phần 10: Tạo tính đăng ký thành viên 67 User Model 69 Controller xử lý đăng ký user 70 Mã hóa mật 71 Mongoose Validation 73 Tạo tính đăng nhập 74 Tổng kết 77 Phần 11: Xác thực với Express Sessions 78 Implementing User Sessions 79 Trang Protect Pages với Authentication Middleware 81 User Logout 83 Tạo trang 404 84 Tổng kết 86 Phần 12: Triển khai web app lên server thật .87 Cài đặt server 87 Đưa sourcecode Node.js lên VPS 89 Quản lý ứng dụng Node.js PM2 90 Kết nối domain vào vps 91 Cấu hình Nginx Reverse Proxy Server 91 Chào tạm biệt 92 Tài liệu tham khảo .93 Trang Lời nói đầu N ode.js trở thành xu hướng giới lập trình back-end Có nhiều ứng dụng lớn đại gia sử dụng Nodejs Có thể kể tên như: Paypal, Netflix, LinkedIn Mục tiêu sách giúp bạn bước vào giới Node.js cách vững Tức bạn hiểu rõ chất, cách xây dựng ứng dụng Nodejs cách Nếu không gọi "vũ trụ Node.js " "Vũ trụ Node.js " bắt nguồn từ viên gạch Javascript Để khám phá "Vũ trụ Node.js " cách trơn tru, sách giúp bạn tìm hiểu "tam trụ" Node.js, Node.js, ExpressJS, MongoDB Mỗi phần sách trình bày thẳng vào vấn đề, kiến thức trọng tâm để tránh thời gian vàng ngọc bạn Sau bạn đọc xong sách này, bạn đủ kỹ để tự xây dựng web app Nodejs triển khai Internet Cách học cách Cuốn sách chia nhỏ nội dung thành 12 phần, phần giới thiệu chủ đề riêng biệt Mục đích để bạn chủ động lịch học, không bị dồn nén nhiều Với phần lý thuyết, có ví dụ minh họa code ln vào dự án Vì vậy, cách học tốt vừa học vừa thực hành Bạn nên tự viết lại dịng code chạy Đừng copy đoạn code sách, điều làm hạn chế khả viết code bạn, làm bạn nhiều không hiểu code bị lỗi Nhớ nhé, đọc đến đâu, tự viết code đến đó, tự build kiểm tra đoạn code chạy khơng! Trang u cầu trình độ Cuốn sách xây dựng từ kiến thức tảng Node.js từ Nên khơng cần bạn phải có kiến thức Node.js Tuy nhiên, Node.js xây dựng ngơn ngữ Javascript nên tốt bạn có kiến thức Javascript Ngoài ra, bạn cần chút hiểu biết HTML CSS để dựng giao diện web Liên hệ với tác giả Nếu có vấn đề trình học, code bị lỗi khơng hiểu, bạn liên hệ với qua hình thức đây: Website: https://vntalking.com Fanpage: https://facebook.com/vntalking Email: support@vntalking.com Github: https://github.com/vntalking/nodejs-express-mongodb-co-ban Trang PHẦN Giới thiệu N ode.js JavaScript runtime để chạy Javascript phía server Có nhiều công ty sử dụng Node.js để xây dựng cho ứng dụng họ Có thể kể số tên tuổi đình đám như: WalMart, LinkedIn, PayPal, YouTube, Yahoo!, Amazon.com, Netflix, eBay Reddit Trong sách này, học Node.js kết hợp với Express mongoDB để xây dựng blog từ đầu, từ số Trong trình đọc thực hành theo sách, bạn hiểu tự xây dựng ứng dụng riêng từ kỹ thuật sách Chúng ta tìm hiểu loạt kỹ thuật xác thực người dùng, validate liệu, bất đồng Javascript, Express, MongoDB template engine.v.v Giới thiệu ứng dụng blog xây dựng Như giới thiệu trên, để việc học có hiệu quả, thay có đoạn code mẫu ngắn không liên quan tới nhau, vừa học vừa xây dựng ứng dụng hoàn chỉnh Tiêu chí "học đến đâu, ứng dụng đến đó" Đây giao diện ứng dụng: Hình 1.1: Template giao diện dùng sách Trang Với trang blog này, người dùng đăng ký tài khoản Sau đăng ký xong họ trang chủ, đăng nhập vào blog Thanh navigation bar hiển thị menu khác tùy thuộc vào trạng thái người đăng nhập hay chưa Để xây dựng giao diện, sử dụng EJS template engine Sau người dùng đăng nhập, thành navigator bar hiển thị text "LogOut" để họ đăng xuất cần Ngồi ra, cịn thêm menu "new post" để họ tạo viết mới, upload ảnh lên blog Sau họ tạo viết xong quay trở lại trang chủ, blog hiển thị danh sách viết published Thông qua việc thực hành xây dựng ứng dụng blog này, bạn nắm kiến thức Node.js, kết hợp với express MongoDB Node.js gì? Trước tìm hiểu khái niệm Node.js gì, bạn cần phải hiểu chế Internet hoạt động Khi người dùng mở trình duyệt, vào website vntalking.com chẳng hạn Như cô tạo request tới server, lúc ấy/trình duyệt coi client Khi client tạo request tới server server phản hồi lại nội dung trang web mà client u cầu Có số ngơn ngữ lập trình thiết kế để viết ứng dụng cho server PHP, Ruby, Python, ASP, Java Nếu trước kia, Javascript thiết kế để chạy trình duyệt, cung cấp thêm khả tương tác trang web với người dùng Ví dụ menu có hiệu ứng dropdown, hay hiệu ứng tuyết rơi Nhưng chuyện thay đổi vào năm 2009, Node.js đời, sử dụng dụng V8 engine làm chạy mã Javascript Giờ đây, Javascript vượt khởi khn khổ trình duyệt, cho phép chạy server Như vậy, ngồi ngơn ngữ dành riêng cho server PHP, Golang, JAVA Javascript trở thành lựa chọn sáng giá khác Những lợi ích mà Node.js mang lại cho bạn: Đầu tiên, V8 JavaScript engine Javascript engine mạnh mẽ, sử dụng trình duyệt Chrome Google Điều làm ứng dụng bạn có tốc độ nhanh Node.js khuyến khích viết mã kiểu asynchronous (bất đồng bộ) để cải thiện tốc độ ứng dụng, tránh vấn đề phát sinh việc sử dụng đa luồng Thứ Javascript ngôn ngữ phổ biến, bạn thừa hưởng nhiều thư viện hay ho mà lại miễn phí Trang Cuối Node.js sử dụng javascript, bạn tận dụng kiến thức có từ trước, bạn viết ứng dụng dùng Javascript trình duyệt Giờ đây, thay phải tìm hiểu thêm ngơn ngữ mới, bạn cần biết Javascript đủ full stack Cài đặt Node.js Để cài đặt Node.js, bạn vào trang chủ nodejs.org (hình 1.2) tải phiên tương ứng với hệ điều hành máy tính bạn Hình 1.2: Download node.js Việc cài đặt diễn đơn giản Nếu máy bạn dùng window cài đặt phần mềm khác thơi Bạn tham khảo chi tiết cài đặt chi tiết Sau cài xong, bạn kiểm tra version lệnh sau: node -v Ngoài ra, cài đặt Node.js, bạn khuyến NPM npm -v Trang Kết hình 1.3 Hình 1.3: kiểm tra phiên node.js Tạo server Nodejs Chúng ta tạo server đơn giản Node.js để bạn dễ hiểu cách client tạo request tới server server phản hồi lại request Bạn sử dụng trình soạn thảo code để viết code Như đề xuất bạn sử dụng Visual Studio Code Giờ tạo thư mục dùng Visual Studio Code (từ viết tắt VS) để mở thư mục Các bạn tạo file Javascript, đặt tên index.js Dưới đoạn code để tạo http server đơn giản: const http = require('http') const server = http.createServer((req, res) => { console.log(req.url) res.end('VNTALKING: Xin chào Node.js') }) server.listen(3000) Giải thích code const http = require('http') Hàm require có tác dụng import module vào tệp bạn xử lý Hàm Node.js giống hàm import hay include ngôn ngữ khác Tham số đầu vào hàm require tên module định nghĩa từ khóa export trả package Quay lại đoạn code trên, require module có tên http gán cho biến có tên http (mình đặt trùng dễ nhận biết biến package thơi, bạn đặt biến tên bạn muốn) http module tích hợp sẵn Node.js, dùng để cung cấp phương thức tương tác với server GET, POST, UPDATE Trang 10 cịn với Chrome Developer Tools -> application Bạn nhìn thấy cookie trang localhost sinh Hình 11.1: Cookie tạo express-session module Nếu bạn comment đoạn code liên quan đến express-session, sau refesh lại trình duyệt cookie khơng tạo bạn thấy Implementing User Sessions Chúng ta bắt tay thực implement cho tính tạo lưu session đăng nhập người dùng Mở controllers/ loginUser.js, thêm đoạn code bơi đậm bên dưới: const bcrypt = require('bcrypt') const User = require(' /models/User') module.exports = (req, res) => { const { username, password } = req.body; User.findOne({ username: username }, (error, user) => { if (user) { bcrypt.compare(password, user.password, (error, same) => { if (same) { // if passwords match req.session.userId = user._id res.redirect('/') } else { res.redirect('/auth/login') } }) } else { res.redirect('/auth/login') } }) } Chúng ta định user_id cho session express-session module lưu thông tin xuống cookie trình duyệt người dùng, để người dùng gửi yêu cầu trình duyệt gửi cookie lại cho server kèm authenticated id Đây cách để server biết người dùng đăng nhập hay chưa Trang 79 Để xem xác thơng tin session object, vào controllers/home.js thêm dòng console.log: module.exports = (req, res) => { BlogPost.find({}, function (error, posts) { console.log(req.session) console.log(posts); res.render('index', { blogposts: posts }); }) } Ok, bạn thử vào trang web, tiến hành đăng nhập thành cơng, kiểm tra hình console Session { cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }, userId: '5e70d250fd1459148c026c22' } Thông tin userId: '5e70d250fd1459148c026c22' chia sẻ trình duyệt server có request Đây thơng tin để biết người dùng đăng nhập hay không Tiếp theo, để kiểm tra session id trước cho phép người dùng tạo post, thêm đoạn code sau vào controllers/newPost.js module.exports = (req, res) => { if (req.session.userId) { return res.render("create"); } res.redirect('/auth/login') } Đoạn code có ý nghĩa là: kiểm tra xem session có chứa user id hay khơng? Nếu khơng có tức request người dùng chưa đăng nhập -> tiến hành redirect sang hình login Trang 80 Protect Pages với Authentication Middleware Trong ứng dụng web, bạn thấy có số trang có người dùng đăng nhập truy cập Ví dụ trang tạo post mới, người đăng nhập phép truy cập Mở rộng yêu cầu: Có nhiều trang web, người ta phân quyền tài khoản Ví dụ có trang thuộc admin panel phải tài khoản admin vào được, hay tài khoản thơng thường phép truy cập giới hạn tính khơng thay đổi giá trị hệ thống Cuối khách truy cập xem nội dung, mà khơng sửa Sau bạn hồn thành xong phần 11 sách này, bạn thử thực hành làm tính phân quyền gợi ý xem Đầu tiên, cần tạo custom middleware đặt tên là: /middleware/authMiddleware.js const User = require(' /models/User') module.exports = (req, res, next) => { User.findById(req.session.userId, (error, user) => { if (error || !user) return res.redirect('/') next() }) } Trong middleware này, query vào DB để tìm userId: User.findById(req.session.userId ) Nếu kết trả mà có tồn gọi hàm next() để chuyển sang middleware khác Ngược lại, redirect trang chủ Tiếp theo, import middleware index.js const authMiddleware = require('./middleware/authMiddleware') Để áp dụng middleware vào route tạo post cần đặt middleware trước newPostController app.get('/posts/new', authMiddleware, newPostController) Trang 81 Chúng ta làm tương tự lưu post vào DB app.post('/posts/store', authMiddleware, storePostController) Để kiểm tra xem đoạn code hoạt động chưa, bạn cần xóa cookie trình duyệt, sau thử chọn menu "new post", web mà redirect trang chủ Sau bạn login làm lại, vào trang "new post" Tiếp tục nhé! Hiện tại, người dùng đăng nhập thành cơng, họ nhìn thấy menu "login" "new user" Điều sai sai khơng? Bởi họ login khơng cần login Tương tự, họ user rồi, cần phải đăng ký nữa??? Tương tự với trường hợp menu "new post" Menu dành cho người dùng đăng nhập, cịn với khách khơng Giờ xử lý trường hợp Trong thư mục middleware, tạo thêm middleware đặt tên redirectIfAuthenticatedMiddleware.js module.exports = (req, res, next) => { if (req.session.userId) { return res.redirect('/') // if user logged in, redirect to home page } next() } Sau import middleware index.js const redirectIfAuthenticatedMiddleware = require('./middleware/redirectIfAut henticatedMiddleware') Áp dụng cho routes sau: app.get('/auth/register', redirectIfAuthenticatedMiddleware, newUserController) app.post('/users/register', redirectIfAuthenticatedMiddleware, storeUserController) app.get('/auth/login', redirectIfAuthenticatedMiddleware, loginController) app.post('/users/login', redirectIfAuthenticatedMiddleware, loginUserController) Giờ bạn đăng nhập thành cơng mà cố tình nhấp vào menu "login", trang web điều hướng trang chủ Nhưng chưa Chúng ta tiếp tục xử lý phần giao diện, cần phải ẩn menu "Login" "New User" người dùng đăng nhập Trang 82 Để làm điều này, index.js global.loggedIn = null; app.use("*", (req, res, next) => { loggedIn = req.session.userId; next() }); Chúng ta khai báo biến loggedIn kiểu global, mục đích truy cập biến file EJS Với khai báo app.use("*", (req, res, next) => … ), với toán tử "*" tức áp dụng cho request, gán UserId cho biến loggedIn Tiếp theo, sửa NavigatorBar views/layout/navbar.ejs Thêm kiểm tra điều kiện cho menu "Login", "new post" "new user" Giờ bạn thử chạy ứng dụng kiểm tra thành User Logout Hiện người dùng chưa có cách để logout tài khoản Để làm điều bạn cần gọi hàm session.destroy() Cách thực tạo giao Trang 83 diện người dùng hoàn toàn tương tự phần trước Mình trình bày nhanh thơi Trong views/layout/navbar.ejs