Bàn về câu lệnh npm run build - tại sao cần phải build?

Bàn về câu lệnh npm run build - tại sao cần phải build?

Vấn đề

npm run build một câu lệnh không quá xa lạ với các lập trình viên Javascript khi chuẩn bị release phiên bản mới của ứng dụng. Theo cách hiểu đơn giản, npm run build thực hiện công việc chuyển đổi mã trong dự án thành mã có thể chạy được trong trình duyệt hoặc Node.js.

Nhưng tại sao lại cần phải có bước build? Bản chất của việc build là gì? Có phải tất cả dự án Javascript/Node.js cần phải build hay không? Hy vọng bạn đọc sẽ tìm được câu trả lời trong bài viết dưới đây.

npm script

package.json là một file có trong các dự án Javascript hay Node.js. Chức năng của nó là lưu trữ một số thông tin về project cũng như thông tin về cấu hình và các chỉ dẫn cho dự án hoạt động. Lấy ví dụ đơn giản, trong package.json lưu trữ lại tất cả các thư viện npm để mỗi khi cần tải các phụ thuộc (dependencies) chỉ cần chạy npm install.

scripts là một thuộc tính trong package.json, nó lưu giữ các giá trị trông giống như dưới đây:

{
  "scripts": {
    "dev": "vite",
    "tsc": "vue-tsc --noEmit",
    "build": "npm run tsc && vite build",
    "build-dev": "vue-tsc --noEmit && vite build --mode development",
    "serve": "vite preview"
  }
}

Khi đó, nếu chúng ta gõ npm run build thì ở bên dưới (background), câu lệnh thực sự chạy đó chính là vue-tsc --noEmit && vite build. Nói cách khác build chỉ là "tên đại diện" cho câu lệnh bạn thực sự muốn chạy. Tôi không thích build thì đổi tên nó thành release không thành vấn đề. Nếu muốn chạy, chỉ cần gõ npm run release thế là xong. npm run release lúc này cũng giống như npm run build trước đó.

scripts sinh ra để che giấu đi sự phức tạp trong việc nhớ các câu lệnh của project. Ở ví dụ trên, việc ghi nhớ npm run build so với vue-tsc --noEmit && vite build theo bạn thì cái nào dễ dàng hơn? Hơn nữa trong một dự án không chỉ sử dụng một lệnh mà có khi là nhiều cho đến cả vài chục. Thậm chí chúng có móc nối đến nhau, nghĩa là lệnh này bằng nhiều lệnh khác cộng lại.

Hãy nhìn vào dòng của lệnh build trên, nó là sự kết hợp của tscvite build. Tạo ra nhiều scripts với độ phân tử giúp bạn có thể tái sử dụng. Việc đặt tên cho chúng còn mang lại ý nghĩa gợi nhớ. Nghĩa là bất kì project nào, nếu mở package.json ra mà thấy có build trong scripts thì chắc hẳn đó chính là lệnh chuẩn bị release phiên bản mới của ứng dụng.

Sự phức tạp của giới trình duyệt/Node.js

Sự phức tạp của giới trình duyệt/Node.js

Javascript sinh ra đã mang nhiều sự phức tạp, nhiều khi bạn không thể hiểu nổi tại sao typeof null == 'object' và vô số những điều vô lý đến thuyết phục khi làm việc với nó. Để giải thích cho điều đó có khá nhiều lý do, một trong những lý do là sự phân mảnh của Javascript. Nếu như với các ngôn ngữ khác, muốn sử dụng nó bạn chỉ cần tải bản cài đặt về rồi cài vào máy là có thể sử dụng. Sau khi phát triển xong, muốn triển khai ứng dụng lên máy chủ thì chỉ cần sử dụng đúng phiên bản cài đặt trước đó thì mọi thứ đều hoạt động. Nhưng với Javascript thì ngược lại, cho phép chạy mã Javascript hay không là quyền thuộc về trình duyệt. Mà trình duyệt thì có rất nhiều và không phải cái nào cũng tuân thủ theo quy tắc của Javascript. Hay nói cách khác, một đoạn mã Javascript chạy tốt trên trình duyệt này nhưng chưa chắc đã chạy trên trình duyệt khác.

