项目工程化 vite

一、项目工程化

1.1初始环境

  • node v18.17.0
  • pnpm 8.7.5
  • vite 4.4.5

1.1.1安装pnpm

pnpm:performant npm ,意味"高性能的 npm"。pnpm由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,极大的优化了性能,扩展了使用场景。被誉为"最先进的包管理工具"

pnpm安装指令

bash 复制代码
npm i -g pnpm

1.1.2搭建脚手架

bash 复制代码
pnpm create vite

进入到项目根目录pnpm i安装全部依赖.

2.2项目配置

一、配置eslint

eslint中文官网:eslint.nodejs.cn/

ESLint最初是由Nicholas C. Zakas 于2013年6月创建的开源项目。它的目标是提供一个插件化的javascript代码检测工具

vite@4.4.5自带.eslintrc.cjs (以下是默认内容, 之后要被全部替换)

cjs 复制代码
module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react-refresh'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}
1.1react环境代码校验插件说明(目前共10个)
md 复制代码
###### 让所有与prettier规则存在冲突的Eslint rules失效,并使用prettier进行代码检查
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-node": "^11.1.0",

###### 运行更漂亮的Eslint,使prettier规则优先级更高,Eslint优先级低
"eslint-plugin-prettier": "^4.2.1",

###### 该解析器允许使用Eslint校验所有babel code
"@babel/eslint-parser": "^7.19.1",

###############################################
"@typescript-eslint/eslint-plugin": "^6.1.0", //typescript对应的eslint 规则插件
"@typescript-eslint/parser": "^6.1.0",
"eslint": "^8.45.0",
"eslint-plugin-react": "^7.33.0",
"prettier": "^3.0.0"

安装指令( 先装7个,再装3个 )

bash 复制代码
pnpm install -D eslint eslint-plugin-import eslint-plugin-react eslint-plugin-node @babel/eslint-parser @typescript-eslint/eslint-plugin @typescript-eslint/parser
1.2修改.eslintrc.cjs配置文件(全选覆盖)
cjs 复制代码
module.exports = {
  // 运行环境
  env: {
    browser: true,
    es2021: true,
    node: true,
    jest: true,
  },
  /* 指定如何解析语法 */
  /** 优先级低于 parse 的语法解析配置 */
  parserOptions: {
    parser: '@typescript-eslint/parser', // 指定解析器
    ecmaVersion: 'latest', // 允许解析那个版本的特性
    sourceType: 'module', // 允许使用 import
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true, // 允许对JSX进行解析
    },
  },
  /* 继承已有的规则 */
  extends: [
    'eslint:recommended', // vite自带
    'plugin:@typescript-eslint/recommended', // vite自带 @typescript-eslint/eslint-plugin的推荐规则
    'plugin:react-hooks/recommended', // vite自带
    'plugin:import/typescript', // eslint-plugin-import 抛出导入等支持的规则
    'plugin:prettier/recommended', // eslint-plugin-prettier 的推荐规则
  ],
  // https://stackoverflow.com/questions/64126764/how-do-i-fix-typescript-compiler-errors-on-css-files
  ignorePatterns: ["**/*.css", "**/*.scss"],
  parser: '@typescript-eslint/parser', // 指定解析器
  plugins: ['react-refresh', '@typescript-eslint', 'react', 'prettier'],
  /*
   * "off" 或 0 - 关闭规则
   * "warn" 或 1 - 打开规则作为警告(不影响退出代码)
   * "error" 或 2 - 打开规则作为错误(退出代码将为 1)
   */
  rules: {
    // react
    'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
    'react/no-children-prop': 'off',

    // eslint(https://eslint.bootcss.com/docs/rules/)
    'no-var': 'error', // 要求使用 let 或 const 而不是 var
    'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-unexpected-multiline': 'error', // 禁止空余的多行
    'no-useless-escape': 'off', // 禁止不必要的转义字符

    // typeScript (https://typescript-eslint.io/rules)
    '@typescript-eslint/no-unused-vars': 'off', // 禁止定义未使用的变量
    '@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore
    '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。
    '@typescript-eslint/semi': 'off',
  },
}
1.3创建.eslintignore忽略文件
file 复制代码
build
dist
node_modules
1.4配置脚本

package.json新增两个运行脚本

