阿里云主机折上折
  • 微信号
Current Site:Index > File organization structure

File organization structure

Author:Chuan Chen 阅读数:25920人阅读 分类: JavaScript

Basic Principles of File Organization

The file organization structure of a JavaScript project directly impacts the maintainability and readability of the code. A good file structure should follow modular principles, grouping related functionalities together while maintaining a reasonable level of depth. A typical project structure usually includes the following core directories:

  • src/ - Contains source code
  • public/ - Contains static resources
  • tests/ - Contains test code
  • config/ - Contains configuration files
// Example: Basic project structure  
project-root/  
├── src/  
│   ├── components/  
│   ├── utils/  
│   ├── styles/  
│   └── index.js  
├── public/  
│   ├── index.html  
│   └── favicon.ico  
├── tests/  
│   ├── unit/  
│   └── integration/  
└── package.json  

Organizing Files by Feature

Feature-based organization (Functional Organization) groups files according to their role in the application. This structure is particularly suitable for small to medium-sized projects, where each feature module contains all its related files:

src/  
├── auth/  
│   ├── AuthService.js  
│   ├── LoginForm.jsx  
│   ├── RegisterForm.jsx  
│   └── auth.test.js  
├── products/  
│   ├── ProductList.jsx  
│   ├── ProductCard.jsx  
│   ├── ProductApi.js  
│   └── products.test.js  
└── shared/  
    ├── Button.jsx  
    └── Input.jsx  
// Example: Internal structure of a feature module  
// src/products/ProductApi.js  
export const fetchProducts = async () => {  
  const response = await fetch('/api/products');  
  return response.json();  
};  

// src/products/ProductList.jsx  
import { fetchProducts } from './ProductApi';  

const ProductList = () => {  
  const [products, setProducts] = useState([]);  
    
  useEffect(() => {  
    fetchProducts().then(setProducts);  
  }, []);  
    
  return (  
    <div>  
      {products.map(product => (  
        <ProductCard key={product.id} product={product} />  
      ))}  
    </div>  
  );  
};  

Organizing Files by Type

Type-based organization (Type-based Organization) groups files according to their file type. This structure is more common in large projects, especially when multiple technology stacks are used:

src/  
├── components/  
│   ├── Button.jsx  
│   ├── Modal.jsx  
│   └── Input.jsx  
├── containers/  
│   ├── App.jsx  
│   └── MainLayout.jsx  
├── services/  
│   ├── ApiService.js  
│   └── AuthService.js  
├── hooks/  
│   ├── useFetch.js  
│   └── useForm.js  
└── utils/  
    ├── helpers.js  
    └── constants.js  
// Example: Component usage in type-based grouping  
// src/components/Button.jsx  
const Button = ({ children, onClick }) => (  
  <button className="btn" onClick={onClick}>  
    {children}  
  </button>  
);  

// src/containers/MainLayout.jsx  
import Button from '../components/Button';  

const MainLayout = () => {  
  return (  
    <div>  
      <header>  
        <Button onClick={() => console.log('Clicked')}>  
          Menu  
        </Button>  
      </header>  
    </div>  
  );  
};  

Hybrid Organization Structure

In practice, projects often adopt a hybrid organization structure, combining the advantages of feature-based and type-based approaches. A common practice is to divide files by type at the top level and by feature within specific directories:

src/  
├── components/  
│   ├── common/  
│   │   ├── Button.jsx  
│   │   └── Input.jsx  
│   └── features/  
│       ├── auth/  
│       │   ├── LoginForm.jsx  
│       │   └── RegisterForm.jsx  
│       └── products/  
│           ├── ProductList.jsx  
│           └── ProductCard.jsx  
├── pages/  
│   ├── HomePage.jsx  
│   └── ProductPage.jsx  
└── services/  
    ├── ProductService.js  
    └── AuthService.js  

Location of Test Files

There are two main patterns for organizing test files:

  1. Centralized: All test files are placed in a separate tests directory
  2. Distributed: Test files are placed in the same directory as their corresponding implementation files
// Example of distributed test files  
src/  
├── components/  
│   ├── Button.jsx  
│   ├── Button.test.jsx  
│   ├── Input.jsx  
│   └── Input.test.jsx  
└── services/  
    ├── ApiService.js  
    └── ApiService.test.js  

// Example of centralized test files  
tests/  
├── unit/  
│   ├── Button.test.jsx  
│   └── ApiService.test.js  
└── integration/  
    ├── authFlow.test.js  
    └── checkoutFlow.test.js  

Organization of Style Files

The organization of style files also requires consideration. Common patterns include:

  • CSS Modules: Each component has its own style file
  • Global Styles: Shared styles are placed in a separate directory
  • CSS-in-JS: Styles are written directly in the component files
// Example of CSS module structure  
src/  
├── components/  
│   ├── Button/  
│   │   ├── index.jsx  
│   │   └── styles.module.css  
│   └── Input/  
│       ├── index.jsx  
│       └── styles.module.css  
└── styles/  
    ├── base.css  
    ├── variables.css  
    └── utilities.css  

Management of Configuration Files

Project configuration files should be centrally managed to avoid scattering them throughout the project. Typical configurations include:

  • Webpack/Babel configurations
  • ESLint/Prettier configurations
  • Environment variable configurations
  • Project-specific configurations
config/  
├── webpack/  
│   ├── webpack.common.js  
│   ├── webpack.dev.js  
│   └── webpack.prod.js  
├── jest.config.js  
├── .eslintrc.js  
└── .prettierrc.js  

Management of Static Resources

Static resources such as images and fonts should be managed uniformly, typically placed in the public or assets directory:

public/  
├── images/  
│   ├── logo.png  
│   └── background.jpg  
├── fonts/  
│   ├── roboto.woff  
│   └── roboto.woff2  
└── favicon.ico  
// Example of static resource reference  
function Header() {  
  return (  
    <header>  
      <img src="/images/logo.png" alt="Company Logo" />  
    </header>  
  );  
}  

Encapsulation of Third-Party Libraries

Encapsulation of third-party libraries should be centrally managed to avoid direct usage in the project:

// src/lib/axios.js  
import axios from 'axios';  

const instance = axios.create({  
  baseURL: process.env.API_BASE_URL,  
  timeout: 10000,  
});  

export default instance;  

// Using the encapsulated axios in other files  
import http from '../lib/axios';  

const fetchUser = async (id) => {  
  const response = await http.get(`/users/${id}`);  
  return response.data;  
};  

Management of Type Definition Files

In TypeScript projects, the organization of type definition files is important:

src/  
├── types/  
│   ├── user.d.ts  
│   ├── product.d.ts  
│   └── api.d.ts  
└── interfaces/  
    ├── IUser.ts  
    └── IProduct.ts  
// src/types/user.d.ts  
interface User {  
  id: string;  
  name: string;  
  email: string;  
}  

// src/components/UserProfile.tsx  
import { User } from '../types/user';  

const UserProfile: React.FC<{ user: User }> = ({ user }) => {  
  return (  
    <div>  
      <h2>{user.name}</h2>  
      <p>{user.email}</p>  
    </div>  
  );  
};  

Organization of Utility Functions

Utility functions should be categorized by functionality to avoid creating overly large utility files:

// src/utils/  
├── arrayUtils.js  
├── dateUtils.js  
├── stringUtils.js  
└── domUtils.js  

// src/utils/dateUtils.js  
export const formatDate = (date) => {  
  return new Date(date).toLocaleDateString();  
};  

export const daysBetween = (date1, date2) => {  
  return Math.abs(date1 - date2) / (1000 * 60 * 60 * 24);  
};  

Organization of Route Configurations

In single-page applications, route configurations should be centrally managed:

// src/routes/  
├── index.js  
├── routes.js  
└── PrivateRoute.js  

// src/routes/routes.js  
import { lazy } from 'react';  

const Home = lazy(() => import('../pages/Home'));  
const Products = lazy(() => import('../pages/Products'));  

const routes = [  
  {  
    path: '/',  
    component: Home,  
    exact: true,  
  },  
  {  
    path: '/products',  
    component: Products,  
  },  
];  

export default routes;  

Organization of State Management

State management code should be separated from components, especially when using Redux or similar libraries:

src/  
├── store/  
│   ├── actions/  
│   │   ├── userActions.js  
│   │   └── productActions.js  
│   ├── reducers/  
│   │   ├── userReducer.js  
│   │   └── productReducer.js  
│   ├── selectors/  
│   │   ├── userSelectors.js  
│   │   └── productSelectors.js  
│   └── store.js  
└── features/  
    ├── user/  
    │   ├── userSlice.js  
    │   └── userApi.js  
    └── products/  
        ├── productSlice.js  
        └── productApi.js  
// Redux Toolkit example  
// src/features/user/userSlice.js  
import { createSlice } from '@reduxjs/toolkit';  

const userSlice = createSlice({  
  name: 'user',  
  initialState: null,  
  reducers: {  
    setUser: (state, action) => action.payload,  
    clearUser: () => null,  
  },  
});  

export const { setUser, clearUser } = userSlice.actions;  
export default userSlice.reducer;  

Environment-Specific Files

Configuration for different environments should be managed through environment variables rather than creating multiple files:

// config.js  
const config = {  
  development: {  
    apiUrl: 'http://localhost:3000/api',  
  },  
  production: {  
    apiUrl: 'https://api.example.com',  
  },  
};  

export default config[process.env.NODE_ENV || 'development'];  

Organization of Documentation Files

Project documentation should be uniformly managed, including component documentation, API documentation, etc.:

docs/  
├── components/  
│   ├── Button.md  
│   └── Input.md  
├── api/  
│   ├── auth.md  
│   └── products.md  
└── README.md  

Consistency in Naming Conventions

File naming should follow consistent conventions. Common ones include:

  • PascalCase: For React components, e.g., Button.jsx
  • camelCase: For utility functions, e.g., formatDate.js
  • kebab-case: For HTML files, e.g., user-profile.html
// Good naming examples  
components/  
├── UserProfile.jsx  
├── product-list.jsx  
└── utils/  
    ├── formatDate.js  
    └── dom-helpers.js  

Special Considerations for Large Projects

For large projects, a more complex organizational structure may be needed:

src/  
├── core/            # Core framework code  
├── modules/         # Business modules  
│   ├── module1/  
│   └── module2/  
├── platform/        # Platform-specific code  
│   ├── web/  
│   └── mobile/  
└── shared/          # Shared code  
    ├── components/  
    └── utils/  

Automation Tools Assistance

Use tools to automatically maintain file structure, for example:

// Using Plop to generate component templates  
// plopfile.js  
module.exports = function(plop) {  
  plop.setGenerator('component', {  
    description: 'Create a new component',  
    prompts: [{  
      type: 'input',  
      name: 'name',  
      message: 'Component name?'  
    }],  
    actions: [{  
      type: 'add',  
      path: 'src/components/{{pascalCase name}}/index.jsx',  
      templateFile: 'plop-templates/component.hbs'  
    }]  
  });  
};  

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:动画实现规范

下一篇:命名规则

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.