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 vite
cá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.cjs
tệ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-vars
lỗi, một bước bổ sung là thêm lint
lệnh vào package.json
tệ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.jsx
tệp bên trong src
thư 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 lint
lệnh sẽ báo cáo về App.jsx
mã 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 lint
lệ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 .prettierignore
tệ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.json
tệ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.cjs
tệp bằng cách thêm prettier
vào extends
mả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 prettier
lệ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 .husky
thư mục có pre-commit
tệp. Bước tiếp theo là cập nhật package.json
tệp thành lint-staged
lệ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-commit
tệp để thiết lập hook của chúng ta để chạy lint
lệnh trên tất cả các ứng dụng và tệp đã thay đổi định dạng bằng lint-staged
lệ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.jsx
thà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.
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-types
và cập nhật VideoPlayer
thà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 đó.