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?

Tin ngắn hàng ngày dành cho bạn
  • openai/codex là một dự án mã nguồn mở mới nhất của OpenAI, ngay sau khi họ công bố hai mô hình mới nhất là o3 và o4 mini. Nghe nói cả o3 và o4 mini này rất thích hợp làm Agent nên tung ra codex như một dạng Agent nhỏ nhẹ chạy ngay trong Terminal luôn.

    Về tính ứng dụng, vì nó là Agent nên nó có thể đọc/thêm/sửa/xoá nội dung tệp của bạn luôn. Ví dụ.

    codex "explain this codebase to me"

    Hoặc tích hợp vào pipe line của CI/CD.

    - name: Update changelog via Codex run: | npm install -g @openai/codex export OPENAI_API_KEY="${{ secrets.OPENAI_KEY }}" codex -a auto-edit --quiet "update CHANGELOG for next release"

     À quên mất, phải dùng API của OpenAI nha 😆

    » Xem thêm
  • Có thể nhiều người chưa biết, OpenAI đã mở trang học viện riêng để giúp người dùng học tập và khai thác được tối đa sức mạnh các mô hình ngôn ngữ của họ.

    OpenAI Academy

    » Xem thêm
  • Mới sáng ra đã có tin giật gân: OpenAI muốn mua lại Windsurf với giá 3 tỉ đô 😳

    » Xem thêm

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ị phát hành phiên bản mới cho ứ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 Scripts

package.json là một tệp quan trọng có trong hầu hết dự án JavaScript/Node.js. Chức năng của nó là lưu trữ thông tin dự án cũng như cấu hình và các lệnh sẽ được sử dụng. Lấy ví dụ, package.json lưu lại tất cả các thư viện để mỗi khi cần cài đặt các gói 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 câu lệnh thực sự được 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 thực sự muốn chạy. Nếu bây giờ tôi không thích build, đổi tên nó thành release cũng không thành vấn đề. Nếu muốn chạy, chỉ cần gõ npm run release. 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 sẽ được sử dụng trong dự án. Ở 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ễ hơn? Trong một dự án không chỉ sử dụng một lệnh duy nhất mà con số có khi lên đến cả hàng chục. Chúng còn có khả năng 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. Đấy là lúc scripts phát huy tác dụng là một nơi hoàn hảo để lưu trữ lại các giá trị.

Hãy nhìn vào dòng lệnh build trên, nó là sự kết hợp của tscvite build. Tạo ra nhiều lệnh ở cấp độ phân tử giúp bạn có thể tái sử dụng. Việc đặt tên cho chúng mang lại ý nghĩa gợi nhớ. Hãy hình dung khi mở package.json ở bất kỳ dự án nào ra mà thấy có build trong scripts thì chắc hẳn đó chính là lệnh có liên quan đến việc sắp sửa phát hành một phiên bản mới cho ứ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

Bản thân JavaScript 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 thì có nhiều lý do, một trong số đó 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 chỉ cần tải bản cài đặt về rồi cài vào máy là xong. Sau khi viết mã, 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 đó là gần như chắc chắn thành công.

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 loại và không phải cái nào cũng tuân thủ theo quy tắc của JavaScript. Nếu như JavaScript phát hành một phiên bản mới thì trình duyệt ngay sau đó phải tung bản cập nhật để hỗ trợ. Điều gì xảy ra nếu người dùng không chịu cập nhật trình duyệt, hoặc trình duyệt không mặn mà với việc chạy đua theo các tính năng mới nhất của JavaScript? Nói cách khác, một đoạn mã JavaScript chạy được trên trình duyệt này chưa chắc đã chạy trên trình duyệt khác. Điều đó khiến cho lập trình viên JavaScript phải vò đầu bứt tai khi giải quyết bài toán "Hỗ trợ tối đa người dùng Internet".

Node.js 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 khác, Node.js chạy phía máy chủ nên không phải giải quyết bài toán khó như trình duyệt.

Nhìn lại thực tế, không phải người dù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... Lập trình viên luôn e ngại rằng liệu mã sắp viết ra đây có tương thích với tất cả người dùng? Ý tưởng của các công cụ hỗ trợ viết một lần - dùng cho tất cả 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ó 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ũ thì babel.js giúp làm điều đó. Tất cả điều cần làm là cài đặt babel, 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 như ví dụ dưới đây.

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

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 xuất hiện thêm nhiều công cụ chuyển đổi mã 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 phát hành bằng những công cụ 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 trả lời câu hỏi liệu ứng dụng của tôi có chạy tốt trên IE8?

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. 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ợ chuyển đổi mã đơn giản thành phức tạp ví dụ như babel, hay các công cụ đóng gói như webpack, rollup...

Nếu phát triển một ứng dụng JavaScript đơn giản mà không sử dụng các công cụ trên rõ ràng bạn không cần phải qua một bước 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 tệp 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 câu lệnh được chạy tương ứng mỗi khi sử dụng npm run. scripts giúp che giấu đi sự phức tạp của câu lệnh và mang ý nghĩa gợi nhớ, build bao hàm những yếu tố đó.

Vì vậy, các dự án mà có sử dụng đến công cụ hỗ trợ chuyển đổi mã như babel, webpack... thì mới cần đến build. Ngược lại, nếu phát triển dự án đơn giản thì không nhất thiết phải có bước build nữa.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

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.

Bình luận (0)

Nội dung bình luận...