Bắt đầu với eslint

Eslint (https://eslint.org/) là thư viện mã nguồn mở cho phép chúng ta phân tích source code để tìm ra những lỗi sai.

Những lỗi sai trong source code rất đa dạng, chúng bao gồm những lỗi vi phạm khi viết code không theo một chuẩn nào đó (thí dụ như thiếu dấu chấm phẩy cuối câu, đặt debugger trong source code…). Mục đích của việc viết code cần tuân theo 1 chuẩn nào đó để chúng ta có thể thống nhất trong việc style code trong toàn dự án.

Bên cạnh việc áp đặt chúng ta viết code theo chuẩn định sẵn, eslint còn giúp chúng ta phát hiện những đoạn code bị lỗi cú pháp hoặc có thể gây ra lỗi runtime (thí dụ cộng 2 biến mà có thể 1 biến có kiểu dữ liệu là chuỗi còn 1 biến có kiểu dữ liệu là số, quên khai báo 1 biến mà đã sử dụng). Thật là 1 công cụ có ích ^^. Chúng ta hãy cùng nhau bắt tay vào làm nào.

Cài đặt

Để cài đặt Eslint, chúng ta cần phải có Nodejs (tối thiểu là version 8.10.0)

Để kiểm tra, chúng ta có thể bật Terminal và kiểm tra bằng lệnh

node -v

Sau đó chúng ta sẽ cài đặt bằng lệnh

npm install -g eslint

Thành quả của chúng ta sẽ là

Ở trên do máy mình có eslint sẵn rồi nên nó ra vậy, tứm lại là khi các bạn cài, cứ không ra lỗi thì xem như hoàn tất.

Tiếp theo, chúng ta sẽ tạo ra 1 folder chứa project và sau này chúng ta sẽ làm việc hoàn toàn trong folder đó luôn.

Chúng ta sẽ khởi tạo 1 dự án mới bằng lệnh

npm init -y

Lệnh trên sẽ khởi tạo nhanh 1 dự án mới cho chúng ta với những cấu hình mặc định (tên, version, description…) Nếu muốn chi tiết hóa những cấu hình này, chúng ta bỏ flag -y ra.

Ta sẽ có kết quả là:

Tiếp theo chúng ta sẽ chạy lệnh

eslint --init

Nó sẽ bắt đầu hỏi mình những câu hỏi

How would you like to use ESLint?

  • To check syntax only -> Giúp chúng ta kiểm tra cú pháp và đảm bảo code chúng ta đúng theo chuẩn
  • To check syntax and find problems -> Giống như trên, nhưng còn kiểm tra xem có vấn đề nào (những lỗi tiềm ẩn) trong code không 
  • To check syntax, find problems, and enforce code style -> Giống cái thứ 2, nhưng ngoài ra, eslint còn đảm bảo code chúng ta tuân theo 1 chuẩn cụ thể nào đó như AirBnb, Google….

What type of modules does your project use?

  • Javascript module (import/export) -> Nếu source code của bạn có sử dụng Babel (là trình biên dịch từ ECMAScript sang Javascript đuợc sử dụng trong các framework, library như Angular, React) thì bạn chọn option này.
  • CommonJS (require/exports) -> Chọn option này nếu bạn không sử dụng Babel, thí dụ trong các dự án Nodejs hoặc dự án web đơn giản.

Which framework does your project use?

  • React
  • Vue
  • None of these

Does your project use TypeScript? -> Bạn có đang xài typescript trong dự án không?

Where does your code run?

  • Browser -> Nếu dự án của bạn viết để chạy trên nền browser.
  • Node -> Nếu dự án của bạn chạy trên môi trường Nodejs.

How would you like to define a style for your project?

  • Use a popular style guide -> Cho phép chúng ta chọn lựa style từ các bộ style guide phổ biến như AirBnB, Standard và Google.
  • Answer questions about your style -> Chúng ta sẽ quyết định style.
  • Inspect your JavaScript file(s) -> Chưa biết cái này là gì. 😦

What format do you want your config file to be in?

  • Javascript -> Format file eslint sẽ là .eslintrc.js
  • YAML-> Format file eslint sẽ là .eslintrc.yaml
  • JSON -> Format file eslint sẽ là .eslintrc.json

Ở bước cuối, ta nhấn Y để bắt đầu tải về các gói thư viện mà eslint cần để chạy đuợc.

Sau khi hoàn tất cài đặt, Now, It time to play

Sử dụng

Mình sẽ tạo ra 1 file index.js để bắt đầu viết 1 số dòng code đầu tiên.

Trong hình trên, mình tạo ra nội dung file là

function addNumber(a, b){
  return x + 1;
}

Sau đó, mình chạy lệnh eslint index.js và kết quả là

trong hình trên, lỗi .... is defined but never used nghĩa là biến đó đuợc khai báo nhưng không đuợc dùng, 'x' is not defined tức là biến đó chưa đuợc khai báo nhưng đã sử dụng …

như vậy đấy, việc sử dụng eslint cực kì đơn giản, chúng ta sẽ tìm hiểu về các cách để tích hợp eslint ở phần sau.

Tiếp theo, chúng ta tìm hiểu qua về các cấu hình eslint hỗ trợ cũng như tập rule.

Các option trong eslint

Chúng ta có thể cấu hình các option của eslint bằng 2 cách

  • Configuration Comments: cấu hình các lựa chọn bằng các comment trực tiếp trong các file
  • Configuration Files sử dụng file eslintrc để cung cấp các thông tin cấu hình trong toàn bộ thư mục hiện hành và thư mục con. Ta có thể sử dụng file .eslintrc.* hoặc cấu hình bằng thuộc tính eslintConfig trong file package.json hoặc ta còn có thể khai báo các options bằng các tham số dòng lệnh.
const getFinalContext = (context) => {
        /* eslint-disable-next-line no-unused-vars */
        const { calls, ...finalContext } = context;
        return finalContext;
    }

Trên đây là 1 thí dụ về cấu hình các option của eslint bằng comment trực tiếp trong file.

Chúng ta hiện tại đang quan tâm về các option mà eslint hỗ trợ, vậy nên, chúng ta bắt đầu bằng cách xem file .eslintrc.*.

Khi kiểm tra file eslintrc, ta sẽ thấy đuợc nội dung cơ bản

module.exports = {
  env: {
    browser: true,
    es6: true,
  },
  extends: [
    'airbnb-base',
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  rules: {
  },

};

env xác định môi trường thực thi, mỗi môi trường thực thi khác nhau xác định tập các biến toàn cục khác nhau (thí dụ các biến toàn cục của Nodejs là: global, module, process, console…. Link).

env.browser File thực thi sẽ được chạy trên môi trường browser hay không,

env.es6 xác định file thực thi sẽ có chứa tất cả các tính năng của ECMAScript 6.

Còn nhiều option khác nữa, chúng ta có thể tham khảo qua link Specifying Enviroments

extends Ta có thể mở rộng tập hợp các luật đuợc bật lên từ các bộ rule khác đuợc định nghĩa sẵn thông qua thuộc tính này

Để tìm hiểu nhiều hơn chúng ta có thể xem qua phần Extending Configuration Files

globals dùng thuộc tính này sẽ giúp ta định nghĩa một số biến toàn cục sử dụng trong file mà không cần khai báo trước. Thuộc tính này là 1 đối tượng với key là tên biến và value là thuộc tính của biến ( writable cho phép biến có thể ghi và readonly chỉ cho phép đọc mà không chi ghi, off trong trường hợp chúng ta muốn không cho phép một số biến toàn cục của môi trường trong source code)

parserOptions ESlint cho phép ta chỉ định phiên bản JS cần hỗ trợ. Mặc định, ESlint chỉ hỗ trợ ES5 chúng ta có thể thay đổi để cho phép hỗ trợ cả ES6, ES7 hay JSX.

Các thuộc tính của parserOptions

ecmaVersion chỉ định version của ECMAScript mà chúng ta sẽ dùng (khi đó, ứng với từng version, eslint sẽ nhận ra đuợc cú pháp của nó để không báo lỗi). (giá trị mặc định là 5)

sourceType: Giá trị mặc định là “script” tức là không có chia theo module. Bạn có thể set nó thành “module” nếu muốn tổ chức code theo module.

ecmaFeatures những tính năng bổ sung thêm

globalReturn

impliedStrict bật strict mode mặc định

jsx bật bộ phân tích JSX.

experimentalObjectRestSpread bật tính năng Object Rest Spread.

rules tập các luật. Mình sẽ đi chi tiết hơn trong phần sau.

Tìm hiểu cơ bản về rule

Rule là tập các luật quy định mà chúng ta buộc phải tuân thủ khi viết code. Chúng ta có thể thiết lập các luật này trực tiếp trong file eslintrc.* hoặc trong các comment trên file source code.

/* eslint eqeqeq: "off", curly: "error" */

Đoạn trên là 1 ví dụ về set rule trong các file source code.

{
    "rules": {
        "eqeqeq": "off",
        "curly": "error",
        "quotes": ["error", "double"]
    }
}

Đoạn trên là 1 ví dụ về set rule trong file eslintrc.*

Mỗi luật sẽ đi kèm với giá trị off hoặc 0 để tắt rule, warn hoặc 1 để báo warning và error hoặc 2 để báo lỗi và dừng chương trình.

Để nghiên cứu nhiều hơn về các thao tác với rules (disable, enable theo file…) các bạn có thể tham khảo chi tiết tại đây.

Rules

Phần này mình trình bày về rules.

Thông thuờng, mặc định, khi chúng ta thiết lập eslint trong dự án, không có rule nào đuợc bật. Chúng ta cần phải bật nó lên hoặc extend từ các bộ rule từ các bên thứ 3 cung cấp (ví dụ có eslint:recommended chứa các rule để ngăn những lỗi phổ biến) .

Đối với 1 số rule, eslint có thể tự fix đuợc bằng cách chỉnh sửa source code (thí dụ rule no-extra-semi – lỗi viết thừa dấu phẩy), và ta sẽ thêm tham số --fix để fix lỗi bằng eslint.

Để xem tập các rules, ta có thể tham khảo link Eslint – Rules.

Mình ví dụ minh họa 1 số rule trong tập hợp Best Practices

accessor-pairsTrong object hoặc class, 1 thuộc tính nếu có phương thức get (hoặc set) thì phải có phương thức set (hoặc get) tương ứng
array-callback-returnTrong các callback của các phương thức mảng (thí dụ filter, map..) bắt buộc phải có lệnh return.
block-scoped-varBắt buộc sử dụng biến trong phạm vi scope nó định nghĩa


eqeqeq
Bắt buộc sử dụng === và !==

no-eval
Không cho phép sử dụng eval()

Một số rule cần thiết

Trong quá trình làm việc, mình thấy 1 số rule sau rất cần thiết với chúng ta.

getter-returnBắt buộc trả về giá trị trong getter. Nếu không trả về giá trị, xem như getter đó vô nghĩa.
no-unreachableKhông cho phép những đoạn code unreachable (thí dụ như những lệnh phía sau lệnh return trong hàm)Để rút gọn code, cũng như sẽ tránh những lỗi không may xảy ra nếu chúng ta return
use-isnanBắt buộc gọi lệnh isNaN() để kiểm tra 1 biến có mang giá trị NaN không.1 biến mang giá trị NaN khi so sánh với NaN sẽ trả về kết quả là false. isNaN() là cách an toàn nhất.
eqeqeqSử dụng === và !== khi so sánhNếu sử dụng ==, Javascript sẽ không kiểm tra kiểu lẫn giá trị. Điều này có thể sẽ gây ra một số lỗi.
no-evalKhông sử dụng hàm eval()Hàm eval() có thể gây ra một số lỗi liên quan đến bảo mật và có thể gây ra lỗ hỗng trong trang web cũng như giảm hiệu suất hệ thống.
no-global-assignKhông gán giá trị cho những biến toàn cục (thí dụ: Window, Object.) Hệ thống sẽ có thể bị lỗi nếu vô tình chúng ta sử dụng những biến này.
no-withKhông sử dụng withSử dụng with đôi khi gây nhầm lẫn cho những lập trình viên không quen với hệ thống
no-shadowKhông cho phép khai báo biến có tên trùng với tên đã khai báo ở scope chaNhằm tránh sử dụng nhầm lẫn
no-undefinedKhông sử dụng tên “undefined” để đặt tên biếnNhằm tránh sử dụng nhầm lẫn

Trong phần tới mình sẽ nói thêm về việc viết 1 custom rule.

Tạm hết..

Give some ideas