× Giới thiệu Lịch khai giảng Tin tức Sản phẩm học viên

Javascript Tools in Action - Từ A-Z các thông tin cơ bản

11/11/2022 01:26

Khám phá một số công cụ JavaScript truy xuất để nâng cấp trò chơi lập trình của bạn.

Khi javascript tiếp tục phát triển, các công cụ (định dạng, linter, Bundler) xung quanh nó tiếp tục trở nên tốt hơn, chúng ta sẽ xem trong bài viết này cách ESLint (linter), Prettier (định dạng) và Husky (Git hooks) có thể cải thiện trải nghiệm nhà phát triển của bạn và có tác động lớn đến ứng dụng của bạn. Vì lợi ích của bài viết này, chúng ta sẽ sử dụng một Reactứng dụng, nhưng hãy nhớ rằng những công cụ này có thể được sử dụng với bất kỳ ứng dụng Javascript / Node nào. Chúng ta sẽ bắt đầu mọi thứ bằng cách tạo một dự án React bằng vitecác bước sau:

npm create vite@latest
Project name: js-tools
Select a framework: react
Select a variant: react
cd js-tools
npm install

ESLint cho chất lượng mã

ESLint là một công cụ giúp bạn tìm và khắc phục các sự cố trong mã JavaScript của mình. Để thêm nó vào ứng dụng của chúng ta, chúng ta sẽ làm theo các bước sau:

cd js-tools
npm init @eslint/config
# we'll need to answer these questions to initialize the config
How would you like to use ESLint? To check syntax and find problems
What type of modules does your project use? JavaScript modules (import/export)
Which framework does your project use? React
Does your project use TypeScript? No
Where does your code run? Browser
What format do you want your config file to be in? Javascript
Would you like to install them now? Yes
Which package manager do you want to use? npm
# we are going to install additional plugins
npm i --save-dev eslint-plugin-react-hooks eslint-plugin-jsx-a11y

Thao tác này sẽ tạo một .eslintrc.cjstệp chứa cấu hình ESLint của chúng ta trong thư mục gốc của ứng dụng, hãy cập nhật tệp cấu hình bằng các plugin đã cài đặt của chúng ta và thêm quy tắc :

const error = 2;

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react/jsx-runtime',
    'plugin:react-hooks/recommended',
    'plugin:jsx-a11y/recommended',
  ],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['react'],
  rules: {
    'no-unused-vars': error,
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
  ignorePatterns: ['node_modules', '.eslintrc.cjs', 'dist'],
};

Chúng ta đang sử dụng các cài đặt được đề xuất cho từng plugin và đã tạo ra no-unused-varslỗi, một bước bổ sung là thêm lintlệnh vào package.jsontệp của chúng ta như sau:

{
  ...,
    "scripts": {
        "dev": "vite",
        "build": "vite build",
        "preview": "vite preview",
        "lint": "eslint --ext js,jsx ."
    },
  ...
}

Bây giờ thiết lập ESLint của chúng ta đã sẵn sàng, chúng ta sẽ cập nhật ứng dụng của mình để thực hiện một số thử nghiệm và xem nó hoạt động như thế nào. Điều đầu tiên cần làm là cập nhật App.jsxtệp bên trong srcthư mục, thành phần này chứa hình ảnh, trình phát video cơ bản và nút chuyển đổi trạng thái phát / tạm dừng trình phát video khi nhấp vào:

import { useEffect, useRef, useState } from 'react';

