Cách sử dụng các gói npm trong trình duyệt với Browserify

Cập nhật lần cuối: 03/16/2026
  • Trình duyệt thiếu hỗ trợ gốc cho hàm `require` của Node, do đó các mô-đun npm kiểu CommonJS không thể chạy trực tiếp trong JavaScript phía máy khách.
  • Browserify phân tích một tệp đầu vào như main.js, theo dõi tất cả các lệnh require và đóng gói mọi thư viện phụ thuộc vào một tệp JavaScript duy nhất sẵn sàng cho trình duyệt.
  • Việc cài đặt các mô-đun bằng các lệnh như `npm install uniq` cho phép Browserify tải các gói từ thư mục `node_modules` và nhúng chúng vào tệp `bundle.js` được tạo ra.
  • Việc chèn bundle.js thông qua thẻ script tiêu chuẩn trong HTML cho phép mã mô-đun dựa trên npm thực thi mượt mà trong trình duyệt như một tài sản được tối ưu hóa duy nhất.

trình duyệt gói npm

Khi bắt đầu làm việc với các module JavaScript, một trong những khó khăn đầu tiên bạn gặp phải là sự khác biệt giữa cách Node.js tải mã và cách trình duyệt thực hiện việc này. Trong Node, bạn chỉ cần gọi require() Và mọi thứ tự động kết nối với nhau một cách kỳ diệu. Nhưng hãy thử làm điều tương tự trực tiếp trên trình duyệt và bạn sẽ nhanh chóng phát hiện ra rằng chức năng này đơn giản là không tồn tại ở đó. Đó chính là lúc các công cụ, quy trình làm việc và các khái niệm xoay quanh trình duyệt gói npm và các trình đóng gói như Browserify xuất hiện để giải quyết vấn đề.

Bài viết này sẽ hướng dẫn bạn cách npm, với tư cách là một hệ sinh thái gói, kết hợp với ý tưởng duyệt, khám phá và cuối cùng là đóng gói các gói đó để chúng thực sự chạy được trong trình duyệt web. Chúng ta sẽ xem xét lại một ví dụ kinh điển dựa trên Browserify và giải thích lý do tại sao. require Phương pháp này hoạt động trong Node.js nhưng không hoạt động trên trình duyệt, và hướng dẫn từng bước cách chuyển đổi từ một tập tin script nhỏ thành một gói tài sản duy nhất mà bạn có thể chèn vào trang web bằng thẻ script đơn giản. Trong quá trình đó, chúng ta cũng sẽ cung cấp ngữ cảnh, các mẹo thực tế và một số giải pháp thay thế hiện đại để toàn bộ quy trình làm việc trở nên hợp lý cho các dự án thực tế.

Hiểu rõ sự khác biệt giữa Node.js và trình duyệt

Tích hợp trình duyệt Node.js npm

Điểm mấu chốt cần lưu ý là trình duyệt web và Node.js cung cấp các hệ thống mô-đun rất khác nhau ngay từ đầu. Theo truyền thống, Node.js sử dụng định dạng mô-đun CommonJS, trong đó bạn tải các phụ thuộc bằng cách sử dụng require('package-name') và cung cấp chức năng với module.exportsMô hình đó được tích hợp sâu vào môi trường chạy của Node, nhưng các trình duyệt truyền thống lại không hề biết gì về nó.

Trong môi trường trình duyệt thông thường, không có chức năng tích hợp sẵn. require cũng như không có hỗ trợ cho các mô-đun kiểu CommonJS mà hầu hết các gói npm đều dựa vào. Trình duyệt hiểu các thẻ script cổ điển dùng để tải các tệp JavaScript toàn cục, và trong các môi trường hiện đại hơn, nó hỗ trợ các mô-đun ES với... type="module" thuộc tính đó, nhưng nó vẫn chưa tự hiểu được ngữ nghĩa CommonJS của Node.