json 复制代码
  "scripts": {
    ...
    "fix": "eslint src --fix",
  },

通过pnpm run lint去检测语法,如果出现不规范格式,通过pnpm run fix 修改

二、配置prettier

有了eslint,为什么还要有prettier?eslint针对的是javascript,他是一个检测工具,包含js语法以及少部分格式问题,在eslint看来,语法对了就能保证代码正常运行,格式问题属于其次;

而prettier属于格式化工具,它看不惯格式不统一,所以它就把eslint没干好的事接着干,另外,prettier支持

包含js在内的多种语言。

总结起来,eslint和prettier这俩兄弟一个保证js代码质量,一个保证代码美观。

2.1安装依赖包

先装7个,再装3个

bash 复制代码
pnpm install -D eslint-plugin-prettier  prettier  eslint-config-prettier
2.2创建.prettierrc.cjs, 添加规则
js 复制代码
// https://prettier.io/docs/en/options.html
module.exports = {
  printWidth: 100, //单行长度
  tabWidth: 2, //缩进长度
  useTabs: false, //使用空格代替tab缩进
  semi: false, //句末分号
  singleQuote: true, //js中使用单引号
  jsxSingleQuote: false, // jsx中使用双引号
  quoteProps: 'as-needed', //仅在必需时为对象的key添加引号
  trailingComma: 'all', //多行时尽可能打印尾随逗号
  bracketSpacing: true, //在对象前后添加空格-eg: { foo: bar }
  bracketSameLine: false, //多属性html标签的'>'折行放置
  arrowParens: 'always', //单参数箭头函数参数周围使用圆括号-eg: (x) => x
  requirePragma: false, //无需顶部注释即可格式化
  insertPragma: false, //在已被preitter格式化的文件顶部加上标注
  proseWrap: 'preserve', //什么都不做,让散文保持原样
  htmlWhitespaceSensitivity: 'ignore', //对HTML全局空白不敏感
  vueIndentScriptAndStyle: true, //不对vue中的script及style标签缩进
  endOfLine: 'lf', //结束行形式
  embeddedLanguageFormatting: 'auto', //对引用代码进行格式化
  singleAttributePerLine: false, //在 HTML、Vue 和 JSX 中强制每行使用单一属性
}
2.3创建.prettierignore忽略文件
file 复制代码
/.git
/.vscode
/build
/dist/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*
2.4配置脚本
json 复制代码
 "scripts": {
    ...
    "format": "prettier --write \"./**/*.{tsx,ts,jsx,js,json,html,md}\"",
 }

代码格式化 pnpm run format

三、配置stylelint

stylelint为css的lint工具。可格式化css代码,检查css语法错误与不合理的写法,指定css书写顺序等。

官网:stylelint.io/

我们的项目样式处理使用 xxx.module.css,安装以下依赖:

bash 复制代码
npm init stylelint
3.1 .stylelintrc.cjs配置文件

将生成的 .stylelintrc.json 修改为 .stylelintrc.cjs

cjs 复制代码
// @see https://stylelint.bootcss.com/
module.exports = {
  "extends": [
    'stylelint-config-standard', // 配置stylelint拓展插件
    'stylelint-config-css-modules', // 调整stylelint规则以接受css 模块特定语法
    'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件
    'stylelint-config-prettier', // 配置stylelint和prettier兼容
  ],
  /**
   * null  => 关闭该规则
   * always => 必须
   */
  "rules": {
    "font-family-no-missing-generic-family-keyword": null,
    "font-family-name-quotes": null,
    "selector-class-pattern": null,
    "alpha-value-notation": null,
    "function-url-quotes": null,
    "color-function-notation": null,
  }
}
3.2安装依赖
bash 复制代码
pnpm i stylelint-config-css-modules stylelint-config-recess-order stylelint-config-prettier typescript-plugin-css-modules -D
3.3创建.stylelintignore忽略文件
file 复制代码
/node_modules/*
/dist/*
/html/*
/public/*
3.4运行脚本
json 复制代码
 "scripts": {
    ...
    "fix:style": "npx stylelint \"**/*.css\" --fix",
  },
3.5创建src/custom.d.ts文件, 注意是项目的src文件夹下
ts 复制代码
declare module '*.css' {
  const css: { [key: string]: string }
  export default css
}
3.6配置typescript

