从0到1搭建React企业级3D项目(附源码,自带无3D和3D分支)

494 阅读11分钟

代码我就不放文章末尾恶心人了,需要自提:

分支信息:

  • master: 3D项目附带全景Demo
  • react-app-no-3D: 纯React项目,没有3D相关配置

代码仓库地址:gitee.com/stone710/re…

项目搭建的脚手架用的是vite(^5.4.10),需要注意node版本最好是16+

image.png

开始搭建项目

npm create vite@latest

首先给项目命名,接着选择框架

bf4384ee99274b1cdfa326c506d79e7.png

接着选择语言,我这边选择的是TypeScript + SWC,下面科普一下什么是SWC

SWC 是一种高性能的 JavaScript 和 TypeScript 编译器,常被用作 Babel 的替代品。它旨在提高代码编译的速度和效率,特别适合大型项目或需要快速迭代的开发环境。Vite 等现代前端构建工具集成了 SWC,以加快开发服务器的启动时间和构建过程。

image.png

到这项目就已经搭建起来了,接下来就是安装一些依赖

基础依赖安装

Less:CSS预处理器

npm i --save less

Axios:HTTP库

npm i --save axios

gasp:动画库

gasp是目前我用过比较顺手的库,几乎能满足我的所有需求

npm i --save gasp

规范依赖安装

安装eslint

ESLint 主要用于代码 linting,检测代码中的潜在错误和不符合编码规范的问题。确保代码的正确性和可维护性,帮助开发人员遵守编码规范。

npm i eslint -D

初始化eslint

npx eslint --init

接下来就按着截图选吧

image.png image.png image.png image.png image.png image.png

初始化以后会在项目内添加eslint.config.js文件,具体配置就不在这详细讲了直接上配置

import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
import prettier from "eslint-config-prettier";