Sự khác biệt này trở thành vấn đề ngay khi bạn cố gắng tái sử dụng mã kiểu Node hoặc các gói npm trực tiếp bên trong JavaScript phía máy khách. Bạn có thể có một đoạn mã đơn giản như sau: var unique = require('uniq') Điều đó hoạt động hoàn hảo trong một script Node, nhưng nếu bạn dán cùng dòng lệnh đó vào một tệp được tải trong trình duyệt, bạn sẽ ngay lập tức nhận được lỗi tham chiếu, bởi vì require không được xác định.

Do đó, các nhà phát triển cần một loại "cầu nối" nào đó cho phép họ tiếp tục viết mã quen thuộc giống Node.js trong khi vẫn cung cấp các tài nguyên tương thích với trình duyệt. Thông thường, cầu nối đó là một công cụ đóng gói: một công cụ sẽ duyệt qua biểu đồ phụ thuộc của bạn bắt đầu từ một tệp đầu vào, thu thập mọi thứ cần thiết và xuất ra một gói JavaScript duy nhất mà trình duyệt có thể thực thi mà không cần biết gì về Node hoặc npm.

Browserify đóng vai trò gì trong hệ sinh thái npm?

Browserify là một trong những công cụ tiên phong và có tầm ảnh hưởng lớn, đã giải quyết chính xác thách thức này cho các nhà phát triển JavaScript. Mục tiêu của nó rất đơn giản: cho phép bạn viết mã bằng Node.js. require Sử dụng mẫu này, tải các mô-đun từ npm, rồi đóng gói tất cả vào một tệp duy nhất chạy trong trình duyệt như thể CommonJS được hỗ trợ nguyên bản.

Từ góc độ duyệt các gói npm, Browserify biến hệ sinh thái gói Node khổng lồ thành một thư viện các phụ thuộc tiềm năng phía máy khách. Thay vì sao chép thủ công các tập lệnh, bạn chỉ cần cài đặt một mô-đun từ npm và sử dụng nó. require() Tương tự như mã phía máy chủ, và dựa vào Browserify để dịch mã đó thành định dạng mà trình duyệt của người dùng có thể hiểu được.

Về mặt nội bộ, Browserify duyệt qua tất cả các mô-đun được tham chiếu thông qua requireBắt đầu từ một tệp đầu vào nhất định, chương trình sẽ xây dựng biểu đồ phụ thuộc. Đối với mỗi mô-đun trong đồ thị đó, nó sẽ viết lại mã thành dạng mô phỏng môi trường CommonJS trong trình duyệt, bao gồm phạm vi cục bộ và giao diện thân thiện với trình duyệt. require quá trình triển khai. Sản phẩm cuối cùng là một tập tin gói duy nhất, thường được đặt tên là bundle.js, bao gồm tất cả các mô-đun này.

Kết quả cuối cùng là một quy trình làm việc mà các nhà phát triển giao diện người dùng có thể dựa vào các gói từ npm mà không cần lo lắng về việc trình duyệt thiếu hỗ trợ gốc cho các mô-đun Node.js. Bạn có quyền truy cập vào một kho thư viện khổng lồ cho các tác vụ như thao tác dữ liệu, tiện ích hoặc hỗ trợ giao diện người dùng, nhưng vẫn chỉ cần cung cấp một tệp kịch bản duy nhất cho máy khách, tích hợp mượt mà vào các trang HTML truyền thống.

Viết lại ví dụ hướng dẫn Browserify kinh điển

Để dễ hình dung hơn, hãy tưởng tượng bạn có một tệp JavaScript duy nhất có tên là... main.js Trong dự án của bạn, bạn muốn sử dụng một gói npm có tên là... uniq Để lọc các giá trị trùng lặp khỏi một mảng. Trong môi trường Node.js, bạn sẽ bắt đầu tệp bằng một dòng như sau: var unique = require('uniq')Dòng này nhập hàm đã được xuất từ... uniq mô-đun và lưu trữ nó trong một biến có tên là unique.

Bên trong này main.js Từ tệp tin đó, bạn có thể tạo một mảng số đơn giản chứa các mục lặp lại. Ví dụ, bạn có thể thiết lập var data = Trong đó, một số nhất định xuất hiện nhiều hơn một lần. Mục tiêu là tạo ra một mảng mới chỉ bao gồm mỗi số một lần duy nhất, theo thứ tự đã được sắp xếp.

