本文介绍

一开始,打算用不同的项目加载threejs,后来选择了vite项目,从原生、vue、react三个项目创建,到适配语法检查、风格检查、以及代码提交。三个项目配置好后,分别实现了threejs的加载,

vite简介

Vite(法语意为“快速”,发音同 “veet”)是一个由 Evan You(Vue.js 创始人)创建的现代化前端构建工具。它旨在为现代 Web 项目提供更快速、更敏捷的开发体验。
官方地址:https://cn.vitejs.dev/
官方介绍:Vite 是一个超快的前端构建工具赋能下一代 Web 应用的发展

vite与webpack的区别

webpack

  • 打包构建:当你运行服务时,Webpack 需要先递归地构建应用的所有依赖图,然后将每个模块打包成一个或多个bundle。
  • 服务启动:必须打包完成后,开发服务器才能启动。
  • 热更新(HMR):如果文件发生变化,Webpack 需要重新计算依赖图并重新打包修改过的部分,这使得大项目中会变得非常缓慢。
    在这里插入图片描述

vite

  • Vite 的创新在于它利用了现代浏览器原生支持 ES Module的特性,彻底改变了开发服务器的启动和更新流程。
  • Vite 通过颠覆传统的“先打包,后服务”模式,利用浏览器原生 ESM 和强大的工具(如 esbuild 和 Rollup),为开发者带来了无与伦比的开发体验。它极大地减少了开发者在等待服务器启动和代码更新上的时间,已经成为现代前端开发中 Webpack 的强大替代品,并被许多大型项目和框架(如 Vue)推荐为默认的构建工具。
    在这里插入图片描述

vite应用,创建各种项目

创建命令(命令都是相同的,创建步骤参考后面截图)

pnpm create vite

使用vite创建原生项目

“Vanilla”(香草)是冰淇淋中最基本、最经典的口味。其他口味如巧克力、草莓、曲奇等都是在香草的基础上添加了其他成分。

  • 香草冰淇淋 = 基础、纯粹、原味
  • 其他口味冰淇淋 = 在基础上添加了额外的东西

映射到编程世界:

  • Vanilla JavaScript = 纯粹的原生 JavaScript

  • jQuery / React / Vue 等 = 在 JavaScript 基础上添加了语法糖、抽象层和工具的“风味”

在这里插入图片描述

使用vite创建vue项目

  • 这里vue项目就不多做介绍,之后我们需要在项目中配置eslint、stylelint、以及提交检查等。

在这里插入图片描述

使用vite创建react项目

  • 这里react项目也不多做介绍,最新版的没有交互,就帮我们创建了eslint,手动删除之后重新配置eslint、stylelint、以及提交检查等。

在这里插入图片描述

项目配置语法检查及提交检查

安装依赖

pnpm i -D postcss postcss-html stylelint stylelint-config-recess-order stylelint-config-standard simple-git-hooks chalk lint-staged
npx @antfu/eslint-config@latest

脚本

	...
	"lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "stylelint": "stylelint  \"**/*.{css,scss,less,vue,html}\"",
    "stylelint:fix": "stylelint  \"**/*.{css,scss,less,vue,html}\" --fix",
    "staged:fix": "lint-staged"
    ...

"simple-git-hooks": {
  "pre-commit": "pnpm lint-staged",
  "commit-msg": "node scripts/verifyCommit.js"
}

修改.vscode/settings.json

  // Auto fix
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never",
    "source.fixAll.stylelint": "explicit"
  },

  // stylelint配置
  "stylelint.enable": true,
  // 关闭编辑器内置样式检查(避免与stylelint冲突)
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false,
  "stylelint.validate": [
      "css",
      "less",
      "postcss",
      "scss",
      "sass",
      "vue"
  ],

创建stylelint配置文件

stylelint.config.js