/** @type {import('eslint').Linter.Config[]} */
export default [
  { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
  { languageOptions: { globals: { ...globals.browser, process: true } } }, // 添加 process 到全局变量
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReact.configs.flat.recommended,
  {
    plugins: {
      prettier
    },
    rules: {
      // React 相关规则
      'react/react-in-jsx-scope': 'off', // 使用 React 17+ 时,不需要在 JSX 文件中导入 React
      'react/prop-types': 'off', // 使用 TypeScript 时,可以关闭 prop-types 检查
      'react/jsx-filename-extension': ['warn', { extensions: ['.tsx'] }], // 允许在 .tsx 文件中使用 JSX

      // TypeScript 相关规则
      '@typescript-eslint/explicit-module-boundary-types': 'off', // 不强制要求导出函数和类的公共类方法的显式返回和参数类型
      '@typescript-eslint/no-explicit-any': 'warn', // 警告使用 any 类型
      '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], // 禁止未使用的变量,但忽略以下划线开头的参数

      // 常用的代码风格规则
      'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境警告 console 的使用
      'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 生产环境禁止使用 debugger
      'prefer-const': 'error', // 优先使用 const
      'no-var': 'error', // 禁止使用 var
      'eqeqeq': ['error', 'always'], // 要求使用 === 和 !==

      // 函数相关规则
      'func-style': ['error', 'expression'], // 优先使用函数表达式而不是函数声明
      'arrow-body-style': ['error', 'as-needed'], // 当只有一个表达式时,省略箭头函数的大括号

      // 错误预防规则
      'no-unused-expressions': 'error', // 禁止出现未使用过的表达式
      'no-use-before-define': ['error', { functions: false, classes: true, variables: true }], // 禁止在变量定义之前使用它们
    },
  }
];

配置好后我们需要安装ESLint插件

image.png

安装prettier

prettier 是一个代码格式化工具,旨在自动化地格式化代码,使其符合一致的风格标准。它支持多种编程语言,包括 JavaScript、TypeScript、HTML 和 CSS 等。

eslint-config-prettier 是一个 ESLint 配置包,用于禁用与 Prettier 冲突的 ESLint 规则,确保 ESLint 和 Prettier 可以和谐共存。

eslint-plugin-prettier 是一个 ESLint 插件,它将 Prettier 的格式化规则作为 ESLint 规则运行,确保代码在保存时自动格式化

npm install prettier eslint-config-prettier eslint-plugin-prettier -D

在根目录下添加.prettierrc.cjs文件

module.exports = {
  // 一行最多允许的字符数
  // 默认值:80
  // 建议值:90
  printWidth: 90,

  // 每个缩进级别的空格数
  // 默认值:2
  // 建议值:2
  tabWidth: 2,

  // 是否使用制表符而不是空格缩进行
  // React 项目通常使用空格
  // 默认值:false
  useTabs: false,

  // 在语句末尾是否需要分号
  // 默认值:true
  // 建议值:true
  semi: true,

  // 是否使用单引号
  // React 项目中通常使用单引号
  // 默认值:false
  // 建议值:true
  singleQuote: true,

  // 对象属性引用的时间
  // 可选值:"<as-needed|consistent|preserve>"
  // as-needed:仅在必要时添加引号
  // consistent:始终添加引号
  // preserve:保留原有引号
  // 默认值:as-needed
  quoteProps: 'as-needed',

  // 在 JSX 中使用单引号而不是双引号
  // React 项目中通常使用双引号
  // 默认值:false
  // 建议值:false
  jsxSingleQuote: false,

  // 多行时尽可能打印尾随逗号
  // 可选值:"<none|es5|all>"
  // none:不添加尾随逗号
  // es5:在多行对象和数组中添加尾随逗号
  // all:在所有多行结构中添加尾随逗号
  // 默认值:none
  // 建议值:es5
  trailingComma: 'es5',

  // 在对象字面量中的括号之间打印空格
  // 默认值:true
  // 建议值:true
  bracketSpacing: true,

  // JSX 标签的反尖括号是否需要换行
  // 默认值:false
  // 建议值:false
  jsxBracketSameLine: false,

  // 在单独的箭头函数参数周围包括括号
  // 可选值:"<always|avoid>"
  // always:始终包括括号
  // avoid:避免不必要的括号
  // 默认值:always
  // 建议值:always
  arrowParens: 'always',

  // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
  // 默认值:0 和 Infinity
  rangeStart: 0,
  rangeEnd: Infinity,

  // 指定要使用的解析器,不需要在文件开头写 @prettier
  // 默认值:false
  // 建议值:false
  requirePragma: false,

  // 不需要自动在文件开头插入 @prettier
  // 默认值:false
  // 建议值:false
  insertPragma: false,

  // 使用默认的折行标准
  // 可选值:"<always|never|preserve>"
  // always:总是折行
  // never:从不折行
  // preserve:保留原有折行
  // 默认值:preserve
  // 建议值:preserve
  proseWrap: 'preserve',

  // 指定 HTML 文件的全局空格敏感度
  // 可选值:"<css|strict|ignore>"
  // css:遵循 CSS 规范
  // strict:严格处理空格
  // ignore:忽略空格
  // 默认值:css
  // 建议值:css
  htmlWhitespaceSensitivity: 'css',

  // 换行符使用方式
  // 可选值:"<auto|lf|crlf|cr>"
  // auto:保持现有的行尾
  // lf:适用于 Unix/Linux
  // crlf:适用于 Windows
  // cr:仅适用于旧版 Mac
  // 默认值:auto
  // 建议值:lf
  endOfLine: 'lf',
};

在根目录下添加.prettierignore文件

package.json
.cache
.shadowenv.d
.vscode
build
node_modules
prisma
public
.github
tmp
*.yml
.shopify
.js

接下来只要安装对应的插件即可

image.png

安装Stylelint

npm install stylelint-config-recommended-less stylelint-config-standard stylelint-less stylelint-order stylelint-prettier -D

在根目录下添加.stylelintignore.stylelintrc.cjs


*.min.css

*.js
*.ts
*.jsx
*.tsx
*.jpg
*.png
*.eot
*.ttf
*.woff
*.json

/test/
/dist/
/node_modules/
/lib/
module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-recommended-less',
    'stylelint-prettier/recommended'
  ],
  plugins: ['stylelint-order'],
  // 不同格式的文件指定自定义语法
  overrides: [
    {
      files: ['**/*.(less|css|html)'],
      customSyntax: 'postcss-less'
    },
    {
      files: ['**/*.(html)'],
      customSyntax: 'postcss-html'
    }
  ],
  rules: {
    'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep']
      }
    ],
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['deep']
      }
    ],
    // 指定样式的排序
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'justify-content',
      'align-items',
      'float',
      'clear',
      'overflow',
      'overflow-x',
      'overflow-y',
      'padding',
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left',
      'margin',
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left',
      'width',
      'min-width',
      'max-width',
      'height',
      'min-height',
      'max-height',
      'font-size',
      'font-family',
      'text-align',
      'text-justify',
      'text-indent',
      'text-overflow',
      'text-decoration',
      'white-space',
      'color',
      'background',
      'background-position',
      'background-repeat',
      'background-size',
      'background-color',
      'background-clip',
      'border',
      'border-style',
      'border-width',
      'border-color',
      'border-top-style',
      'border-top-width',
      'border-top-color',
      'border-right-style',
      'border-right-width',
      'border-right-color',
      'border-bottom-style',
      'border-bottom-width',
      'border-bottom-color',
      'border-left-style',
      'border-left-width',
      'border-left-color',
      'border-radius',
      'opacity',
      'filter',
      'list-style',
      'outline',
      'visibility',
      'box-shadow',
      'text-shadow',
      'resize',
      'transition'
    ]
  }
}