Nhờ sử dụng hàm đã nhập, phần còn lại của mã trở nên rất đơn giản. Bạn có thể gọi console.log(unique(data)) in ra màn hình console mảng được trả về bởi uniq Gói này loại bỏ các giá trị trùng lặp khỏi danh sách. Nếu bạn chạy nó trong Node.js, bạn sẽ thấy một mảng đầu ra trong đó mỗi số chỉ xuất hiện một lần.

Tất cả những lập luận này đều dựa trên giả định rằng uniq Mô-đun này có sẵn trong môi trường của bạn và điều đó require Hàm đã được định nghĩa và có khả năng giải quyết vấn đề. Trong Node.js, điều đó được xử lý bởi runtime và... Thuật toán phân giải mô-đun nút, tìm kiếm một thư mục có tên node_modules và sau đó là một thư mục có tên uniq bên trong nó.

Cài đặt gói uniq từ npm

Trước khi mã của bạn có thể gọi require('uniq')Bạn cần phải cài đặt gói đó từ kho lưu trữ npm. Thao tác này được thực hiện từ dòng lệnh bằng cách sử dụng trình khách npm đi kèm với Node.js. Trong thư mục dự án của bạn, bạn có thể chạy một lệnh như sau: npm install uniq để npm tải xuống mô-đun và lưu trữ nó trong thư mục. node_modules thư mục.

npm install uniq lệnh này sẽ lấy phiên bản đã được xuất bản của uniq đóng gói và thêm nó vào phần phụ thuộc của dự án cục bộ của bạn. Tùy thuộc vào cấu hình npm của bạn và việc bạn có sử dụng hay không. package.json Tệp này cũng có thể ghi lại gói đó vào danh sách các gói phụ thuộc của bạn, đảm bảo quá trình cài đặt nhất quán trên các môi trường khác nhau cho các nhà phát triển khác trong nhóm của bạn.

Sau khi gói phần mềm được cài đặt, cấu trúc thư mục của dự án sẽ bao gồm một thư mục mới. node_modules/uniq thư mục chứa mã của gói đó. Đó chính xác là điều cho phép Node.js require hệ thống định vị mô-đun khi nó được giải quyết 'uniq'Browserify sẽ kiểm tra cùng một thư mục đó khi bắt đầu xây dựng biểu đồ phụ thuộc cho gói ứng dụng của bạn.

Tại thời điểm này, main.js Tệp này là mã Node hoàn toàn hợp lệ, có thể được thực thi trên máy chủ hoặc từ thiết bị đầu cuối bằng trình thông dịch Node tiêu chuẩn. Tuy nhiên, nếu bạn chỉ đơn giản là bỏ qua điều này main.js Nếu bạn chèn tệp vào trang web bằng thẻ script, trình duyệt của bạn vẫn sẽ không hiểu kiểu nhập CommonJS đó, vì vậy bạn cần thêm một bước nữa để làm cho nó tương thích với trình duyệt.

Đóng gói main.js và các phần phụ thuộc của nó vào bundle.js

Bước quan trọng giúp đoạn mã kiểu Node này chạy được trong trình duyệt là cho phép Browserify xử lý. main.js và tất cả các mô-đun cần thiết của nó, sau đó tạo ra một tệp JavaScript duy nhất thường được gọi là bundle.js. Bạn có thể thực hiện việc này từ dòng lệnh sau khi Browserify được cài đặt toàn cục hoặc cục bộ trong dự án của bạn.

Một lệnh điển hình để kích hoạt quá trình này có thể trông như sau: browserify main.js -o bundle.js. Ở đây, browserify là tệp thực thi khởi chạy quá trình đóng gói. main.js là tệp đầu vào mà Browserify coi là gốc của biểu đồ phụ thuộc, và -o bundle.js Hướng dẫn công cụ ghi gói kết quả vào một tệp có tên bundle.js trong thư mục hiện tại.

