Như vậy là chúng ta lại bắt đầu một Sub-Series
mới của Tự Học Lập Trình Web Một Cách Thật Tự Nhiên để tìm hiểu về một framework
có tên là ExpressJS
. Đây là một framework
rất phổ biến dành cho các ứng dụng web
trên nền NodeJS
– và sẽ giúp đỡ chúng ta xây dựng phần mềm server
thuận lợi hơn với nhiều lớp công cụ trừu tượng và cách sử dụng đơn giản.
Trước khi bắt đầu bước vào phần nội dung chính của bài viết, chúng ta sẽ cùng nhìn lại code server
đơn giản mà chúng ta đã viết trước đó. Ở đây chúng ta vẫn sẽ sử dụng lại cấu trúc thư mục như cũ với các tệp HTML, CSS, và JS giả định đã được tạo ra trước đó. Các thành phần tạo ra bởi npm
thì mình sẽ không liệt kê ở đây, tuy nhiên thì chúng ta đều đã biết là project
khởi đầu của mình đã init
xong xuôi rồi. Chúng ta chỉ việc cài đặt thêm ExpressJS
để viết code thử và học kiến thức mới thôi.
[nodejs-blog]
|
+---[static]
| |
| +---[asset]
| | |
| | +---style.css
| | +---main.js
| |
| +---[post]
| | |
| | +---an-article.html
| | +---another-article.html
| |
| +---index.html
| +---oops.html
|
+---route.js
+---server.js
+---test.js
const textType ={
html:'text/html',
css:'text/css',
js:'text/javascript',get(url){if(url.endsWith('.html'))return textType.html;elseif(url.endsWith('.css'))return textType.css;elseif(url.endsWith('.js'))return textType.js;elsereturn'';}};// textType
exports.handleHomeRequest=function(request, response){var fsPromises =require('fs/promises');
fsPromises.readFile('static'+'/index.html').then(function(data){
response.setHeader('content-type', textType.html);
response.writeHead(200);
response.end(data);}).catch(function(error){
console.error(error);});};// handleHomeRequest
exports.handlePostRequest=function(request, response){var fsPromises =require('fs/promises');
fsPromises.readFile('static'+ request.url).then(function(data){
response.setHeader('content-type','text/html');
response.writeHead(200);
response.end(data);}).catch(function(error){
console.error(error);handleOopsRequest(request, response);});};// handlePostRequest
exports.handleAssetRequest=function(request, response){var fsPromises =require('fs/promises');
fsPromises.readFile('static'+ request.url).then(function(data){var contentType = textType.get(request.url);
response.setHeader('content-type', contentType);
response.writeHead(200);
response.end(data);}).catch(function(error){
console.error(error);});};// handleAssetRequest
exports.handleOopsRequest=function(request, response){var fsPromises =require('fs/promises');
fsPromises.readFile('static'+'/oops.html').then(function(data){
response.setHeader('content-type', textType.html);
response.writeHead(404);
response.end(data);}).catch(function(error){
console.error(error);});};// handleOopsRequest
/* Creating a server */const http =require('http');consthandleRequest=function(request, response){var route =require('./route.js');if(request.url =='/')
route.handleHomeRequest(request, response);elseif(request.url.startsWith('/post'))
route.handlePostRequest(request, response);elseif(request.url.startsWith('/asset'))
route.handleAssetRequest(request, response);else
route.handleOopsRequest(request, response);};// handleRequestconst server = http.createServer(handleRequest);/* Start running server */const port =3000;const hostname ='127.0.0.1';constcallback=function(){
console.log('Server is running at...');
console.log('http://'+ hostname +':'+ port +'/');};// callback
server.listen(port, hostname, callback);
// xóa nội dung để làm quen với ExpressJS
<!doctypehtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Homepage</title><linkrel="stylesheet"href="/asset/style.css"></head><body><h1>Homepage</h1><scriptsrc="/asset/main.js"></script></body></html>
<!doctypehtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Oops ! Not-Found</title><linkrel="stylesheet"href="/asset/style.css"></head><body><h1>Oops ! Not-Found</h1><scriptsrc="/asset/main.js"></script></body></html>
<!doctypehtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>An Article</title><linkrel="stylesheet"href="/asset/style.css"></head><body><h1>An Article</h1><scriptsrc="/asset/main.js"></script></body></html>
<!doctypehtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Another Article</title><linkrel="stylesheet"href="/asset/style.css"></head><body><h1>Another Article</h1><scriptsrc="/asset/main.js"></script></body></html>
console.log('Client-side JavaScript');
h1{font-size: 90px;line-height: 1.5;text-align: center;}
Cài đặt và sử dụng ExpressJS cơ bản
Giống với các package
khác mà chúng ta đã thử cài đặt từ npm
, việc tiến hành cài đặt ExpressJS
cho project
hiện hành được thực hiện bằng một dòng lệnh cơ bản.
CMD | Terminal
npm install express --save
Và như vậy là chúng ta đã có thể viết code để sử dụng thử ExpressJS
giống như lần đầu tiên khởi tạo một server
trên nền NodeJS
. Mà thực ra chúng ta không viết, là copy/paste
về từ trang chủ của ExpressJS
thôi.
/* Creating server */const express =require('express')const server =express()/* Adding a route */var path ='/'
server.get(path,function(request, response){
response.send('Hello World!')})/* Start running server */var port =3000
server.listen(port,function(){
console.log('Server is running at...')
console.log(`http://127.0.0.1:${port}`)})
Bắt đầu chạy thử code Hello World
được cung cấp bởi ExpressJS.com.
CMD | Terminal
npm test
Tuyệt.. mọi thứ đã hoạt động tốt giống như ExpressJS quảng cáo.
Ở đây chúng ta có thể thấy đặc điểm quan trọng đầu tiên trong code ví dụ của ExpressJS cung cấp đó là… không có dấu chấm phẩy ;
nào cả. Về việc JavaScript không bắt buộc phải sử dụng các dấu ;
để kết thúc câu lệnh thì chúng ta đã đề cập tới từ bài viết đầu tiên giới thiệu về JavaScript rồi. Tuy nhiên chúng ta cũng đã quy ước là sẽ giữ thói quen sử dụng nó trong một thời gian cho đến khi cảm thấy quen thuộc hơn với JavaScript. Và bây giờ thì ExpressJS vừa mới nhắc chúng ta là có thể ngưng sử dụng các dấu ;
được rồi.
Đối với code khởi tạo server
đơn giản thì hiển nhiên chúng ta chưa thể nhìn thấy được nhiều sự khác biệt giữa code Hello World
không có ExpressJS và code Hello World
mà chúng ta vừa mới copy/paste
từ trang chủ của ExpressJS. Ở đây chúng ta chỉ nhận ra một chi tiết khác biệt nho nhỏ – đó là đoạn server.get()
chắc chắn là có ý nghĩa tương đương với đoạn code mà chúng ta truyền hàm xử lý yêu cầu handleRequest
vào phương thức http.createServer
của code cũ.
Tuy nhiên ở đây server.get()
nhận vào thêm một tham số path
chỉ đường dẫn nhận diện từ yêu cầu được gửi tới. Và hàm xử lý yêu cầu được truyền vào sẽ chỉ được thực thi khi yêu cầu gửi tới phù hợp với path
mà chúng ta truyền vào phương thức server.get()
. Như vậy là chúng ta không phải khởi đầu với một hàm handleRequest
tiếp nhận tất cả các kiểu reuqest
truyền tới và sau đó lại phải thực hiện phân tích để chia tác vụ về các hàm xử lý phụ. Nếu vậy có lẽ ExpressJS sẽ cho phép chúng ta tạo ra thêm những chu trình xử lý route
khác với cách thức tương tự như cái route
dành cho trang chủ trong code ví dụ vừa rồi.
/* Creating server */const express =require('express')const server =express()/* Adding a route */
server.get('/',function(request, response){
response.send('Bạn vừa yêu cầu xem Trang Chủ')})
server.get('/post',function(request, response){
response.send('Bạn vừa yêu cầu xem Bài Viết')})/* Start running server */
server.listen(3000,function(){
console.log('Server is running at...')
console.log(`http://127.0.0.1:${port}`)})
Thật tuyệt… Như vậy là chúng ta không cần phải thực hiện thao tác phân tích đường dẫn yêu cầu ở một hàm tiếp nhận request
tổng bộ rồi ủy thác công việc tới hàm xử lý phù hợp ở cấp thấp hơn. Tất cả những gì chúng ta cần làm đó là truyền các cặp đường dẫn/hàm xử lý
tương ứng vào các câu lệnh server.get(path, handler)
.
Tuy nhiên đó vẫn chưa phải là tất cả những gì mà ExpressJS có thể giúp đỡ chúng ta thay đổi code server
đơn giản mà chúng ta đã có trước đó. Bây giờ chúng ta sẽ thử gửi trả lại các tệp HTML tĩnh tương ứng với các yêu cầu.
/* Creating server */const express =require('express')const server =express()/* Adding routes */var staticPath = __dirname +'/static'
server.get('/',function(request, response){
response.sendFile(staticPath +'/index.html')})
server.get('*',function(request, response){
response.sendFile(staticPath + request.originalUrl)})/* Start running server */
server.listen(3000,function(){
console.log('Server is running at...')
console.log(`http://127.0.0.1:${port}`)})
Thao tác gửi trả một tệp tĩnh cũng là một trong số những thao tác rất phổ biến và vì vậy ExpressJS cũng đã giúp chúng ta đơn giản hóa mọi thao tác xử lý chi tiết. Chúng ta đã không cần phải nhờ File System
truy xuất tới tệp cần gửi trả để đọc nội dung, và cũng không cần phải thiết lập những chi tiết liên quan tới tiêu đề phản hồi như kiểu nội dung phản hồi là gì hay tín hiệu phản hồi 200
hay 404
.
Nếu như jQuery
ở phía client-side
là một nhà thông thái trong nhóm tác vụ làm việc với cấu trúc văn bản HTML và CSS; Thì ExpressJS
ở đây lại đặc biệt am hiểu về những thao tác điều hướng route
, và phản rồi response
khi làm việc với các yêu cầu request
gửi tới từ đâu đó.
Ở đây chúng ta đã sử dụng path
ở lần gắn hàm xử lý sự kiện thứ hai là *
, nó có nghĩa là hàm xử lý truyền vào ở đây sẽ được áp dụng cho tất cả các yêu cầu gửi tới. Ký hiệu này được sử dụng với ý nghĩa tương tự ở rất nhiều công cụ lập trình khác mà chúng ta đã học; Ví dụ như bộ chọn *
của CSS cũng là để chọn tất cả các phần tử HTML có mặt trong trang web đơn; Hoặc trong các biểu thức thường thị RexExp
giúp làm việc với các chuỗi, thì *
cũng có ý nghĩa là bất kỳ kí tự nào. Vậy chúng ta cứ ghi nhớ *
có nghĩa là bất kỳ
cái gì cũng phù hợp.
Làm quen với tài liệu của ExpressJS
Sau khi chúng ta đã hiểu sơ lược về những giá trị mà ExpressJS đem lại, việc tiếp tục tìm hiểu về framework
này chắc chắn vẫn sẽ là xuất phát từ tài liệu chính thức trên trang chủ của framework
– ExpressJS.com.
Bộ tài liệu chính thức mà ExpressJS cung cấp cho chúng ta rất gọn gàng với 5 chỉ mục chính ở phía bên trái được đặt trong một danh sách đóng/mở
dạng accordion
giúp chúng ta luôn luôn duy trì được cái nhìn tổng quan về các công cụ được cung cấp. Và điểm khởi đầu của framework
là hàm express()
.
var express = require('express')
var app = express()
ExpressJS gọi phần mềm server
của chúng ta là app
(application) – hay ứng dụng
– để biểu thị một phần mềm hoạt động qua tương tác mạng network
nói chung. Và như vậy chúng ta có chỉ mục tiếp theo cần mở xem là Application.
var express = require('express')
var app = express()
app.get('/', function(req, res) {
res.send('hello world')
})
app.listen(3000)
Bên cạnh đó thì object express
cũng có một phương thức nổi bật so với số còn lại đó là express.Router()
và chúng ta cũng thấy có một chỉ mục tương ứng cùng tên Router – tạm dịch là trình định tuyến – điều hướng yêu cầu nhận được tới đâu đó để xử lý. Các router
sẽ giúp chúng ta tách rời tác vụ phân tích và chuyển hướng yêu cầu khỏi phần thân chương trình chính ở tệp khởi tạo ứng dụng app
trong trường hợp bạn có dự định xây dựng một thứ gì đó đồ sộ.
var express =require('express')var router = express.Router()
router.get('/',function(req, res){
res.send('hello world')})
module.exports ={ router }
var express =require('express')var app =express()var{ router }=require('./router.js')
app.use(router)
app.listen(3000)
Hai chỉ mục còn lại là Request và Response thì chúng ta cũng có thể đoán ra được là liên quan tới 2 tham số đầu tiên (req, res)
mà các hàm xử lý nhận được. Như vậy là chúng ta có thể thấy tổng quan những công cụ của ExpressJS được liệt kê trong trong tài liệu này sẽ giúp chúng ta đơn giản hóa các tác vụ phân tích và điều hướng yêu cầu tới những chu trình xử lý riêng. Như vậy thì chúng ta sẽ có thể tập trung tốt hơn vào việc viết code xử lý yêu cầu cụ thể và không tốn quá nhiều năng lượng vào thao tác phân tích địa chỉ yêu cầu và khởi tạo logic điều hướng.
Thế cái tác vụ tự động tạo ra mấy trang web đơn từ nguồn dữ liệu đơn giản sẽ được hỗ trợ ở chỗ nào?
À.. mình quên khuấy mất. Cái này mới là cái quan trọng nhất đối với nhu cầu tạo blog đơn giản của chúng ta hiện tại; Chứ cái tác vụ phân tích với điều hướng yêu cầu thì cũng chưa hẳn là quan trọng lắm.
Phương thức app.render(view, callback)
sẽ giúp chúng ta sử dụng các biểu mẫu template
mô tả code HTML ở dạng chưa có dữ liệu thực tế – gắn với dữ liệu truy vấn được bởi logic cung cấp trong hàm callback
và tạo ra code HTML hoàn chỉnh để gửi trả cho trình duyệt web. Và như vậy là chúng ta sẽ cần tìm hiểu cách thức để tạo ra cái template
mà chúng ta vừa nói đến, và… hoàn thiện trang blog đơn giản mà chúng ta đang xây dựng thôi.
Tuy nhiên thì trước hết chúng ta vẫn nên có một lượt giới thiệu tổng quan về từng chỉ mục chính trong tài liệu của ExpressJS. Cũng giống như khi chúng ta học cách sử dụng Bootstrap
hay jQuery
ở phía mặt tiền front-end
thôi; Chúng ta cần xem qua hết một lượt để nhớ mặt được kha khá những công cụ mà ExpressJS cung cấp, rồi sau đó mới có thể tự tin mà lần mò viết code được.
Vậy, hẹn gặp lại bạn trong bài viết tiếp theo với chủ đề tìm hiểu về thao tác điều hướng yêu cầu trong ExpressJS.
(Sắp đăng tải) [ExpressJS] Bài 2 – Phân tích yêu cầu và điều hướng cơ bản
Nguồn: viblo.asia