NPM link: Cách sử dụng, lợi ích và lưu ý quan trọng

npm link là lệnh trong npm dùng để tạo một liên kết symlink giữa một package cục bộ và dự án đang sử dụng nó, giúp bạn phát triển và thử nghiệm thư viện theo thời gian thực mà không cần publish lên npm registry. Đây là công cụ cực kỳ hữu ích khi bạn muốn chỉnh sửa package local và quan sát ngay lập tức thay đổi trong project.

Đọc bài viết sau để được giải đáp chi tiết hơn về:

  • npm link là gì và hoạt động thế nào?
  • Hướng dẫn cách cài đặt liên kết (link) cho package. 
  • Hướng dẫn chi tiết cách sử dụng npm link.
  • Một số ví dụ thực tế về npm link trong lập trình.
  • Các lỗi thường gặp khi sử dụng npm link.
  • So sánh sự khác biệt giữa npm link vs unlinking.

Đọc chi tiết: NPM là gì: Khái niệm, lệnh và thao tác cơ bản với NPM

npm link được sử dụng để tạo một symlink tới toàn bộ thư mục package gốc (nơi có package.json) và thư mục node_modules của ứng dụng, mà không quan tâm thư mục dist hay thư mục main.

Khi tạo các package NPM, bạn sẽ cần test nó trong một project khác để xem hành vi thực tế khi được dùng làm dependency. Bạn có thể thực hiện điều này bằng cách publish package lên NPM rồi cài lại vào project mỗi lần, hoặc copy package trực tiếp vào thư mục node_modules của project, nhưng cả hai cách đều chậm và dễ gây lỗi.

Lúc này, khi sử dụng npm link sẽ giúp bạn tối ưu quy trình bằng cách dùng project local của mình làm dependency cho project khác mà không cần phải publish hay copy thủ công vào node_modules.

Lưu ý: Từ npm v9 trở đi, npm link KHÔNG tự động thêm dependency vào package.json. Nó chỉ tạo symlink trong node_modules, nhưng không ghi gì vào package.json.

Để liên kết một package bằng npm link, bạn chỉ cần thực hiện hai bước đơn giản sau:

Bước 1: Vào thư mục package gốc mà bạn muốn được liên kết với project khác (package này sẽ được sử dụng như một dependency cho project khác) và chạy lệnh:

npm link

Bước 2: Vào thư mục của project sẽ sử dụng package của bạn như một dependency và chạy lệnh:

npm link <package-name>

Vậy là xong. Sau khi liên kết, bạn có thể chỉnh sửa và build package dependency của mình trong khi project chính đang chạy, và các thay đổi sẽ được cập nhật tự động, giúp bạn debug một cách chính xác và hiệu quả.

Giả sử chúng ta có hai thư mục:

  • web-logger – một package NPM dùng để hiển thị log trực tiếp trên giao diện, tiện cho việc debug mà không cần mở DevTools.
  • test-react-application – một ứng dụng React tạo bằng create-react-app 

Bạn vào project web-logger (sẽ được dùng làm dependency) và chạy lệnh

npm link

Sau đó, trong project test-react-application, tiếp tục chạy:

npm link @bsartori/web-logger

Trong đó: 

  • @bsartori/web-logger là tên package có scope tổ chức. 
  • Sau khi chạy lệnh, bạn sẽ thấy @bsartori/web-logger bên trong thư mục node_modules. Biểu tượng thư mục cho thấy đây là một symlink.

Trong project test-react-application, tiến hành import dependency bằng lệnh:

import logger from '@bsartori/web-logger';

Lưu ý rằng khi di chuột vào tên dependency, bạn có thể thấy đường dẫn gốc của nó (original pathname). Sau khi import dependency, bạn chỉ cần thực hiện một số cấu hình mà dependency yêu cầu và gọi hàm logging của mình. Cuối cùng, lưu file và xem kết quả trực tiếp trên trình duyệt của bạn.

Khi bạn sử dụng npm link để phát triển một module cục bộ, và module đó khai báo React dưới dạng peer dependency, rất dễ gặp lỗi nổi tiếng: “multiple instances of React”. Dưới đây là 2 cách khắc phục:

Cách 1: Liên kết ngược (back-link) dependency React của module về React của ứng dụng

Trong ứng dụng nơi bạn gặp lỗi nhiều phiên bản React:

  • Truy cập vào thư mục: node_modules/react
  • Chạy lệnh: yarn link

Tiếp theo, trong module được link (module local) cũng đang sử dụng React:

yarn link react

Kết quả: Cả hai nơi sẽ đều trỏ về cùng một file React – chính là React nằm trong node_modules/react của ứng dụng. Nhờ đó bạn tránh được lỗi nhiều phiên bản React chạy song song.

Cách 2: Dùng Rescripts 

Rescripts cho phép bạn override cấu hình Webpack của CRA mà không cần eject. Các bước dùng như sau:

  • Cài đặt: yarn add @rescripts/cli
  • Thay các lệnh react-scripts trong project bằng rescripts tương ứng.
  • Thêm file .rescriptsrc.js này vào thư mục gốc của project:
const path = require('path')
const resolveFrom = require('resolve-from')

const fixLinkedDependencies = config => {
  config.resolve = {
    ...config.resolve,
    alias: {
      ...config.resolve.alias,
      react$: resolveFrom(path.resolve('node_modules'), 'react'),
      'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'),
    },
  }
  return config
}

module.exports = [
  fixLinkedDependencies,
]

Chạy ứng dụng bằng lệnh:

yarn start

Liên kết bị hỏng

  • Dấu hiệu: npm hỏi lại bạn có muốn cài package từ registry. Ví dụ:
Need to install the following packages:

create-project-calavera@0.0.5

Ok to proceed? (y)
  • Cách xử lý là chạy lại lệnh:
npm link
npm link <package-name>

Gỡ liên kết (unlinking) trong npm

Khi muốn ngừng sử dụng package được liên kết bằng npm link, bạn cần gỡ symlink theo đúng thứ tự để tránh lỗi.

Trước hết, trong project đang thử nghiệm, chạy:

npm unlink <package-name>

Lệnh này chỉ gỡ link trong project hiện tại, không xóa symlink global. Để xóa hoàn toàn symlink, bạn dùng lệnh:

npm uninstall -g package-name

Lệnh này đảm bảo các lệnh npm create hoặc cài package sau đó sẽ sử dụng phiên bản từ registry thay vì package cục bộ, 

Ví dụ về unlinking

Giả sử bạn đang phát triển một package NPM tên cowabunga với cấu trúc project như sau:

{
  "name": "cowabunga",
  "version": "0.0.1",
  "description": "Component này thông báo khi mọi thứ trở nên tuyệt vời",
  "main": "dist/index.js",
  "keywords": [
    "component",
    "cowabunga",
    "dude"
  ],
  "dependencies": {
    "some-package": "^10.0.1"
  },
  "author": "",
  "license": "ISC",
  "access": "public"
}

Lưu ý: Package này có thư mục node_modules riêng bên trong. Đây là nguồn cơn của nhiều rắc rối: khi bạn đổi branch, thư mục này có thể biến mất. Khi đó symlink của project sẽ không còn tìm thấy dependencies của cowabunga, dẫn đến lỗi: 

npm ERR! enoent ENOENT: no such file or directory, access ‘my_project/node_modules/cowabunga/node_modules/some-package’

Để khắc phục lỗi này có thể xử lý nhanh bằng cách chạy lại npm install trong thư mục cowabunga trước khi unlink.

Gỡ liên kết (Unlinking)

Trước khi chuyển branch hoặc xóa thư mục node_modules trong chính package, bạn cần unlink theo đúng thứ tự để tránh lỗi symlink.

  • Bước 1: Trong project đang dùng package, bạn hãy chạy lệnh
npm unlink cowabunga

Hoặc từ npm 9+ có thể dùng lệnh:

npm uninstall cowabunga

Hai lệnh này chỉ gỡ symlink trong project thử nghiệm.

  • Bước 2: Trong chính thư mục package cowabunga, chỉ cần chạy lệnh npm unlink là npm tự gỡ global symlink