Đằng sau hậu trường, Browserify phân tích... main.js, theo sau mọi require Hàm này gọi là `finds` và khám phá đệ quy từng mô-đun được nhập khẩu. Điều đó bao gồm cả các tệp cục bộ của riêng bạn nếu bạn yêu cầu chúng bằng đường dẫn tương đối, cũng như các mô-đun của bên thứ ba nằm trong thư mục đó. node_modules, chẳng hạn như uniq Gói bạn vừa cài đặt từ npm.

Mọi thư viện phụ thuộc mà Browserify gặp phải đều được chuyển đổi để có thể chạy bên trong trình duyệt mà không cần môi trường Node gốc. Nó bao bọc mỗi mô-đun trong phạm vi riêng của nó, mô phỏng giao diện CommonJS và đóng gói tất cả các mô-đun đã được chuyển đổi này vào một tập lệnh duy nhất. Kết quả là... bundle.js Tệp này chứa mã mô phỏng require chức năng và cho phép bản gốc của bạn var unique = require('uniq') dòng lệnh này cần hoạt động đúng cách khi được thực thi ở phía máy khách.

Sau khi Browserify hoàn tất, bạn chỉ còn lại một tệp JavaScript duy nhất chứa logic ứng dụng ban đầu cùng toàn bộ cây phụ thuộc bắc cầu cần thiết để ứng dụng hoạt động. Tệp này hiện đã sẵn sàng để được tham chiếu trong trang HTML giống như bất kỳ tập lệnh nào khác, mà không cần bất kỳ cấu hình bổ sung nào ở phía trình duyệt.

Tải gói Browserify vào trang HTML

Với bundle.js Việc tích hợp mọi thứ vào một trang web thông thường được thực hiện đơn giản như thêm một thẻ script vào HTML của bạn. Thay vì cố gắng tải main.js Trực tiếp, bạn tham chiếu đến gói đã biên dịch mà Browserify tạo ra, gói này đã bao gồm sẵn. uniq và bất kỳ mô-đun npm nào khác mà bạn có thể cần.

Một đoạn mã HTML cơ bản có thể chứa nội dung như sau: <script src="bundle.js"></script> ở đâu đó trước khi đóng cửa </body> tag. Thẻ script này yêu cầu trình duyệt tải xuống và thực thi tệp đó. bundle.js tệp. Vì gói này mô phỏng môi trường CommonJS bên trong chính nó, nên các lệnh gọi của bạn đến require Nó hoạt động nội bộ mặc dù môi trường trình duyệt toàn cầu vẫn không biết chức năng đó là gì.

Từ góc độ hiển thị của trang, không có sự khác biệt rõ rệt nào giữa gói mã này và bất kỳ tệp JavaScript đơn lẻ nào khác mà bạn có thể thêm vào. Độ phức tạp của các mô-đun, sự phụ thuộc nội bộ và quá trình mô phỏng. require Toàn bộ logic được gói gọn bên trong bundle.jsTrình duyệt chỉ cần tải và chạy một tài nguyên duy nhất, điều này cũng mang lại lợi thế về hiệu suất so với việc tải nhiều tệp nhỏ riêng biệt.

Do đó, quy trình làm việc này phù hợp ngay cả với các nền tảng giao diện người dùng cũ hơn, nơi bạn có thể làm việc với các tệp HTML tĩnh hoặc các mẫu được render phía máy chủ. Bạn không cần phải thay đổi hoàn toàn cấu trúc trang của mình; bạn chỉ cần thay đổi cách chuẩn bị mã JavaScript để phục vụ, thay thế nhiều tài nguyên rải rác và các mô-đun chỉ dành cho Node bằng một gói được sắp xếp hợp lý do Browserify tạo ra.

Vì sao việc đóng gói bằng Browserify lại quan trọng đối với việc duyệt gói npm

Khi mọi người nói về "trình duyệt gói npm" hoặc việc duyệt các gói npm để sử dụng cho giao diện người dùng, câu hỏi thường gặp là: làm thế nào tôi có thể thực sự sử dụng mô-đun này trong một dự án dựa trên trình duyệt? Sự tồn tại của các công cụ như Browserify biến danh mục lý thuyết về các thư viện phía máy chủ thành một bộ công cụ thực tiễn mà bạn có thể áp dụng trực tiếp trong các ứng dụng web của mình.