export default {
  // 1. 基础配置,继承两个官方推荐的配置
  // stylelint-config-standard:Stylelint 的标准规则集,涵盖常见的 CSS 规范。
  // stylelint-config-recess-order:强制 CSS 属性按照特定顺序排列(如 position -> display -> margin 等),提高代码可读性。
  extends: ['stylelint-config-standard', 'stylelint-config-recess-order'],

  // 2. 文件解析器
  overrides: [
    {
      files: ['**/*.(html|vue)'],
      customSyntax: 'postcss-html', // 解析 CSS、HTML、Vue(如 Vue 的 <style> 块) 文件
    },
    // 选less可以注释scss
    // {
    //   files: ['*.less', '**/*.less'],
    //   customSyntax: 'postcss-less', // 解析 Less 文件
    // },
    // 选sass可以注释上面的less
    // {
    //   files: ['*.scss', '**/*.scss'],
    //   customSyntax: 'postcss-scss', // 解析 SCSS 文件
    //   rules: {
    //     'scss/percent-placeholder-pattern': null, // 关闭 SCSS 占位符检查
    //     'scss/at-mixin-pattern': null, // 关闭 SCSS Mixin 命名检查
    //   },
    // },
  ],

  // 3. 自定义规则
  rules: {
    // (1) 忽略某些规则: 这些规则被设为 null,表示不检查,通常是为了兼容项目特殊情况。
    'media-feature-range-notation': null, // 允许 `min-width: 768px` 或 `width >= 768px`
    'selector-not-notation': null, // 允许 `:not(.class)` 或 `:not(.class, .other)`
    'import-notation': null,
    'function-no-unknown': null, // 允许未知的 CSS 函数(如自定义函数)
    'selector-class-pattern': null, // 允许任意类名(默认强制 kebab-case)
    'no-empty-source': null, // 允许空样式文件
    'no-descending-specificity': null, // 允许低优先级选择器覆盖高优先级
    'font-family-no-missing-generic-family-keyword': null, // 允许 `font-family: Arial`(不强制加 `sans-serif`)
    'named-grid-areas-no-invalid': null, //  禁用对 CSS Grid 命名区域有效性的检查。

    // (2) 特殊伪类/伪元素处理: 允许 Vue 特有的伪类(如 :global)和伪元素(如 ::v-deep),避免误报。
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['global', 'deep'], // 允许 `:global` 和 `:deep`(Vue Scoped CSS)
      },
    ],
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep', ':deep'], // 允许 `::v-deep` 和 `::deep`(Vue 深度选择器)
      },
    ],

    // (3) 忽略未知的 @ 规则: 允许 TailwindCSS、SCSS/Less 的特殊语法(如 @apply、@mixin)
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          // TailwindCSS
          'tailwind',
          'apply',
          'variants',

          // SCSS/Less 控制语句
          'function',
          'if',
          'each',

          // SCSS Mixins
          'include',
          'mixin',
          'extend',

          'use',
          'responsive',
          'screen',

          'return',
        ],
      },
    ],

    // (4) 其他重要规则
    'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], // 允许微信小程序的 `rpx` 单位
    'rule-empty-line-before': [// 规则前空行(注释后除外)
      'always',
      {
        ignore: ['after-comment', 'first-nested'],
      },
    ],
    'property-no-vendor-prefix': [ // 允许 `-webkit-` 前缀
      true,
      {
        ignoreProperties: ['background-clip'],
      },
    ],
    'selector-id-pattern': null,
  },

  // 4. 忽略文件: 不检查 .js、.jsx、.tsx、.ts 文件(Stylelint 只处理样式文件)
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
}

创建stylelint忽略文件

.stylelintignore

/dist/*
/public/*

node_modules
.husky
.vscode
.idea
*.sh
*.md

stats.html

提交检查配置文件

scripts/verifyCommit.js

// @ts-check
import { readFileSync } from 'node:fs'
import path from 'node:path'
import chalk from 'chalk'

const msgPath = path.resolve('.git/COMMIT_EDITMSG')
const msg = readFileSync(msgPath, 'utf-8').trim()

const commitRE
  // eslint-disable-next-line regexp/no-unused-capturing-group
  = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/

chalk.level = 1
if (!commitRE.test(msg)) {
  console.error(
    `  ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
      'invalid commit message format.',
    )}\n\n${
      chalk.red(
        '  Proper commit message format is required for automated changelog generation. Examples:\n\n',
      )
    }    ${chalk.green('feat(compiler): add \'comments\' option')}\n`
    + `    ${chalk.green(
      'fix(v-model): handle events on blur (close #28)',
    )}\n\n${
      chalk.red('  See .github/commit-convention.md for more details.\n')}`,
  )
  process.exit(1)
}

lint-staged.config.js

/**  @type {import('lint-staged').Config} */
export default {
  '*.{js,jsx,ts,tsx}': ['eslint --fix'],
  '*.json': ['eslint --fix'],
  '*.{scss,less,styl,html,vue}': ['eslint --fix', 'stylelint --fix --allow-empty-input'],
  '*.md': ['prettier --write'],
}