Ngoài ra, bạn nên lưu ý rằng thứ tự sẽ rất quan trọng, vấn đề thường gặp là khi chuyển branch, symlink không thể tìm thấy package nữa. Điều này dẫn đến tình trạng “nửa vời” là bạn không thể link, không thể unlink vì những thư mục cần thiết đã không còn tồn tại.

Khi điều này xảy ra, hãy checkout lại branch ban đầu của bạn và bắt đầu lại từ đầu quy trình linking giữa package và project.

Hoặc bạn cũng có thể chạy 

npm install -g .

Trong thư mục package để cài đặt nó global, giúp tránh được một số rắc rối liên quan đến việc tạo link. 

npm link được lưu trong thư mục global node_modules của npm trên máy tính. Khi bạn chạy npm link trong một package, npm sẽ tạo một symbolic link (symlink) trong thư mục global của npm (npm root -g) trỏ đến thư mục package cục bộ của bạn.

Khi bạn chạy npm link <package-name> trong một project khác, npm sẽ tạo liên kết từ project đó đến symlink global, thay vì cài trực tiếp package từ registry.

Bạn có thể chạy npm uninstall -g <package-name> để xóa link global hoặc npm unlink <package-name> trong project để xóa link local. 

  • Xóa link local trong project: Vào thư mục project và chạy npm unlink <package-name>. Lệnh này sẽ xóa symlink đến package global.
  • Xóa link global: Vào thư mục package gốc và chạy npm uninstall -g <package-name>. Lệnh này xóa symlink global và làm package không còn được liên kết với bất kỳ project nào.
  • Xóa nhiều link: Nếu muốn xóa nhiều link cùng lúc, bạn cần lặp lại lệnh cho từng package. npm không có lệnh duy nhất để xóa tất cả link cùng lúc, nhưng bạn có thể dùng script shell để tự động unlink nhiều package.

Đọc chi tiết: NPM remove package: Cách xoá package khỏi dự án NodeJS

Npm link không có chế độ “vô hiệu hóa”, bạn chỉ có thể unlink package để ngừng sử dụng liên kết. Khi bạn đã tạo link, npm sẽ luôn ưu tiên package cục bộ qua symlink. Để “vô hiệu hóa”, bạn chỉ cần chạy npm unlink trong project hoặc npm unlink -g ở package gốc. Sau khi unlink, project sẽ trở về trạng thái sử dụng package đã được cài từ npm registry thay vì từ thư mục cục bộ.

Ngoài ra, sau khi gỡ symlink, nếu package không có trong package.json, project sẽ báo lỗi Cannot find module. Để dùng lại phiên bản từ registry, bạn phải chạy npm install <package>.

Tổng kết

npm link là giải pháp mạnh mẽ giúp đơn giản hóa việc phát triển và thử nghiệm package trong môi trường cục bộ. Khi hiểu đúng cơ chế hoạt động, bạn sẽ rút ngắn đáng kể thời gian cài đặt, tiết kiệm công sức và cải thiện chất lượng sản phẩm trước khi publish lên npm registry. Hãy tận dụng công cụ này kết hợp với các chiến lược quản lý package hiện đại như workspaces hay monorepo để tối ưu hiệu suất làm việc.

TÁC GIẢ
Tuong Uyen
Tuong Uyen

Senior Content Writer

Có hơn 3 năm kinh nghiệm chuyên thực hiện các phỏng vấn chuyên sâu về kiến thức công nghệ thông tin với nhiều chuyên gia IT thuộc nhiều lĩnh vực IT hấp dẫn như Software Development, Game, Blockchain, Data, RPA,… Với niềm yêu thích và nghiên cứu về những kiến thức nền tảng mà mọi người kỹ sư công nghệ thông tin nào cũng cần phải nắm vững, như C++, Framework Front-End, Web, Mobile, Database,…, Uyên mang đến đa dạng những bài viết kiến thức IT cho mọi người đọc từ cơ bản đến nâng cao.