同上安装相关插件

image.png 然后我们需要在根目录下面创建.vscode文件夹,在下面添加settings.json文件,在里面配置默认的代码格式工具,以及相关的一些配置

{
    // 设置默认的代码格式化工具为 Prettier
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    
    // 在保存文件时自动格式化代码
    "editor.formatOnSave": true,
    
    // 不要求项目根目录存在 Prettier 配置文件
    "prettier.requireConfig": false
}

到这里规范相关配置已经告一段落了,但是有人会经常漏了装插件导致功能异常(没错那个人就是我

032CA5E7.gif),那么我们在.vscode文件夹下面添加一个文件extensions.json,将上面安装的插件添加进去当我们vscode里面没有指定插件的时候,右下角将会有提示让你安装。

image.png

{
  "recommendations": [
    "stylelint.vscode-stylelint", 
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "eamodio.gitlens",
    "cssho.vscode-svgviewer"
  ]
}

Git Hook安装

当提交代码的时候,如果要去执行脚本一下代码检查就很麻烦了,这就需要Huskylint-staged上场了。两者结合使用,可以构建出一个高效的代码检查和格式化工作流,特别适合多人协作的开发环境,有助于维持项目的代码质量。

安装Husky

npm install husky -D

接下来就是初始化项目,初始化前记得先绑定远程仓库不然就会报错了。

image.png

npx husky init

初始化以后会在根目录下面创建.husky文件夹

安装lint-staged

npm install lint-staged -D

package.json中添加脚本

"pre-commit": "lint-staged"

image.png

在根目录下面创建.lintstagedrc文件

{
  "src/**/*.{html,jsx,js,ts,tsx,json,md}": [
    "prettier --write",
    "eslint --fix",
    "stylelint --fix"
  ]
}

最后一步,修改.husky/pre-commit文件

npm run pre-commit

然后就可以测试一下功能正不正常,我们可以尝试提交内容到本地仓库(git commit),然后打开vscode终端,选择输出再选择GIT即可

image.png 然后就可以发现lint-staged是可以正常运行的.

提交代码报错:All input files were ignored because of the ignore pattern. Either change your input, ignore pattern or use "--allow-empty-input" to allow no inputs

这个是因为提交代码时styleLint没有匹配的文件导致报错,需要取消严格模式,全局搜索stylelint --fix,然后修改脚本

"stylelint --fix --allow-empty-input"

项目调整

去除严格模式

StrictMode 是 React 提供的一个工具,用于帮助开发者发现并解决潜在的问题。

