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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。