在tsconfig.json的compilerOptions中添加插件配置项

json 复制代码
{
  "compilerOptions": {
    ...
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  },
  ...
}
3.7 vscode(可选)

如果使用 vscode 编辑器, 可以在根项目下创建.vscode/settings.json

json 复制代码
{
  "typescript.tsdk":"node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

这样输入styles.的时候就会有提示代码

四、配置husky

在上面我们已经集成好了我们代码校验工具,但是需要每次手动的去执行命令才会格式化我们的代码。如果有人没有格式化就提交了远程仓库中,那这个规范就没什么用。所以我们需要强制让开发人员按照代码规范来提交。

要做到这件事情,就需要利用husky在代码提交之前触发git hook(git在客户端的钩子),然后执行 pnpm run format来自动的格式化我们的代码。

安装 husky

bash 复制代码
pnpm install -D husky

执行

bash 复制代码
npx husky-init

会在根目录下生成个一个.husky目录,在这个目录下面会有一个pre-commit文件,这个文件里面的命令在我们执行commit的时候就会执行

尝试在.husky/pre-commit文件添加如下命令:

file 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm fix
pnpm format
git add .

.husky/pre-commit文件在之后配置 lint-staged 时还要再次被修改! 在这里写是为了理解文件可以写一些什么代码, 方便理解.

当我们对代码进行commit操作的时候,就会执行命令,对代码进行格式化,然后再提交。

五、配置cz-customizable

bash 复制代码
pnpm i -D cz-customizable

根目录创建.cz-config.js

js 复制代码
module.exports = {
  types: [
    {
      value: '✨ feat',
      name: '✨ feat:     新功能',
    },
    {
      value: '🐛 fix',
      name: '🐛 fix:      修复bug',
    },
    {
      value: '🚀 chore',
      name: '🚀 chore:    构建/工程依赖/工具',
    },
    {
      value: '💄 style',
      name: '💄 style:    代码的样式美化',
    },
    {
      value: '♻️ refactor',
      name: '♻️  refactor: 重构',
    },
    {
      value: '⚡️ perf',
      name: '⚡️ perf:     性能优化',
    },
    {
      value: '✅ test',
      name: '✅ test:     测试',
    },
    {
      value: '🎉 init',
      name: '🎉 init:     初始化',
    },
    {
      value: '📝 docs',
      name: '📝 docs:    文档变更',
    },
    {
      value: '⏪️ revert',
      name: '⏪️ revert:   回退',
    },
    {
      value: '🔧 config',
      name: '🔧 config:   修改配置',
    },
    {
      value: '📦️ build',
      name: '📦️ build:    打包',
    },
    {
      value: '👷 ci',
      name: '👷 ci:       CI related changes',
    },
  ],
  messages: {
    type: '请选择提交类型(必填)',
    customScope: '请输入文件修改范围(可选)',
    subject: '请简要描述提交(必填)',
    body: '请输入详细描述(可选)',
    breaking: '列出任何BREAKING CHANGES(可选)',
    footer: '请输入要关闭的issue(可选)',
    confirmCommit: '确定提交此说明吗?',
  },
  allowCustomScopes: true,
  allowBreakingChanges: [':sparkles: feat', ':bug: fix'],
  subjectLimit: 72,
}

配置脚本

json 复制代码
  "type": "commonjs",
  "scripts": {
    ...
    "prepare": "husky install",
    "commit": "cz-customizable"
  },

以后使用 pnpm commit 代替 git commit -m

但这样做还是会有人使用 git commit,所以要配置 commitlint

六、配置commitlint

git log 日志规范

6.1安装规范包

带gitmoji图标( ✨🎨🔥🐛👽️👥🤡🙈🧐🌱 ... )

bash 复制代码
pnpm add @commitlint/cli  commitlint-config-cz  commitlint-config-git-commit-emoji  -D
6.2创建commitlint.config.cjs(注意是cjs),然后添加下面的代码:
cjs 复制代码
module.exports = {
  extends: ['git-commit-emoji', 'cz']
}
6.3在 package.json中配置scripts命令
json 复制代码
# 在scrips中添加下面的代码
  "scripts": {
    ...
    "commitlint": "commitlint --config commitlint.config.cjs -e -V"
  },
6.4配置husky
bash 复制代码
npx husky add .husky/commit-msg 

在生成的commit-msg文件中添加下面的命令

file 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm run commitlint

这样git commit -m就提交不了了,必须用pnpm commit提交!

七、配置 lint-staged

bash 复制代码
pnpm i lint-staged -D

package.json文件

json 复制代码
  "scripts": {
    ...
    "lint-staged": "lint-staged"
  },
  "lint-staged": {
    "./src/*.{html,css,tsx,ts,jsx,js,json,vue}": [
      "eslint src --fix",
      "npx stylelint \"**/*.css\" --fix",
      "prettier --write"
    ]
  },

.husky\pre-commit 文件内容如下:

file 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm run lint-staged

lint-staged 的作用是只校验 git add 中的文件

没有被 git add 的文件不校验

八、强制使用pnpm包管理器工具

团队开发项目的时候,需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,

导致项目出现bug问题,因此包管理器工具需要统一管理!!!

在根目录创建 scripts/preinstall.js文件,添加下面的内容

js 复制代码
if (!/pnpm/.test(process.env.npm_execpath || '')) {
  console.warn(
    `\u001b[33mThis repository must using pnpm as the package manager ` +
    ` for scripts to work properly.\u001b[39m\n`,
  )
  process.exit(1)
}

package.json配置命令

json 复制代码
"scripts": {
  ...
  "preinstall": "node ./scripts/preinstall.js"
},

当我们使用npm或者yarn来安装包的时候,就会报错了。原理就是在install的时候会触发preinstall(npm提供的生命周期钩子)这个文件里面的代码。

九、代码上传前用 jest 测试

todo...

十、配置 @ 别名

打开 vite.config.ts

ts 复制代码
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve('./src')
    }
  }
})

