Frontend Development 15 min read

Frontend Development Best Practices and Common Pitfalls

This article presents a comprehensive guide to frontend development best practices, covering commit message standards, dependency management, import ordering, naming conventions, lint configuration, CSS property ordering, inline styles, code duplication, magic numbers, pure functions, and component structuring, with concrete examples and recommendations for improving code quality and maintainability.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Frontend Development Best Practices and Common Pitfalls

Standardization Issues

Meaningless commit messages

It is recommended that everyone understand commit message conventions and configure commit lint for projects to experience the benefits.

Unused and default dependencies

Use depcheck to detect unnecessary dependencies.

Unused dependencies
* @alife/bc-big-brother
* @alife/scc-gangesweb-inquiry
* babel-runtime
* caniuse-lite
Unused devDependencies
* @ali/kyle-config-saga
* style-loader
Missing dependencies
* @src/utils: ./src/utils/do-dot.js
* @alife/bc-safe-log: ./src/utils/log.js
* @src/pages: ./src/pages/template/showroom-list/index.jsx
* @src/modules: ./src/pages/template/showroom-gallery/index-v2.jsx
* @src/components: ./src/pages/template/promotion-venue/index.jsx
* @alife/bc-video-player: ./src/pages/template/pla-detail/product-detail.jsx

Mixing dependencies and devDependencies

Because tnpm flattens dependencies, mixing them works but is considered amateur; consider using peerDependencies for true runtime dependencies.

Import order

In frontend code, imports generally fall into three categories: CSS, project files, and third‑party packages. Although no strict order is mandated, separating them improves readability and can be automated with tools like ESLint and Prettier.

Even the order of fields in package.json can be automatically sorted using sort-package-json .

Method names should be verb phrases

Instead of productListFetch() , prefer fetchProductList for clearer intent.

Leftover console debugging code

Configure ESLint to treat console statements as errors; use eslint-disable only when absolutely necessary.

Improper eslint‑disable scope

Avoid disabling ESLint for an entire file; disable only the specific rule on the line that needs it.

// eslint-disable-next-line no-alert
alert('foo');

Refer to the official documentation for disabling rules: https://eslint.org/docs/latest/user-guide/configuring/rules#disabling-rules

Large commented code blocks

Instead of keeping dead code, rely on Git history and add a TODO marker if removal is postponed.

Misleading file extensions

If a file is named with .ts but contains no TypeScript, rename it to avoid confusion.

CSS property order

Common conventions group properties as layout/position, size, text, and others. Tools like prettier-plugin-style-order can enforce this automatically.

CSS class naming

Use lowercase letters; CSS is case‑insensitive.

Separate words with hyphens (e.g., block-element-modifier ) following BEM conventions.

Avoid single‑word class names to reduce naming collisions.

In CSS Modules, camelCase naming is recommended: https://github.com/css-modules/css-modules#naming

Static inline styles

function Demo() {
  return (
{list.map(product => (
))}
);
}

Inline static styles have two drawbacks: they lack semantic meaning and increase DOM size, affecting download time in SSR scenarios.

Repeated style overrides

Prefer precise scoping over layered overrides.

.container {
  margin: 0 auto;
  color: #333;

  &.mobile {
    color: #444;
  }
}

Can be refactored to:

.container {
  margin: 0 auto;

  &.pc {
    color: #333;
  }

  &.mobile {
    color: #444;
  }
}

Frontend Engineering Issues

Code not merged to master; use GitLab tags for identification.

Version numbers pushed outside the release process cause ordering problems.

Lint not effective; ensure proper configuration and Husky pre‑commit hooks.

README Without Value

A good README should include project description, environment setup, API documentation, and build/release commands, tailored to the project's type.

Common Method Misuse

Mixing forEach and map

Use map only when you need a new array; otherwise prefer forEach .

Array.prototype.map() creates a new array by applying a function to each element of the original array.
arr.map(item => {
  item.name += '--';
});

Optional chaining without compatibility check

Optional chaining simplifies null checks but may break in environments that do not support it.

const children = testObj?.elements?.items;
return (
  <>{
    children.map(item =>
{item}
)
  }
);

Unnecessary callback wrapping

getList()
  .then(list => {
    console.log(list);
  });

Can be simplified to:

getList().then(console.log);

Await causing unnecessary serial calls

When calls are independent, run them in parallel with Promise.all .

const user = await getUser(userId);
const favorites = await getFavaritesByUserId(userId);
setStore(user, favorites);

Better:

Promise.all([getUser(userId), getFavaritesByUserId(userId)]).then(setStore);

Bad Programming Habits

Programming based on symptoms

if (indexOf('test') >= 0) {}
// special handling for top 3 ranks
if (index < 4) {}
if (ieVersion >= 9) {
  // use Array.isArray
}

Rewrite for clarity:

if (indexOf('test') != -1) {}
if (index <= 3) {}
if (typeof Array.isArray === 'function') {}

Exhaustive conditional code

Example of version comparison using nested if statements; a loop simplifies the logic.

function compareVersion(v1, v2) {
  const ver1Arr = v1.split('.').map(Number);
  const ver2Arr = v2.split('.').map(Number);
  for (let i = 0; i < 3; i++) {
    if (ver1Arr[i] > ver2Arr[i]) return 1;
    else if (ver1Arr[i] < ver2Arr[i]) return -1;
  }
  return 0;
}

Magic numbers and constant extraction

if (column > 7) {}

Extract such values into a constants module:

// constants.js
export const MAX_COLUMN = 7;

Functions with side effects

({ activeIndex1, floorArray }) => {
  let finalLiveList;
  if (activeIndex1 === 0) {
    floorArray[0].list[0].cardType = floorArray?.[0]?.cardType;
    finalLiveList = [...floorArray[0].list, ...floorArray[1].list];
  } else {
    finalLiveList = [...floorArray[0].list];
  }
  return (
);
};

Pure functions should avoid mutating input parameters.

Mixing thought process with implementation in render

Separate UI logic from component implementation for readability.

function Component1() {}
function Component2() {}
function Component3() {}
function Component4() {}

function Demo() {
  return (
);
}

Violating DRY principle

Avoid copying and modifying code blocks; refactor shared logic into reusable functions.

Cultivating Good Programming Habits

Writing robust, readable code reflects professional integrity; engineers should treat each line as a representation of themselves.

Technical literacy is the everyday cultivation of good coding habits.

best practicescoding standardslint
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.