export default function () {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const heading = 'Hello ESLint + Prettier + Husky';

  useEffect(() => {
    if (!isPlaying) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, []);

  const togglePlay = () => setIsPlaying(!isPlaying);

  return (
    <div>
      <button type="button" onClick={togglePlay}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>

      <div>
        <video
          loop
          playsInline
          ref={videoRef}
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
        />
      </div>

      <div>
        <img src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg" />
      </div>
    </div>
  );
}

Hãy thử và xem những gì đang chạy lintlệnh sẽ báo cáo về App.jsxmã của chúng ta:

Chúng ta có 4 lỗi tuyệt vời 😅 hoặc không quá nghiêm trọng nên ta phải nói rằng, chúng ta vừa bắt gặp nhiều loại lỗi, một số lỗi liên quan đến React, một số lỗi liên quan đến a11y và một lỗi là do quy tắc chúng ta đã thêm để cấm các biến không sử dụng. Điều tuyệt vời về ESLint là nó bắt lỗi cho bạn và cung cấp cho chúng ta chỉ dẫn về giải pháp và tất cả các quy tắc đều được ghi chép rất đầy đủ. Vì vậy, để sửa mã của chúng ta, chúng ta sẽ cần:

- Đặt tên cho thành phần của chúng ta

- Sử dụng biến `tiêu đề` hoặc chỉ cần xóa nó nếu nó vô dụng

- Thêm thẻ `track` cho phụ đề trong trình phát video

- Thêm thuộc tính `alt` với văn bản có ý nghĩa vào phần tử hình ảnh

Sau khi áp dụng các bản sửa lỗi này khi chạy lệnh `lint`, chúng ta không nhận được lỗi nào, mã cố định của chúng ta như sau:

import { useEffect, useRef, useState } from 'react';

export default function App() {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const heading = 'Hello ESLint + Prettier + Husky';

  useEffect(() => {
    if (!isPlaying) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, [isPlaying]);

  const togglePlay = () => setIsPlaying(!isPlaying);

  return (
    <div>
      <h1>{heading}</h1>
      <button type="button" onClick={togglePlay}>
        {isPlaying ? 'Pause' : 'play'}
      </button>

      <div>
        <video
          loop
          playsInline
          ref={videoRef}
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
        >
          <track kind="captions" src="flower-en.vtt" srcLang="en" />
        </video>
      </div>

      <div>
        <img
          alt="Grapefruit slice atop a pile of other slices"
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
        />
      </div>
    </div>
  );
}

Hơi khó chịu khi phải sử dụng lintlệnh trước mỗi lần cam kết và người ta có thể quên làm điều đó, thiết lập git hook có thể hữu ích để tự động hóa tác vụ này và giải quyết vấn đề này và đó là những gì chúng ta sẽ nói về Husky tiết diện.

Prettier để định dạng mã

Prettier là một trình định dạng mã được xác nhận, hỗ trợ nhiều ngôn ngữ và tích hợp với nhiều trình soạn thảo mã. Hãy thêm đẹp hơn vào ứng dụng của chúng ta:

  npm install --save-dev --save-exact prettier

Chúng ta sẽ cần tạo hai tệp ở thư mục gốc của ứng dụng, một .prettierignoretệp để bỏ qua các tệp hoặc thư mục mà chúng ta không muốn định dạng:

node_modules/
dist/
public/

Và một .prettierrc.jsontệp sẽ chứa cấu hình đẹp hơn của chúng ta:

{
  "arrowParens": "always",
  "bracketSameLine": false,
  "bracketSpacing": true,
  "endOfLine": "lf",
  "embeddedLanguageFormatting": "auto",
  "htmlWhitespaceSensitivity": "css",
  "insertPragma": false,
  "jsxSingleQuote": false,
  "printWidth": 80,
  "proseWrap": "always",
  "quoteProps": "as-needed",
  "requirePragma": false,
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "all",
  "useTabs": true
}

Cấu hình Prettier có thể tùy chỉnh, bạn có thể chơi với sân chơi đẹp hơn để tìm cài đặt phù hợp với bạn nhất. Một bước bổ sung để làm cho đẹp hơn hoạt động tốt với ESLint là cài đặt một plugin ESLint bổ sung:

  npm i --save-dev eslint-config-prettier

Chúng ta cũng sẽ cần cập nhật .eslintrc.cjstệp bằng cách thêm prettiervào extendsmảng, chúng ta cần đảm bảo đặt nó ở vị trí cuối cùng để ghi đè các cấu hình khác:

const error = 2;

module.exports = {
  ...,
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react/jsx-runtime',
    'plugin:react-hooks/recommended',
    'plugin:jsx-a11y/recommended',
    'prettier',
  ],
  ...

Chạy đẹp hơn rất dễ dàng và đơn giản, một cách là chạy npx prettier --write .lệnh sẽ định dạng tất cả mã ứng dụng của bạn, cách thứ hai là sử dụng nó từ trình chỉnh sửa của bạn, điều này sẽ tận dụng tối đa từ Prettier, thông qua phím tắt hoặc tự động bất cứ khi nào bạn lưu một tệp tin. Khi một dòng quá dài trong khi mã hóa đến nỗi nó không vừa trên màn hình của bạn, chỉ cần nhấn một phím và xem nó được bao bọc thành nhiều dòng một cách kỳ diệu! Hoặc khi bạn dán một số mã và thụt lề bị lộn xộn, hãy để Prettier sửa nó cho bạn mà không cần rời khỏi trình chỉnh sửa của bạn.

Tuy nhiên, điều gì sẽ xảy ra nếu một trong những nhà phát triển sử dụng trình chỉnh sửa không hỗ trợ đẹp hơn và quên sử dụng prettierlệnh, có một cách để khắc phục sự cố này và đó là chủ đề của phần Husky bên dưới.

Husky cho móc Git

Husky giúp bạn thiết lập các git hook để cài đặt các thông báo cam kết, chạy các bài kiểm tra, mã lint, v.v. khi bạn cam kết hoặc đẩy. Chúng ta sẽ sử dụng nó cùng với lint-staged để tự động hóa việc viết mã và định dạng trước khi cam kết mã.

  npx husky-init && npm install
  npm i --save-dev lint-staged

Thao tác này sẽ tạo một .huskythư mục có pre-committệp. Bước tiếp theo là cập nhật package.jsontệp thành lint-stagedlệnh thiết lập và yêu cầu nó định dạng bất kỳ tệp nào đã thay đổi trong cam kết hiện tại:

{
  ...,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint --ext js,jsx .",
    "prepare": "husky install"
  },
    "lint-staged": {
        "**/*.+(js|jsx|json|css)": "prettier --write --ignore-unknown"
    },
  ...
}

Bước cuối cùng là cập nhật pre-committệp để thiết lập hook của chúng ta để chạy lintlệnh trên tất cả các ứng dụng và tệp đã thay đổi định dạng bằng lint-stagedlệnh:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint
npx lint-staged

Hãy thực hiện một số cấu trúc lại ứng dụng của chúng ta để xem tất cả những điều này hoạt động như thế nào, chúng ta sẽ tạo một VideoPlayer.jsxthành phần và sử dụng nó trong App.jsx:

import { useEffect, useRef } from 'react';

export default function VideoPlayer({ isPlaying, videoSrc, trackSrc }) {
  const videoRef = useRef(null);

  useEffect(() => {
    if (!isPlaying) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, [isPlaying]);

  return (
    <video loop playsInline ref={videoRef} src={videoSrc}>
      <track kind="captions" src={trackSrc} srcLang="en" />
    </video>
  );
}
import { useState } from 'react';
import VideoPlayer from './VideoPlayer';

export default function App() {
  const [isPlaying, setIsPlaying] = useState(false);
  const heading = 'Hello ESLint + Prettier + Husky';

  const togglePlay = () => setIsPlaying(!isPlaying);

  return (
    <div>
      <h1>{heading}</h1>
      <button type="button" onClick={togglePlay}>
        {isPlaying ? 'Pause' : 'play'}
      </button>

      <div>
        <VideoPlayer
          isPlaying={isPlaying}
          trackSrc="flower-en.vtt"
          videoSrc="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
        />
      </div>

      <div>
        <img
          alt="Grapefruit slice atop a pile of other slices"
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg"
        />
      </div>
    </div>
  );
}

Bây giờ chúng ta hài lòng với mã của mình, hãy cam kết các thay đổi của chúng ta và xem nó diễn ra như thế nào.

lỗi cam kết mã husky

Một lần nữa lại xảy ra lỗi 😅 lần này nó kêu lên vì thiếu xác thực đạo cụ và như bạn có thể thấy cam kết của chúng ta không thành công. Hãy khắc phục điều này, bằng cách cài đặt PropTypes trước tiên npm i prop-typesvà cập nhật VideoPlayerthành phần:

import { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';

export default function VideoPlayer({ isPlaying, videoSrc, trackSrc }) {
  const videoRef = useRef(null);

  useEffect(() => {
    if (!isPlaying) {
      videoRef.current.play();
    } else {
      videoRef.current.pause();
    }
  }, [isPlaying]);

  return (
    <video loop playsInline ref={videoRef} src={videoSrc}>
      <track kind="captions" src={trackSrc} srcLang="fr" />
    </video>
  );
}

VideoPlayer.propTypes = {
  isPlaying: PropTypes.bool.isRequired,
  videoSrc: PropTypes.string.isRequired,
  trackSrc: PropTypes.string.isRequired,
};

Sau khi sửa những lỗi đó, cam kết của chúng ta đã thành công sau khi chạy các lệnh định dạng mã và linting. Như bạn có thể thấy với Husky, về cơ bản, chúng ta đã tự động hóa và định dạng bằng cách sử dụng hook cam kết trước này và điều này sẽ tránh bất kỳ mã không mong muốn nào trong cơ sở mã của chúng ta và giải quyết các vấn đề như trình chỉnh sửa không tương thích và quên chạy các lệnh đó.

cam kết mã thành công