vscode配置:

// setting.json
{
  "editor.formatOnSave": true,
  "typescript.suggest.autoImports": true,
  "typescript.preferences.quoteStyle": "single",
  "typescript.tsdk": "node_modules/typescript/lib",
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.tabSize": 2,
  "editor.inlayHints.fontSize": 10,
  "typescript.inlayHints.parameterNames.enabled": "all",
  "typescript.inlayHints.functionLikeReturnTypes.enabled": true,
  "typescript.inlayHints.enumMemberValues.enabled": true,
  "cSpell.ignoreWords": ["tiptap", "hocuspocus", "pinia"]
}
// extensions.json
{
  "recommendations": ["vue.volar", "esbenp.prettier-vscode"],
  "unwantedRecommendations": ["vscode.typescript-language-features"]
}

vite配置:

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import path from 'node:path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import VueComponents from 'unplugin-vue-components/vite'
import { AntDesignVueResolver, ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import ElementPlus from 'unplugin-element-plus/vite'
import { glob } from 'glob'

const assetPatterns = <const>[
  ['media', /\.(mp4|webm|ogg|mp3|wav|flac|aac|swf)(\?.*)?$/i],
  ['image', /\.(png|jpe?g|gif|ico|svg|webp)(\?.*)?$/i],
  ['font', /\.(woff2?|eot|ttf|otf)(\?.*)?$/i],
  ['css', /\.(s?css|less|styl)(\?.*)?$/i],
]

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())

  return {
    plugins: [
      vue(),
      vueJsx(),
      ElementPlus({
        useSource: true,
        defaultLocale: 'zh-cn',
      }),
      VueComponents({
        version: 3,
        dts: 'src/components.d.ts',
        resolvers: [
          AntDesignVueResolver({ importStyle: 'less' }),
          ElementPlusResolver({ importStyle: 'sass' }),
        ],
      }),
      AutoImport({
        include: [/\.[tj]sx?$/, /\.vue$/, /\.vue\?vue/],
        imports: ['vue', 'vue-router', 'vuex'],
        dts: 'src/auto-import.d.ts',
        resolvers: [
          AntDesignVueResolver({ importStyle: 'less' }),
          ElementPlusResolver({ importStyle: 'sass' }),
        ],
        eslintrc: {
          enabled: true,
        },
      }),
    ],
    resolve: {
      alias: [
        {
          find: '@',
          replacement: path.resolve('./src'),
        },
      ],
    },
    css: {
      preprocessorOptions: {
        less: {
          javascriptEnabled: true,
          // WARNING: 引入具体样式会导致每个文件都有重复的样式
          additionalData: `
          @import "./src/assets/styles/mixins.less";
          @import "./src/assets/styles/variables.less";
          `,
          modifyVars: {
            'primary-color': '#08B286',
            'link-color': '#08B286',
          },
        },
        scss: {
          outputStyle: 'expanded',
        },
      },
    },
    build: {
      assetsInlineLimit: 2048,
      target: 'chrome70',
      reportCompressedSize: false,
      rollupOptions: {
        output: {
          assetFileNames(assetInfo) {
            const ext = path.extname(assetInfo.name || '')
            let prefix = 'misc'
            for (const [name, pattern] of assetPatterns) {
              if (pattern.test(ext)) {
                prefix = name
                break
              }
            }
            return `${prefix}/[name].[hash][extname]`
          },
          chunkFileNames: 'js/[name].[hash].js',
          entryFileNames: 'js/entry-[name].[hash].js',
        },
      },
    },
    esbuild: {
      charset: 'ascii',
    },
    server: {
      open: false,
      cors: false, // 类型: boolean | CorsOptions 为开发服务器配置 CORS。默认启用并允许任何源
      host: '0.0.0.0',
      proxy: {
        '/api': {
          target: env.VITE_APP_BASE_URL,
          changeOrigin: true,
        },
      },
    },
    base: '/',
    optimizeDeps: {
      exclude: ['prosemirror-model'],
      include: ['lodash-es', 'element-plus', 'vuex'].concat(
        glob
          .sync([
            'node_modules/ant-design-vue/es/**/style',
            'node_modules/element-plus/es/components/**/style/index.mjs',
          ])
          .map((file) => {
            return file
              .replace('node_modules\\', '')
              .replace('.mjs', '')
              .replaceAll(path.sep, path.posix.sep)
          }),
      ),
    },
  }
})

ts配置

// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "allowSyntheticDefaultImports": true,
    "strictFunctionTypes": false,
    "jsx": "preserve",
    "baseUrl": ".",
    "rootDir": ".",
    "outDir": "./build",
    "noEmit": true,
    "allowJs": false,
    "sourceMap": false,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "experimentalDecorators": true,
    "lib": ["dom", "esnext"],
    "noImplicitAny": false,
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src/**/*", "*.config.ts"],
  "exclude": ["node_modules", "dist", "build", "**/*.js"]
}

eslint配置:

// .eslintrc.js
module.exports = {
  env: { node: true },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'prettier',
    './.eslintrc-auto-import.json',
  ],
  globals: {
    defineEmits: 'readonly',
    defineProps: 'readonly',
    ChildNode: true,
    NodeJS: 'readonly',
  },
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    // sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    'no-unused-vars': 0,
    'vue/multi-word-component-names': 'off',
    'vue/no-v-html': 'off',
    'no-case-declarations': 'off',
    'vue/no-dupe-keys': 'warn',
  },
}

prettierrc配置:

// .prettierrc.yml
semi: false
singleQuote: true
# Change when properties in objects are quoted.
# If at least one property in an object requires quotes, quote all properties.
quoteProps: consistent
tabWidth: 2
printWidth: 100
# FIXME: 系统稳定后可改为lf
endOfLine: auto
trailingComma: all
bracketSpacing: true
# Include parentheses around a sole arrow function parameter.
arrowParens: always
proseWrap: preserve
jsxSingleQuote: false
# Put > on the last line instead of at a new line.
bracketSameLine: false

愚者
12 声望3 粉丝