Node.js thì hạn chế được sự phân mảnh hơn, vì nó chỉ sử dụng V8 của Chrome. Sử dụng Node.js đồng nghĩa với việc bạn phải dùng V8. Một mặt tích cực khác, Chrome hiện đang là "vua" của trình duyệt thế nên để đáp lại điều đó, nó luôn được cập nhật những tiêu chuẩn của ECMAScript nhanh nhất. Những bản cập nhật luôn mang lại thêm những tính năng mới.

Nhìn lại thực tế, không phải khách hàng nào cũng có phiên bản trình duyệt mới nhất. Không phải tất cả đều sử dụng Chrome hay Firefox… thế nên việc đắn đo liệu mã mình sắp viết đây có chạy được trên tất cả trình duyệt hay không là một điều đáng lo ngại. Ý tưởng của các công cụ hỗ trợ viết một lần "dịch" cho tất cả cũng xuất hiện từ đây.

Có thể bạn đã nghe nói đến babel.js, đây là thư viện chuyển đổi mã Javascript mới hơn về mã mà hầu hết các trình duyệt cả cũ cả mới có thể chạy được. Hiểu đơn giản, nếu bạn muốn dùng các cú pháp Javascript mới nhất mà vẫn có thể chạy được trên các trình duyệt cũ hoặc khác nhau thì babel.js giúp bạn làm điều đó. Bạn cần phải cài đặt babel.js, viết mã rồi sử dụng nó để chuyển đổi mã bạn vừa viết. Đó là lúc lệnh build xuất hiện. Trong build có thể là câu lệnh có sử dụng babel. Thay vì phải gõ một câu lệnh phức tạp thì chúng ta chỉ cần npm run build.

{
  "scripts": {
    "build": "babel src -d lib"
  }
}

Ngày nay với sự ra đời của nhiều Framework hỗ trợ xây dựng ứng dụng dựa trên phản ứng như Angular, React, Vue… càng làm nổi bật thêm các build tools hơn nữa. Về cơ bản, các Framework che giấu sự phức tạp khi phát triển và cho đến lúc release bằng những build tools như webpack, rollup, vite… Điều đó giúp cho nhà phát triển ứng dụng tập trung vào công đoạn viết mã nhiều hơn so với việc đi "phát minh" lại cấu trúc dự án.

Như vậy có phải tất cả ứng dụng cần phải build?

Câu trả lời là không. Như tôi đã nói build chỉ là một "tên đại diện" cho câu lệnh phức tạp, hơn nữa nó còn mang ý nghĩa gợi nhớ. build thường xuất hiện trong dự án có sử dụng các công cụ hỗ trợ compile mã đơn giản thành phức tạp ví dụ như babel, hay các công cụ bundle như webpack, rollup…

Nếu bạn phát triển một ứng dụng thuần Javascript đơn giản mà không sử dụng các công cụ trên, thì rõ ràng bạn không cần phải build. Trình duyệt hay Node.js có thể chạy được những đoạn mã mà bạn viết.

Tổng kết

package.json là một file chứa các thông số và cấu hình cho dự án Javascript/Node.js. scripts là một thuộc tính chứa các giá trị và câu lệnh được chạy tương ứng mỗi khi sử dụng npm run. scripts giúp chúng ta che giấu đi sự phức tạp của câu lệnh và mang ý nghĩa gợi nhớ, build cũng mang ý nghĩa đó.

Vì vậy, các dự án mà có sử dụng đến build tools như babel, webpack… thì mới cần đến build còn lại, nếu bạn phát triển dự án thuần Javascript mà trình duyệt có thể hiểu được luôn thì không cần thiết phải qua bước build nữa.

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (0)