StrictMode是一个发现问题的功能,但是有时候也会带来很奇怪的问题,我不喜欢,干掉!!!(因人而异不一定要删除

打开main.tsx文件,去掉StrictMode

企业微信截图_17323228785663.png

添加路径别名

路径别名允许你在项目中使用自定义的路径前缀来引用模块,从而简化导入路径,提高代码的可读性和可维护性。

vite.config.ts修改配置

import path from 'path';
export default defineConfig({
    resolve: {
        alias: {
            '@': path.resolve(__dirname, 'src'),
            Pages: path.resolve(__dirname, 'src/pages'),
            Type: path.resolve(__dirname, 'src/type'),
            Components: path.resolve(__dirname, 'src/components'),
            Api: path.resolve(__dirname, 'src/api'),
        }
    }
})

引入path以后eslint会报错没有对应类型,所以我们需要安装node的类型

npm install --save-dev @types/node

然后需要在typeScript配置文件里面添加这些别名,这里踩了一个坑,这里的tsconfig.json文件内容是这个样子的

{
  "files": [],
  "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
}

这里有两个文件tsconfig.app.json主要用于客户端应用的编译配置,tsconfig.node.json主要用于服务器端或 Node.js 应用的编译配置。所以应该在tsconfig.app.json中添加配置信息

{
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"],
      "Pages/*": ["src/pages/*"],
      "Type/*": ["src/type/*"],
      "Components/*": ["src/components/*"],
      "Api/*": ["src/api/*"]
    },
    ....
}

配置本地服务器配置

vite.config.ts修改配置

export default defineConfig({
    server: {
        port: 8080,
        host: '0.0.0.0',
        open: true, // 启动时在浏览器打开
        proxy: {},
    }
})

配置路由信息

安装react-dom插件

npm install react-dom react-router-dom --save-dev

route文件夹下创建index.tsx,并且在type文件夹下创建类型文件

import { lazy } from 'react';
import { RouterItem } from 'Type/router';
const Layout = lazy(() => import('Components/Layout.tsx'));
const Home = lazy(() => import('Pages/Home/index.tsx'));
const routes: RouterItem[] = [
  {
    name: 'Index',
    path: '/',
    element: <Layout />,
    children: [
      {
        name: 'Home',
        path: '/',
        element: <Home />,
        children: [],
      },
    ],
  },
];

export default routes;
export interface RouterItem {
  name: string;
  path: string;
  element: React.ReactNode;
  children: RouterItem[];
}

然后配置main.tsx文件,引入BrowserRouter跟路由配置

import { createRoot } from 'react-dom/client';
import './index.css';
import { BrowserRouter } from 'react-router-dom';
import App from './App.tsx';

createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

接着创建Layout组件,在这个组件内我们可以设置网页的固定元素比如页眉和页脚

import { Outlet } from 'react-router-dom';

export default function Layout() {
  return (
    <>
      {/* Header */}
      <Outlet />
      {/* Footer */}
    </>
  );
}

创建Home组件

import { useState } from 'react';

const Home = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
};
export default Home;

常用功能(可选)

环境变量

首先安装dotenv插件

npm install dotenv-cli --save-dev

在项目根目录下创建.env.dev.env.production文件添加公共的引入前缀VITE_PUBLISH_PREFIX,并且修改package.json的脚本运行配置

{
  "scripts": {
    "dev": "dotenv -e .env.dev vite",
    "build": "dotenv -e .env.production vite build",
  }
}

添加VITE_ENVIRONMENT属性,这里需要注意需要以VITE_为前缀,不然vite无法识别

VITE_ENVIRONMENT='dev'
VITE_ENVIRONMENT='production'

使用方法

import.meta.env.VITE_PUBLISH_PREFIX

3D相关插件安装 (如果你不打算使用3D项目就不用往下看了)

安装three

npm install three @types/three

安装r3f

为啥要用r3f不用原生threejs,可以看《React项目3D可视化利器》

npm install @react-three/fiber -D

安装rect-three-drei

这个是基于r3f的拓展库。里面实现了很多的效果,就不需要我们自己实现.

npm install @react-three/drei

配置eslint

因为r3f大部分对象都是以标签的形式,需要添加特殊的eslint规则,所以需要安装插件

npm install @react-three/eslint-plugin

结尾

到此就已经结束项目的搭建了,毕竟内容比较多,如果大家发现有什么问题可以评论找我反馈。😘