Trên thực tế, điều này có nghĩa là việc tìm kiếm các module hữu ích trên npm không còn bị giới hạn ở Node hoặc công việc lập trình phía máy chủ nữa. Nếu bạn tìm thấy một thư viện tiện ích nhỏ hoạt động hoàn toàn trên các cấu trúc dữ liệu JavaScript và không phụ thuộc vào các API dành riêng cho Node, rất có thể bạn có thể sử dụng nó trong trình duyệt bằng cách tích hợp nó với Browserify hoặc một công cụ tương tự. Điều đó sẽ mở rộng đáng kể các lựa chọn của bạn khi giải quyết các vấn đề như loại bỏ các phần tử trùng lặp trong mảng, chuyển đổi dữ liệu hoặc triển khai các thuật toán nhỏ.

Hơn nữa, việc đóng gói dữ liệu giúp giảm số lượng yêu cầu mạng mà trang web của bạn phải thực hiện khi tải. Thay vì sử dụng các thẻ script riêng biệt cho từng tệp cục bộ hoặc thư viện từ xa, tất cả được hợp nhất vào một thẻ duy nhất. bundle.js Tài sản này hoạt động tốt với bộ nhớ đệm HTTP và có thể đơn giản hóa quy trình triển khai, đặc biệt khi bạn đang xử lý các ứng dụng phức tạp dựa trên nhiều mô-đun npm.

Từ góc độ bảo trì, việc có thể luôn luôn dựa vào... require Và việc quản lý phụ thuộc của npm giúp cho mã nguồn giao diện người dùng của bạn trở nên dễ dự đoán và có tính mô-đun hơn. Bạn cài đặt, cập nhật và gỡ bỏ các mô-đun bằng lệnh npm, kiểm tra các phụ thuộc một cách tập trung và để Browserify xử lý việc chuyển đổi cần thiết để đảm bảo khả năng tương thích với trình duyệt, thay vì phải sao chép tệp thủ công hoặc nhúng mã của bên thứ ba theo cách tùy tiện.

Mối liên hệ với các công cụ JavaScript hiện đại

Mặc dù ví dụ kinh điển mà chúng ta đã xem xét tập trung cụ thể vào Browserify, nhưng mô hình cơ bản mà nó minh họa vẫn là nền tảng của nhiều công cụ xây dựng giao diện người dùng hiện đại. Các công cụ đóng gói mới hơn như Webpack, Rollup, Parcel hoặc Vite cũng giải quyết vấn đề chuyển đổi các mô-đun được viết theo một kiểu nhất định thành các gói mà trình duyệt có thể thực thi hiệu quả.

Các trình duyệt hiện đại giờ đây hỗ trợ mô-đun ES một cách tự nhiên thông qua <script type="module">Điều này làm thay đổi một phần bức tranh nhưng không loại bỏ hoàn toàn nhu cầu về các bước xây dựng có hỗ trợ npm. Nhiều gói trong hệ sinh thái npm vẫn để lộ các điểm truy cập CommonJS hoặc dựa vào cơ chế phân giải kiểu Node, và ngay cả khi có sẵn các bản dựng mô-đun ES, việc đóng gói vẫn rất có giá trị đối với việc tối ưu hóa, loại bỏ mã không cần thiết và đảm bảo hành vi tải nhất quán.

Trong bối cảnh rộng hơn này, ví dụ nhỏ sử dụng require('uniq'), npm install uniqbrowserify main.js -o bundle.js Lệnh này không chỉ là một hướng dẫn đơn giản. Nó minh họa quy trình cốt lõi "viết mã theo module, cài đặt các thư viện phụ thuộc từ npm, sau đó tạo ra một gói thân thiện với trình duyệt", một mô hình được chia sẻ bởi hầu hết các thiết lập front-end chuyên nghiệp hiện nay, ngay cả khi các công cụ cụ thể khác nhau.

