Alibaba Front-end Specification
repository·main·Indexed 22 days ago
https://github.com/alibaba/f2e-specA comprehensive set of coding standards and engineering best practices for front-end development. It includes specification documentation for JS, TS, CSS, HTML, React, and Node.js, alongside automated linting tools such as f2elint, eslint-config-ali, stylelint-config-ali, prettier-config-ali, commitlint-config-ali, and markdownlint-config-ali to enforce compliance across projects.
What's inside f2e-spec
- The CSS Coding Specification defines coding styles and best practices for CSS and its pre-compiled languages, specifically Sass and Less. These rules are designed to ensure consistency across front-end projects. Some of these rules can be automatically enforced using the stylelint tool.
Overview of CSS Coding Specifications
mainThe CSS Coding Specifications cover coding styles and best practices for CSS and its pre-compiled languages, specifically Sass and Less. Many of these rules are designed to be enforced using the stylelint tool.Overview of Alibaba Front-end Specification
mainThe Alibaba Front-end Specification is a set of coding and engineering standards used extensively within Alibaba's economic ecosystem. It aims to reduce collaboration costs and improve project maintainability and stability by unifying coding styles, promoting best practices, and providing automated code defect checks.
The project consists of two main parts:
- Specification Documentation: Detailed rules for various languages (JS, TS, CSS, HTML), frameworks (React, Node.js), and engineering processes (Git, Changelogs).
- Supporting Tools: Automated linting tools to enforce these rules.
You can either read the documentation to understand the standards or use tools like
f2elintto integrate these checks into your project automatically.Validate Keys in for-in Loops
mainWhen using a
for-inloop, always verify that the key belongs to the object's own properties. This prevents the loop from iterating over properties inherited from the prototype chain.Recommended ESLint rule:
guard-for-in// bad for (const key in foo) { doSomething(key); } // good for (const key in foo) { if (Object.prototype.hasOwnProperty.call(foo, key)) { doSomething(key); } }Choose a Git workflow (No Flow, GitHub Flow, or Git Flow)
mainSelect a workflow based on your team size and release requirements:
- No Flow: For single-maintainer projects. Commit directly to
main/master. - GitHub Flow / One Flow: Best for agile development. Uses a single maintenance branch (
main/master). Createfeatureorhotfixbranches frommainand merge back. Versions are typically strictly increasing. - Git Flow: Best for projects with fixed release cycles and long-term maintenance (e.g., Node.js). Uses multiple maintenance branches (e.g.,
LTSbranches) to backport security fixes to older versions.
- No Flow: For single-maintainer projects. Commit directly to
Naming conventions for React components and instances
mainFollow these naming rules to ensure consistency and compatibility with ESLint rules like
react/jsx-filename-extensionandreact/jsx-pascal-case:- File Extensions: Use
.jsx,.tsx,.js, or.tsfor React component files. - Component References: Use PascalCase (UpperCamelCase) when importing/referencing component definitions.
- Component Instances: Use camelCase (lowerCamelCase) when assigning a component instance to a variable.
// bad import reservationCard from './reservation-card'; // good import ReservationCard from './reservation-card'; // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;- File Extensions: Use
Configure DOCTYPE requirements
mainThe
<!doctype html>declaration is Mandatory. It must be at the very beginning of the document and must use lowercase HTML5 syntax.<!-- ✅ good --> <!doctype html> <html lang="zh-CN"></html>Node.js Coding Style: Use Built-in Globals
mainAvoid manually requiring Node.js built-in modules that are already available as global variables. This keeps code cleaner and follows
node/prefer-globalESLint rules.// bad const { Buffer } = require('buffer'); const b = Buffer.alloc(16); // good const b = Buffer.alloc(16); // bad const process = require('process'); process.exit(0); // good process.exit(0);Use egg and typescript/egg configurations
mainStarting from version 15.0.0, the
nodeandtypescript/nodeconfigurations no longer provideeggrelated settings. To lint Egg.js projects, you must use the following configurations instead:- Use
eggfor standard Egg.js projects. - Use
typescript/eggfor Egg.js projects using TypeScript.
- Use
Order class members by priority
mainClass members should follow a consistent order:
- Static vs Instance: Static members (
static) come before instance members. - Type: Properties (
field) come beforeconstructor, which comes before methods (method). - Accessibility:
publicmembers come beforeprotected, which come beforeprivate.
// good class Foo { public static foo1 = 'foo1'; protected static foo2 = 'foo2'; private static foo3 = 'foo3'; public static getFoo1() {} public bar1 = 'bar1'; protected bar2 = 'bar2'; private bar3 = 'bar3'; public constructor() {} public getBar1() {} }- Static vs Instance: Static members (
React Component Creation and Lifecycle Best Practices
mainFollow these rules for defining and managing React components:
- Use ES6 Classes: Use
class extends React.Componentinstead ofcreateReactClass. - Prefer Function Components: If a component has no internal state or refs, use a function component instead of a class component.
- Single Component per File: Each file should contain only one React component (though multiple function components are allowed).
- Avoid
thisin Function Components: Do not usethisinside function components; access props and context directly. - Avoid
React.createElement: Use JSX instead of callingReact.createElementdirectly unless you are not using JSX files. - Avoid Deprecated Lifecycles: Do not use
componentWillMount,componentWillReceiveProps, orcomponentWillUpdate. Useconstructor,componentDidMount, orcomponentDidUpdateinstead. You can use therename-unsafe-lifecyclescodemod to prefix these withUNSAFE_. - No Mixins: Do not use mixins as they introduce implicit dependencies and naming conflicts. Use HOCs or hooks instead.
// good - Use ES6 class class Listing extends React.Component { render() { return <div>{this.state.hello}</div>; } } // good - Use function component for stateless components function Listing({ hello }) { return <div>{hello}</div>; }- Use ES6 Classes: Use
Ensure return statements in array callback methods
mainWhen using specific array methods, you must include a
returnstatement in the callback function to avoid misuse or errors. This applies to the following methods:map,filter,from,every,find,findIndex,reduce,reduceRight,some, andsort.Common Pitfalls:
- Using
mapfor side effects: If you only want to iterate over an array without creating a new one, useforEachinstead ofmap. - Missing
returninreduce: Failing to return the accumulator (memo) in areducecallback will result in aTypeError(e.g.,Cannot set property '...' of undefined).
// bad: map used for side effects instead of forEach myArray.map((item, index) => { myObj[item] = index; }); // good: use forEach for side effects myArray.forEach((item, index) => { myObj[item] = index; }); // bad: missing return in reduce const myObj = myArray.reduce((memo, item, index) => { memo[item] = index; }, {}); // good: return the memo in reduce const myObj = myArray.reduce((memo, item, index) => { memo[item] = index; return memo; }, {});- Using