更新

npx simple-git-hooks

pnpm i

最后分别配置eslint的配置文件

下面配置中,分别这样配:vanilla-不用改,vue-启用vue支持,react-启用react支持

import antfu from '@antfu/eslint-config'

export default antfu({
  // 1. 基本配置
  // type: 'lib', // 表示当前项目是一个库(library),而不是应用(app)
  // 2. 代码风格配置(Stylistic)
  stylistic: true, // 或者你可以更加细粒度的设置
  // 3. 格式化工具
  formatters: true, // 使用外部格式化工具(如 Prettier)

  // 4. ts支持
  typescript: true, // 启用 TypeScript 支持

  // 5. vue/react 支持
  // vue: true, // 启用 Vue 支持
  // react: true, // 启用 React 支持

  // 6. 规则覆盖(Rules)
  /**
   * 规则 https://www.wenjiangs.com/docs/eslint,vue规则:https://eslint.vuejs.org/rules/
   * 主要有如下的设置规则,可以设置字符串也可以设置数字,两者效果一致
   */
  rules: {
    'eslint-comments/no-unlimited-disable': 'off',
    'ts/no-use-before-define': 'off',
    'style/no-mixed-operators': 'off',
    'no-console': 'warn',
    'ts/no-unused-expressions': 'off',
    'style/max-statements-per-line': 'off',
    'ts/prefer-namespace-keyword': 'off',
    'antfu/top-level-function': 'off',
    'node/prefer-global/process': 'off',
    'ts/consistent-type-definitions': 'off',
    'ts/ban-ts-comment': 'off',
    'vue/singleline-html-element-content-newline': 'off', // vue 标签强制换行
    // 关闭一些耗时的规则
    'import/no-cycle': 'off',
    'import/no-deprecated': 'off',
    'import/no-named-as-default': 'off',
    'prefer-promise-reject-errors': 'off',

  },

  // 7. 忽略文件(Ignores)
  // 9x版本 忽略文件这种配置方式 废弃掉eslintignore
  // 【注意:ignores 是 @antfu/eslint-config 的配置方式,替代了传统的 .eslintignore 文件】
  ignores: [
    '*.sh',
    'node_modules',
    '*.md',
    '*.woff',
    '*.ttf',
    '.vscode',
    '.idea',
    '/public',
    '/docs',
    '.husky',
    '.local',
    '/bin',
    'Dockerfile',
    '/dist',
    '/src/libs',
    'src/mock',
    '*.min.js',
    '/*.json',
  ],
  // 8. 其他配置
  // 关闭对 JSON 和 YAML 的支持
  // jsonc: false, // 关闭 JSON 支持
  // yaml: false, // 关闭 YAML 支持
  // isInEditor: false, // 保存删除未引入的代码
  // unocss: true, // unocss 检测&格式化 暂时注释 等配置了unocss再开放为true
})

threejs的加载

在项目中运行如下命令

pnpm i -D three @types/three

下载资源中的项目,查看使用方式,下面是原生封装的使用方式

import * as THREE from 'three'

export function setupThree(canvasThree: HTMLCanvasElement) {
  // 1.创建场景
  const scene = new THREE.Scene()

  // 2.创建相机
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000,
  )
  camera.position.set(0, 0, 10)
  scene.add(camera)

  // 3.创建物体(几何体 + 材质 = 物体)
  const boxWidth = 1
  const boxHeight = 1
  const boxDepth = 1
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth)

  const material = new THREE.MeshBasicMaterial({ color: 0x44AA88 })

  const cube = new THREE.Mesh(geometry, material)

  scene.add(cube)

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: canvasThree })

  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight)

  // 渲染场景
  renderer.render(scene, camera)
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