Do đó, việc hiểu cách Browserify hoạt động sẽ giúp bạn dễ dàng hơn trong việc hiểu các công nghệ mới hơn. Thay vì coi các công cụ đóng gói hiện đại như những hộp đen, bạn có thể thấy điểm tương đồng: tất cả đều đọc các tệp đầu vào, theo dõi các lệnh import hoặc require, thu thập các phụ thuộc, chuyển đổi mã và xuất ra các gói mà trình duyệt tải thông qua các thẻ script đơn giản. Hệ sinh thái gói npm, hệ thống module và công cụ đóng gói cùng nhau tạo nên trải nghiệm liền mạch trong quá trình phát triển hàng ngày.

Tổng hợp tất cả lại thành một quy trình làm việc thực tế.

Tóm lại, quy trình làm việc thực tế được thể hiện trong ví dụ ban đầu như sau: bạn bắt đầu bằng cách viết mã ứng dụng của mình vào một tệp như sau: main.js sử dụng require Để nhập bất kỳ mô-đun npm nào bạn muốn sử dụng. Trong tệp đó, bạn có thể gọi var unique = require('uniq'), định nghĩa các mảng như sau: và ghi kết quả vào bảng điều khiển. Về mặt lý thuyết, bạn đang làm việc như thể tất cả những điều này sẽ chạy trên Node.js.

Bước tiếp theo là đảm bảo các mô-đun đó thực sự tồn tại trong dự án của bạn bằng cách cài đặt chúng bằng npm, ví dụ như thông qua npm install uniq. Hành động này sẽ điền vào node_modules thư mục này cho phép cả Node và Browserify truy cập vào mã của mô-đun để có thể phân giải và đưa nó vào khi cần thiết.

Sau khi mã và các thư viện phụ thuộc đã được thiết lập, bạn hướng dẫn Browserify thu thập mọi thứ một cách đệ quy bắt đầu từ tệp đầu vào của bạn bằng cách chạy một lệnh như sau: browserify main.js -o bundle.js. Quá trình đó duyệt qua cây phụ thuộc, bao bọc từng mô-đun để mô phỏng môi trường CommonJS trong trình duyệt, và cuối cùng ghi ra kết quả. bundle.js là một tệp tin duy nhất chứa tất cả mã cần thiết.

Cuối cùng, bạn chuyển sang HTML và chỉ tham chiếu đến tệp đầu ra duy nhất này bằng thẻ script thông thường như sau: <script src="bundle.js"></script>. Trang này không yêu cầu cú pháp đặc biệt nào; sự phức tạp nằm hoàn toàn bên trong gói mã. Trình duyệt tải xuống và thực thi gói mã đó. bundle.jsvà đoạn mã bên trong nó chạy như thể require Cơ chế hoạt động đã được tích hợp vào chính trình duyệt.

Bằng cách tuân theo mô hình này, bạn sẽ thu hẹp khoảng cách giữa hệ thống module của Node và môi trường trình duyệt một cách hiệu quả, đồng thời vẫn được hưởng lợi từ hệ sinh thái gói npm khổng lồ. Bạn duyệt qua các gói, cài đặt chúng, yêu cầu chúng và sau đó gửi một tệp được tối ưu hóa đến người dùng, giữ cho cả trải nghiệm phát triển và môi trường thời gian chạy đều dễ quản lý và hiệu quả.

Nhìn từ góc độ tổng quan, sự kết hợp giữa npm, các module kiểu Node và một công cụ đóng gói như Browserify sẽ biến một tập hợp các tệp JavaScript rải rác thành một hệ thống quản lý tài nguyên mạch lạc, sẵn sàng cho trình duyệt. Các nhà phát triển có thể viết mã theo dạng mô-đun, phụ thuộc vào các gói được cộng đồng duy trì và vẫn cung cấp một tập lệnh duy nhất cho các trang web của họ, làm cho việc phát triển JavaScript hiện đại vừa có khả năng mở rộng vừa dễ tiếp cận trên nhiều công cụ và môi trường khác nhau.

ataque Shai-Hulud a la cadena de suministro de npm
Bài viết liên quan:
Shai-Hulud: el ataque que sacude la cadena de suministro de npm
bài viết liên quan: