diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..303e56a --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,4 @@ +// .commitlintrc.js +module.exports = { + extends: ['@commitlint/config-conventional'] +}; diff --git a/.env b/.env new file mode 100644 index 0000000..e263269 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +// 开发环境优先级: .env.development > .env +// 生产环境优先级: .env.production > .env +// .env 文件 +VITE_IMG_BASE_URL=https://my-image-cdn.com \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..083c815 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +NODE_ENV=development \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..995fca4 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +NODE_ENV=production \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..8b8f583 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,46 @@ +// .eslintrc.js +module.exports = { + root: true, + env: { + browser: true, + es2021: true, + node: true + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + // 1. 接入 prettier 的规则 + 'prettier', + 'plugin:prettier/recommended' + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 'latest', + sourceType: 'module' + }, + // 2. 加入 prettier 的 eslint 插件 + plugins: ['react', '@typescript-eslint', 'prettier'], + rules: { + // 3. 注意要加上这一句,开启 prettier 自动修复的功能 + 'prettier/prettier': 'error', + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'react/react-in-jsx-scope': 'off' + }, + settings: { + react: { + createClass: 'createReactClass', // Regex for Component Factory to use, + // default to "createReactClass" + pragma: 'React', // Pragma to use, default to "React" + fragment: 'Fragment', // Fragment to use (may be a property of ), default to "Fragment" + version: 'detect', // React version. "detect" automatically picks the version you have installed. + // You can also use `16.0`, `16.3`, etc, if you want to override the detected value. + // It will default to "latest" and warn if missing, and to "detect" in the future + flowVersion: '0.53' // Flow version + } + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..42cdacd --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx --no-install commitlint -e diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2330023 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx --no -- lint-staged diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..7549542 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmmirror.com diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..97c49ad --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +// .prettierrc.js +module.exports = { + printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80 + tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个 + useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减 + singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号 + semi: true, // 行尾是否使用分号,默认为true + trailingComma: "none", // 是否使用尾逗号 + bracketSpacing: true, // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 } +}; diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..82af9c6 --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,22 @@ +// .stylelintrc.js +module.exports = { + // 注册 stylelint 的 prettier 插件 + plugins: ['stylelint-prettier'], + // 继承一系列规则集合 + extends: [ + // standard 规则集合 + 'stylelint-config-standard', + // standard 规则集合的 scss 版本 + 'stylelint-config-standard-scss', + // 样式属性顺序规则 + 'stylelint-config-recess-order', + // 接入 Prettier 规则 + 'stylelint-config-prettier', + 'stylelint-prettier/recommended' + ], + // 配置 rules + rules: { + // 开启 Prettier 自动格式化功能 + 'prettier/prettier': true + } +}; diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..e72441c --- /dev/null +++ b/Readme.md @@ -0,0 +1,21 @@ +## 依赖安装说明 + +pnpm create vite ;#React typescript +pnpm install sass -D + +// 为避免类型报错,你需要通过 `pnpm i @types/node -D` 安装类型 +pnpm i @types/node -D #解决 import “path”类型报错 + +//用来自动为不同的目标浏览器添加样式前缀,解决的是浏览器兼容性的问题。 +pnpm i autoprefixer -D + +pnpm install postcss -D + +//用于压缩图片的插件 +pnpm i vite-plugin-imagemin -D + +- 总之,vite 依赖预构建主要做了两件事情: +- 一是将其他格式(如 UMD 和 CommonJS)的产物转换为 ESM 格式,使其在浏览器通过 + + diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..a2bf01b --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './index.css'; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + +); diff --git a/src/variable.scss b/src/variable.scss new file mode 100644 index 0000000..795383b --- /dev/null +++ b/src/variable.scss @@ -0,0 +1 @@ +$theme-color: red diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..91dd38f --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,11 @@ +/// + +interface ImportMetaEnv { + readonly VITE_APP_TITLE: string; + // 自定义的环境变量 + readonly VITE_IMG_BASE_URL: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3d0a51a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..9d31e2a --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..5392d4b --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,124 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// 为避免类型报错,你需要通过 `pnpm i @types/node -D` 安装类型 +import path from 'path'; +// 如果类型报错,需要安装 @types/node: pnpm i @types/node -D +// 自动引入方案 +import { normalizePath } from 'vite'; +import autoprefixer from 'autoprefixer'; +import viteEslint from 'vite-plugin-eslint'; +import viteStylelint from 'vite-plugin-stylelint'; +// 压缩图片插件 +import viteImagemin from 'vite-plugin-imagemin'; + +const variablePath = normalizePath( + path.resolve(__dirname, './src/variable.scss') +); + +// 是否为生产环境,在生产环境一般会注入 NODE_ENV 这个环境变量,见下面的环境变量文件配置 +const isProduction = process.env.NODE_ENV === 'production'; +// 填入项目的 CDN 域名地址 +const CDN_URL = 'xxxxxx'; + +// https://vitejs.dev/config/ +export default defineConfig({ + root: path.resolve(__dirname, './src'), + publicDir: path.resolve(__dirname, './public'), + resolve: { + // 别名配置 + alias: { + '@assets': path.join(__dirname, 'src/assets') + } + }, + //配置生产环境下cdn引用时的自动化的方式来实现地址的替换 + base: isProduction ? CDN_URL : '/', + json: { + // 禁用json按名导入的方式 + // 这样会将 JSON 的内容解析为export default JSON.parse("xxx") + stringify: true + }, + css: { + postcss: { + plugins: [ + autoprefixer({ + // 指定目标浏览器 + overrideBrowserslist: ['Chrome > 20', 'ff > 10', 'ie 10'] + }) + ] + }, + preprocessorOptions: { + scss: { + // additionalData 的内容会在每个 scss 文件的开头自动注入 + additionalData: `@import "${variablePath}";` + } + } + //css module 方案 + // modules: { + // // 一般我们可以通过 generateScopedName 属性来对生成的类名进行自定义 + // // 其中,name 表示当前文件名,local 表示类名 + // generateScopedName: "[name]_[local]_[hash:base64:5]", + // }, + }, + plugins: [ + react({ + // babel: { + // plugins: [ + // // 适配 styled-component + // 'babel-plugin-styled-components', + // // 适配 emotion + // '@emotion/babel-plugin' + // ] + // }, + // 注意: 对于 emotion,需要单独加上这个配置 + // 通过 `@emotion/react` 包编译 emotion 中的特殊 jsx 语法 + // jsxImportSource: '@emotion/react' + }), + viteEslint(), + viteStylelint({ + // 对某些文件排除检查 + exclude: '/windicss|node_modules/' + }), + viteImagemin({ + // 无损压缩配置,无损压缩下图片质量不会变差 + optipng: { + optimizationLevel: 7 + }, + // 有损压缩配置,有损压缩下图片质量可能会变差 + pngquant: { + quality: [0.8, 0.9] + }, + // svg 优化 + svgo: { + plugins: [ + { + name: 'removeViewBox' + }, + { + name: 'removeEmptyAttrs', + active: false + } + ] + } + }) + ], + build: { + // 8 KB + // 决定资源是否打包成单文件的最小体积 + assetsInlineLimit: 8 * 1024 + }, + optimizeDeps: { + include: [ + // 可以通过include参数提前声明需要按需加载的依赖:避免运行时的二次预构建 + ], + exclude: [ + // 用于将某些依赖从预构建的过程中排除。 + ], + // Vite 提供了esbuildOptions 参数来让我们自定义 Esbuild 本身的配置 + // 常用的场景是加入一些 Esbuild 插件: + esbuildOptions: { + // 这个配置主要是处理一些特殊情况,如某个第三方包本身的代码出现问题了。 + plugins: [] + } + } +});