Giới thiệu
Ban đầu, Javascript không có cách nào để nhập / xuất mô-đun. Đây là một vấn đề. Hãy tưởng tượng việc viết ứng dụng của bạn chỉ trong một tệp - điều đó sẽ thật là ác mộng!
Sau đó, những người thông minh hơn tôi rất nhiều đã cố gắng thêm mô-đun vào Javascript. Một số trong số đó là IIFE, CJS, AMD, UMD và ESM. Bạn có thể đã nghe một số trong số chúng (có những phương pháp khác, nhưng đây là những người chơi lớn).
Trong những năm qua, có một hệ sinh thái ngày càng tăng đều đặn của các thành phần JavaScript để bạn lựa chọn. Số lượng sự lựa chọn tuyệt đối là tuyệt vời, nhưng điều này cũng gây khó khăn khi các thành phần được trộn và kết hợp với nhau. Và không mất quá nhiều thời gian để các nhà phát triển chớm nở phát hiện ra rằng không phải tất cả các thành phần đều được xây dựng để chơi tốt với nhau.
Để giải quyết những vấn đề này, AMD
và CommonJS
có thông số kỹ thuật mô-đun cạnh tranh đã xuất hiện tại hiện trường, cho phép các nhà phát triển viết mã của họ theo cách mô-đun hóa và hộp cát đã thỏa thuận, để không “gây ô nhiễm hệ sinh thái”.
IIFE (Immediately-Invoked Function Expression)
Tất cả bắt đầu ở đây, đây là dạng mô-đun lâu đời nhất trong JavaScript.
Biểu thức hàm được gọi ngay lập tức (IIFE) là một hàm ẩn danh được gọi khi nó được khai báo. Nó không thực sự là một mẫu mô-đun, nó là một mẫu bao bọc giúp đóng gói mã và giữ nó cách ly với các phần khác của ứng dụng.
TẠO MODULE
SỬ DỤNG PHỤ THUỘC
Bao gồm “mô-đun” IIFE trong tài liệu HTML của bạn dưới dạng
AMD
Asynchronous Module Definition
(AMD) Định nghĩa mô-đun không đồng bộ đã đạt được sức hút trên giao diện người dùng, với RequestJS là cách triển khai phổ biến nhất.
Đây là mô-đun foo
với một phụ thuộc duy nhất vào jquery
:
Và một ví dụ phức tạp hơn một chút với nhiều phụ thuộc và nhiều phương thức được tiếp xúc:
Phần đầu tiên của định nghĩa là một mảng các phần phụ thuộc, trong khi phần thứ hai về cơ bản là hàm gọi lại chỉ được thực thi khi các phần phụ thuộc có sẵn (các trình tải tập lệnh như RequestJS đảm nhiệm phần đó, bao gồm cả việc tìm ra vị trí của các tệp) .
Lưu ý rằng sự phụ thuộc vào thứ tự biến là quan trọng (ví dụ: jquery-> $, underscore->_).
Cũng lưu ý rằng chúng ta có thể ánh xạ các phụ thuộc vào bất kỳ biến tùy ý nào mà chúng ta muốn ở đây. Nếu chúng tôi thay đổi $ thành \(trong đoạn mã trên, tất cả các tham chiếu jQuery trong khối chức năng của chúng tôi sẽ\) thay vì $.
Và lưu ý, quan trọng nhất, bạn không thể tham chiếu các biến $
và _
bên ngoài hàm, vì nó được đóng hộp cát từ mã khác. Đó là mục tiêu ở đây!
Sử dụng phụ thuộc
- AMD imports các mô-đun không đồng bộ (do đó có tên).
- AMD được tạo ra cho front end (khi nó được đề xuất) (trong khi CJS là back end).
- Cú pháp của AMD kém trực quan hơn CJS. Tôi nghĩ về AMD như người anh em đối lập hoàn toàn với CJS.
CommonJS
CJS là viết tắt của CommonJS
Mẫu này phát triển từ mẫu AMD dựa trên trình duyệt để sử dụng trong Node.js ở phía máy chủ. Nó sử dụng module.exports
để xác định các mô-đun và require('...')
bao gồm chúng như một phần phụ thuộc.
CommonJS là một phong cách bạn có thể quen thuộc nếu bạn viết bất cứ điều gì bằng Node (sử dụng một biến thể nhỏ). Nó cũng đang đạt được sức hút trên giao diện người dùng với Browserify.
Sử dụng định dạng tương tự như trước đây, đây là foomô-đun của chúng tôi trông như thế nào trong CommonJS:
Và ví dụ phức tạp hơn của chúng tôi, với nhiều phụ thuộc và nhiều phương thức được hiển thị:
Sử dụng phụ thuộc
- Một số bạn có thể nhận ra ngay cú pháp CJS từ node. Đó là bởi vì node sử dụng định dạng mô-đun CJS.
- CJS imports đồng bộ mô-đun.
- Bạn có thể import từ thư viện
node_modules
hoặc dir địa phương. Hoặc bởiconst myLocalModule = require('./some/local/file.js')
hoặcvar React = require('react');
đều hoạt động. - Khi CJS import, nó sẽ cung cấp cho bạn một bản sao của đối tượng được import.
- CJS sẽ không hoạt động trong trình duyệt. Nó sẽ phải được chuyển đổi và đóng gói.
UMD: Universal Module Definition
Vì phong cách CommonJS và AMD đều phổ biến như nhau, nên có vẻ như vẫn chưa có sự đồng thuận. Điều này đã tạo ra sự thúc đẩy cho một mẫu “phổ quát” hỗ trợ cả hai kiểu, điều này đưa chúng ta đến không gì khác ngoài Định nghĩa Mô-đun Chung.
Mô hình này được thừa nhận là xấu, nhưng cả AMD và CommonJS đều tương thích, cũng như hỗ trợ định nghĩa biến “toàn cầu” kiểu cũ:
Và giữ nguyên mẫu như các ví dụ trên, trường hợp phức tạp hơn với nhiều phụ thuộc và nhiều phương thức được tiếp xúc:
Sử dụng phụ thuộc
Có 3 cách để làm việc với mô-đun UMD:
- Hoạt động ở front và back end (do đó có tên universal).
- Không giống như CJS hoặc AMD, UMD giống như một mẫu để cấu hình một số hệ thống mô-đun. Kiểm tra ở đây để biết thêm các mẫu.
- UMD thường được sử dụng như một mô-đun dự phòng khi sử dụng trình gói như Rollup / Webpack
SystemJS & ES6 module’s
Giai đoạn tiếp theo trong quá trình phát triển và mẫu mô-đun trường hợp hiện đại nhất và tốt nhất để sử dụng ngày nay, tính đến năm 2020, được gọi là System
, System.register
hoặc đơn giản là mô-đun ES6. Điều này làm cho việc sử dụng cú pháp import ... from './module'
. Nó được thiết kế để hỗ trợ cú pháp mô-đun ES6 trong môi trường JavaScript ES5. Cú pháp về cơ bản giống với cú pháp của mô-đun ES6, vì vậy tôi đã gộp các ví dụ này lại với nhau ở đây để đơn giản hóa. Mẫu này thường được sử dụng làm tiêu chuẩn vàng trong một ứng dụng được xây dựng bằng TypeScript.
Tạo mô-đun
Sử dụng phụ thuộc
- Hoạt động trên nhiều trình duyệt hiện đại
- Nó có tính năng tốt nhất của cả hai thế giới: cú pháp đơn giản giống CJS và không đồng bộ của AMD
- Có thể Tree-shakeable, do cấu trúc mô-đun tĩnh của ES6
- ESM cho phép các nhà cung cấp dịch vụ gói như Rollup loại bỏ mã không cần thiết, cho phép các trang web gửi ít mã hơn để tải nhanh hơn.
Bản tóm tắt
ESM
là định dạng mô-đun tốt nhất nhờ vào cú pháp đơn giản, tính chất không đồng bộ và khả năng chuyển động của cây.UMD
hoạt động ở mọi nơi và thường được sử dụng như một dự phòng trong trường hợp ESM không hoạt độngCJS
là đồng bộ và tốt cho back end.AMD
không đồng bộ và tốt cho giao diện người dùng.
Tham khảo:
- What is AMD, CommonJS, and UMD?
- What are CJS, AMD, UMD, and ESM in Javascript?
- The Evolution of JavaScript Module Patterns
- Closures, IIFEs, module pattern trong Javascript
- Module Pattern trong Javascript
- ES6 - Từ cơ bản tới nâng cao (Phần 3)
- Cách mà Google & Amazon quét sạch hàng ngàn JS developers xấu số chỉ bởi 1 câu interview đơn giản!
- Cách viết JavaScript hiện đại: Phần 2: CommonJS module
- JavaScript modules
- Sử dụng RequireJS và AMD để module hóa code JavaScript
- Sử dụng RequireJS và AMD để module hóa code JavaScript
- Tìm hiểu về module system, CommonJS và require