1. Lời mở đầu
Khi học NodeJs thì chắc hẳn các bạn sẽ tiếp xúc với nhiều các framework khác nhau của Node và chắc hẳn ai đã từng học hay tiếp xúc với NodeJS thì sẽ đều sẽ làm việc với Express framework – một web application framework của NodeJS.
Mình nghĩ là đây là một framework khá dễ học với những bạn mới bắt đầu. Nó khá là tiện khi hỗ trợ rất nhiều các tính năng trên web hay trên mobile. Chúng giúp chúng ta xây dựng backend một cách dễ dàng hơn. Có thể kể đến một vài tính năng mà Express hỗ trợ như :
- Middleware
- Routing
- Templating
- Debugging
bên cạnh đó là rất nhiều các API hỗ trợ.
Nghe cũng thú vị rồi đấy, đi vào tìm hiểu thôi.
2. Cài đặt
1 2 3 4 | $ mkdir express $ cd express $ npm install express --save |
Tạo xong express rồi. Trước hết có in Hello World
ra cái đã
Tạo thêm một file index.js với nội dung :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token comment">// khai báo module express</span> <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// khai báo route</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello World!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// lắng nghe app trên cổng 3000</span> app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Server listening at http://localhost:3000</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Chạy node index.js
để xem kết quả.
3. Routing
Như ở ví dụ đơn giản trên thì chúng ta cũng đã nhìn qua sương sương về route của express bằng cách khai báo như trên.
1 2 3 4 | app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello World!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
với đoạn code trên chúng ta có thể hiểu được cấu trúc để khai báo một route theo cấu trúc
1 2 | app<span class="token punctuation">.</span><span class="token constant">METHOD</span><span class="token punctuation">(</span><span class="token constant">PATH</span><span class="token punctuation">,</span> <span class="token constant">HANDLER</span><span class="token punctuation">)</span> |
trong đó :
app
một instance của expressMETHOD
các HTTP methods (get, post, delete, put)PATH
đường dẫn trên browser.HANDLER
một function để thực thi đoạn code khi màpath
được gọi.
Route parameters
Chúng ta cũng có thể khai báo các params cho url với cú pháp :param
.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token comment">// Khai báo routes</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/users/:userId/address/:address'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// lấy params được truyền trên url req.params</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// URL</span> http<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>localhost<span class="token operator">:</span><span class="token number">3000</span><span class="token operator">/</span>users<span class="token operator">/</span><span class="token number">1</span><span class="token operator">/</span>address<span class="token operator">/</span>hanoi <span class="token comment">// Kết quả :</span> <span class="token punctuation">{</span><span class="token string">"userId"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string">"address"</span><span class="token operator">:</span><span class="token string">"hanoi"</span><span class="token punctuation">}</span> |
Sử dụng Router để prefix route
Nếu chúng ta muốn trước khi vào mỗi đường dẫn nào đó đều muốn nó bắt đầu bằng /admin
chả hạn thì chúng ta chỉ cần khai báo như sau :
1 2 3 4 5 6 7 | <span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/admin'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span><span class="token punctuation">;</span> router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/blog'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'day la route co prefix'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Ở đọa code trên chúng ta có khai báo một đối tượng Router, đây là một object khá mạnh của express thường dùng trong các trường hợp như middleware hay là xử lý route. Nó hỗ trỡ một vài các methods mà các bạn có thể xem tham khảo thêm tại đây.
app.route()
Một cách nữa để định nghĩa route
đó là sử dụng app.route(). Việc sử dụng cách này sẽ thấy code khá ngắn gọn và dễ dàng tránh nhầm lẫn, cũng tránh việc bị lặp lại khi định nghĩ nhiều route mà có chung các đường dẫn.
Ví dụ về việc không sử dụng app.route().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">function</span> <span class="token function">doGet</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">doPost</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">doPut</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/books/:book'</span><span class="token punctuation">,</span> doGet<span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/books/:book'</span><span class="token punctuation">,</span> doPost<span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">'/books/:book'</span><span class="token punctuation">,</span> doPut<span class="token punctuation">)</span><span class="token punctuation">;</span> |
Có thể thấy có đến 3 đoạn chúng ta đều khai báo là /books/:book
, nếu có nhiều hơn 3 cái thì nhìn cũng khá là khó chệu. Cách viết tối ưu hơn là sử dụng app.route().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">function</span> <span class="token function">doGet</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">doPost</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">doPut</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// code</span> <span class="token punctuation">}</span> app<span class="token punctuation">.</span><span class="token function">route</span><span class="token punctuation">(</span><span class="token string">'/books/:book'</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>doGet<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span>doPost<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>doPut<span class="token punctuation">)</span><span class="token punctuation">;</span> |
4. Middleware
Khi một request được gửi lên thì Express sẽ thực hiện lần lượt các hàm middleware cho đến khi trả về response cho người dùng. Chúng có quyền truy cập đến các request hay response.
Nếu một hàm Middleware thực hiện xong mà vẫn chưa phải là hàm cuối cùng trong các hàm cần thực hiện chúng ta cần phải gọi đến hàm next() nếu không ứng dụng sẽ bị treo tại ngay cái hàm đó.
Có 5 kiểu middleware được sử dụng trong Express đó là :
- Application-level middleware
- Router-level middleware
- Error-handling middleware
- Built-in middleware
- Third-party middleware
Chúng ta sẽ đi vào tìm hiểu xem từng kiểu đó là gì
Application-level middleware
Khi khởi tạo một ứng dụng Express chúng ta sẽ có một đối tượng đại diện cho ứng dụng đó, cụ thể là app. Đối tượng này thường được chúng ta khai báo dưới dạng tên là app.
1 2 | <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
thì chúng ta coi đây app này là ở level application, level cao nhất. Chúng ta có thể khai báo các middleware của cấp ứng dụng sử dụng app.use() hay là app.METHOD(với METHOD là các phương thức HTTP).
Khai báo middleware cho một đường dẫn cụ thể :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// khai báo middleware cho route</span> app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/user/:id'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Day la middleware'</span><span class="token punctuation">)</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user/:id'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'hello nha'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Server listening at http://localhost:3000</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Nếu không khai báo đường dẫn cụ thể, nó sẽ mặc định chạy khi gọi tới tất cả các route :
1 2 3 4 5 | app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Middleware chung route'</span><span class="token punctuation">)</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Router-level middleware
Middleware này thì tương tự với middleware cấp ứng dụng, chỉ khác là Router-level middleware là instance của express.Router().
Để sử dụng middlware cấp route chúng ta cũng sẽ sử dụng router.use() hoặc router.METHOD như Application-level middleware.
Ở trên nếu mọi người để ý thì ở phần tìm hiểu về Route mình cũng đã sử dụng router.use() để định nghĩa prefix cho route.
Khai báo middleware chạy ở bất cứ request nào :
1 2 3 4 5 | router<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Middleware route'</span><span class="token punctuation">)</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Error-handling middleware
Đây là middleware dùng cho việc xử lý lỗi. Nhưng khi dùng middleware này cần khai báo đủ 4 tham số là err, req, res, next
. Mặc dù không sử dụng đến tham số next, nhưng việc khai báo này là bắt buộc để Express nhận ra đây là hàm xử lí lỗi.
Giả sử khi server lỗi.
1 2 3 4 5 | app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>err<span class="token punctuation">.</span>stack<span class="token punctuation">)</span> res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Something broke!'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Third-party middleware
Sử dụng middlware này để chúng ta thêm các chức năng cần thiết khác cho app. Giả sử chúng ta thêm một middleware là cookie-parser
.
Chỉ cần chạy lệnh
1 2 | $ npm install cookie-parser |
sau đó khai báo ở cấp ứng dụng hay cấp route thì tùy các bạn định nghĩa. Ví dụ :
1 2 3 4 5 6 7 | <span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span> <span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">var</span> cookieParser <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cookie-parser'</span><span class="token punctuation">)</span> <span class="token comment">// load the cookie-parsing middleware</span> app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cookieParser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Chúng ta có thể tham khảo thêm các middleware khác tại đây.
5. Sử dụng template engines
Nếu như bạn từng tiếp xúc với Ruby on Rails thì việc tiếp cận các template engines của NodeJS khá dễ dàng. Nếu như trong Rails có erb thì NodeJS có ejs, hay là Rails có slim còn Node có pug. Mình thấy không có quá nhiều sự khác biệt nào trong việc sử dụng template engines trong Node nếu như bạn từ tiếp xúc với Rails.
Để sử dụng template engine pug chỉ cần cài
1 2 | $ npm install --save pug |
và khai báo
1 2 3 4 5 | <span class="token comment">//Khai báo đường dẫn đến thư mục chứa các template</span> app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'views'</span><span class="token punctuation">,</span> <span class="token string">'./views'</span><span class="token punctuation">)</span> <span class="token comment">//Khai báo template engine sử dụng</span> app<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'view engine'</span><span class="token punctuation">,</span> <span class="token string">'pug'</span><span class="token punctuation">)</span> |
Và cách khai báo này cũng tương tự nếu như các bạn dùng template engines nào khác.
6, Express database
Express có thể kết hợp với rất nhiều các loại cơ sở dữ liệu khác nhau.
Giả sử chúng ta kết nối với mysql
thì trước tiên cần phải cài module mysql trước.
1 2 | $ npm install mysql |
và khai báo để sử dụng
1 2 | <span class="token keyword">const</span> mysql <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mysql'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Để tạo một database
chúng ta cần phải khai báo một vài cấu hình đơn giản như hostname
, database name
..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">var</span> mysql <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mysql'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> con <span class="token operator">=</span> mysql<span class="token punctuation">.</span><span class="token function">createConnection</span><span class="token punctuation">(</span><span class="token punctuation">{</span> host<span class="token operator">:</span> <span class="token string">"localhost"</span><span class="token punctuation">,</span> user<span class="token operator">:</span> <span class="token string">"yourusername"</span><span class="token punctuation">,</span> password<span class="token operator">:</span> <span class="token string">"yourpassword"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> con<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">throw</span> err<span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Connected!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> con<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token string">"CREATE DATABASE mydb"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> result</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">throw</span> err<span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Database created"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Đây chỉ là một ví dụ về cách kết hợp Express với database. Trên thực tế mình thấy người ta hay sử dụng NodeJS với MongoDB hơn cả. Để tìm hiểu các sử dụng và kết hợp chúng bạn có thể xem thêm tại https://github.com/mongodb/node-mongodb-native.
Kết luận
Trên đây là những tìm hiểu của mình về Express framework.