二、项目最终 package.json 配置

json 复制代码
{
  "name": "demo",
  "private": true,
  "version": "0.0.0",
  "type": "commonjs",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "fix": "eslint src --fix",
    "format": "prettier --write \"./**/*.{tsx,ts,jsx,js,json,html,md,vue}\"",
    "fix:style": "npx stylelint \"**/*.css\" --fix",
    "prepare": "husky install",
    "commit": "cz-customizable",
    "commitlint": "commitlint --config commitlint.config.cjs -e -V",
    "lint-staged": "lint-staged",
    "preinstall": "node ./scripts/preinstall.js"
  },
  "lint-staged": {
    "./src/*.{html,css,tsx,ts,jsx,js,json,vue}": [
      "eslint src --fix",
      "npx stylelint \"**/*.css\" --fix",
      "prettier --write"
    ]
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@babel/eslint-parser": "^7.22.15",
    "@commitlint/cli": "^17.7.1",
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.7.0",
    "@typescript-eslint/parser": "^6.7.0",
    "@vitejs/plugin-react-swc": "^3.3.2",
    "commitlint-config-cz": "^0.13.3",
    "commitlint-config-git-commit-emoji": "^1.0.0",
    "cz-customizable": "^7.0.0",
    "eslint": "^8.49.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-import": "^2.28.1",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-prettier": "^5.0.0",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.3",
    "husky": "^8.0.0",
    "lint-staged": "^14.0.1",
    "prettier": "^3.0.3",
    "stylelint": "^15.10.3",
    "stylelint-config-css-modules": "^4.3.0",
    "stylelint-config-prettier": "^9.0.5",
    "stylelint-config-recess-order": "^4.3.0",
    "stylelint-config-standard": "^34.0.0",
    "typescript": "^5.0.2",
    "typescript-plugin-css-modules": "^5.0.1",
    "vite": "^4.4.5"
  }
}

三、react组件通信方式

组件通信方式很重要,不管是项目还是面试都是经常用到的知识点。

  • props: 可以实现父子组件、子父组件、甚至兄弟组件通信(状态提升)
  • context: 可以实现任意组件通信
  • 集中式状态管理等: Redux 等...
  • 消息订阅-发布: pubsub 等...
相关推荐
致博软件F2BPM2 分钟前
Element Plus和Ant Design Vue深度对比分析与选型指南
前端·javascript·vue.js
慧一居士1 小时前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead1 小时前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子7 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina7 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路8 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js