當前位置: 妍妍網 > 碼農

搭建一個符合大廠標準的Vue3+Ts +Vite腳手架

2024-03-23碼農

前言

大家好,我是林三心, 用最通俗易懂的話講最難的知識點 是我的座右銘, 基礎是進階的前提 是我的初心。今天給大家講一講我是怎麽搭建一個 Vue3 + Ts + Vite 的腳手架的吧

vscode外掛程式

  • Volar :Vue3的一款語法提示的外掛程式

  • Prettier-Code formatter :prettier的格式化外掛程式

  • Eslint :eslint的外掛程式

  • stylelint :樣式檔格式化外掛程式

  • JavaScript and TypeScript Nightly :起用ts最新語法

  • 計畫初始化

    使用 Vite 建立計畫的命令,初始化計畫

    npm init vite@latest my-vue-app -- --template vue-ts

    tsconfig.json配置

    {
    "compilerOptions": {
    "target""esnext",
    "module""esnext",
    "moduleResolution""node",
    "strict"true,
    "forceConsistentCasingInFileNames"true,
    "allowSyntheticDefaultImports"true,
    "strictFunctionTypes"false,
    "jsx""preserve",
    "baseUrl"".",
    "allowJs"true,
    "sourceMap"true,
    "esModuleInterop"true,
    "resolveJsonModule"true,
    "noUnusedLocals"true,
    "noUnusedParameters"true,
    "experimentalDecorators"true,
    "lib": ["dom""esnext"],
    "types": ["vite/client"],
    "typeRoots": ["./node_modules/@types/""./types"],
    "noImplicitAny"false,
    "skipLibCheck"true,
    "paths": {
    "/@/*": ["src/*"],
    "/#/*": ["types/*"]
    }
    },
    "include": [
    "tests/**/*.ts",
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "types/**/*.d.ts",
    "types/**/*.ts",
    "build/**/*.ts",
    "build/**/*.d.ts",
    "mock/**/*.ts",
    "vite.config.ts",
    "src/settings/dist/theme.js",
    "src/tools.js"
    ],
    "exclude": ["node_modules""tests/server/**/*.ts""dist""**/*.js"]
    }

    vite.config.ts配置

    import { defineConfig } from'vite'
    import vue from'@vitejs/plugin-vue'
    import { resolve } from'path'
    // npm i --save-dev @types/node
    functionpathResolve(dir: string{
    return resolve(process.cwd(), '.', dir)
    }
    exportdefault defineConfig({
    plugins: [vue()],
    resolve: {
    // 路徑別名
    alias: [
    {
    find/\/@\//,
    replacement: pathResolve('src') + '/',
    },
    {
    find/\/#\//,
    replacement: pathResolve('types') + '/',
    },
    ],
    },
    // 支持使用tsx語法
    esbuild: {
    jsxFactory'h',
    jsxFragment'Fragment',
    jsxInject'import { h } from "vue";',
    },
    })

    支持 Less

    直接計畫中安裝 less 就行,跟 webpack 區別就是, Webpack 需要安裝 less、less-loader ,而 Vite 不需要 less-loader

    npm i less -D

    vscode設定

    主要配置一些 Eslint、Prettier、 stylelint 的使用,以及保存自動呼叫外掛程式進行格式化,計畫新建一個 .vscode 資料夾,資料夾裏新建一個 settings.json

    // .vscode/settings.json
    {
    //========================================
    //============== 編輯器 ===================
    //========================================
    // 光標的動畫樣式
    "editor.cursorBlinking""phase",
    // 光標是否啟用平滑插入的動畫
    "editor.cursorSmoothCaretAnimation"true,
    // vscode重新命名檔或移動檔自動更新匯入路徑
    "typescript.updateImportsOnFileMove.enabled""always",
    // 自動替換為當前計畫的內建的typescript版本
    "typescript.tsdk""./node_modeles/typescript/lib",
    // 一個制表符占的空格數(可能會被覆蓋)
    "editor.tabSize"2,
    // 定義一個預設和的格式程式 (prettier)
    "editor.defaultFormatter""esbenp.prettier-vscode",
    // 取消差異編輯器忽略前空格和尾隨空格的更改
    "diffEditor.ignoreTrimWhitespace"false,
    // 定義函式參數括弧前的處理方式
    "javascript.format.insertSpaceBeforeFunctionParenthesis"true,
    // 在鍵入的時候是否啟動快速建議
    "editor.quickSuggestions": {
    "other"true,
    "comments"true,
    "strings"true
    },
    //========================================
    //============== Other ===================
    //========================================
    // 啟用導航路徑
    "breadcrumbs.enabled"true,
    //========================================
    //============== Other ===================
    //========================================
    // 按下Tab鍵展開縮寫 (例如Html的div,在鍵入的時候按Tab,快捷生成出來)
    "emmet.triggerExpansionOnTab"true,
    // 建議是否縮寫 (如Html的<div />)
    "emmet.showAbbreviationSuggestions"true,
    // 建議是否展開 (如Html的 <div></div>)
    "emmet.showExpandedAbbreviation""always",
    // 為制定語法檔定義當前的語法規則
    "emmet.syntaxProfiles": {
    "vue-html""html",
    "vue""html",
    "xml": {
    "arrt_quotes""single"
    }
    },
    // 在不受支持的語言中添加規則對映
    "emmet.includeLanguages": {
    "jsx-sublime-babel-tags""javascriptreact"
    },
    //========================================
    //============== Files ==================
    //========================================
    // 刪除行位空格
    "files.trimTrailingWhitespace"true,
    // 末尾插入一個新的空格
    "files.insertFinalNewline"true,
    // 刪除新行後面的所有新行
    "files.trimFinalNewlines"true,
    // 預設行尾的字元
    "files.eol""\n",
    // 在尋找搜尋的時候整合的檔
    "search.exclude": {
    "**/node_modules"true,
    "**/*.log"true,
    "**/*.log*"true,
    "**/bower_components"true,
    "**/dist"true,
    "**/elehukouben"true,
    "**/.git"true,
    "**/.gitignore"true,
    "**/.svn"true,
    "**/.DS_Store"true,
    "**/.idea"true,
    "**/.vscode"false,
    "**/yarn.lock"true,
    "**/tmp"true,
    "out"true,
    "dist"true,
    "node_modules"true,
    "CHANGELOG.md"true,
    "examples"true,
    "res"true,
    "screenshots"true
    },
    // 搜尋資料夾時候排外的資料夾
    "files.exclude": {
    "**/bower_components"true,
    "**/.idea"true,
    "**/tmp"true,
    "**/.git"true,
    "**/.svn"true,
    "**/.hg"true,
    "**/CVS"true,
    "**/.DS_Store"true,
    "**/node_modules"false
    },
    // 檔監視器排外的檔 可減少初始化開啟計畫的占用大量cpu
    "files.watcherExclude": {
    "**/.git/objects/**"true,
    "**/.git/subtree-cache/**"true,
    "**/.vscode/**"true,
    "**/node_modules/**"true,
    "**/tmp/**"true,
    "**/bower_components/**"true,
    "**/dist/**"true,
    "**/yarn.lock"true
    },
    " stylelint.enable"true,
    " stylelint.packageManager""yarn",
    //========================================
    //============== Eslint ==================
    //========================================
    // 狀態列顯示Eslint的開啟狀態
    "eslint.alwaysShowStatus"true,
    // Eslint的選項
    "eslint.options": {
    // 要檢查的檔拓展名陣列
    "extensions": [".js"".jsx"".ts"".tsx"".vue"]
    },
    // Eslint校驗的
    "eslint.validate": [
    "javascript",
    "typescript",
    "reacttypescript",
    "reactjavascript",
    "html",
    "vue"
    ],
    //========================================
    //============== Prettier ================
    //========================================
    // 使用當前計畫的prettier配置檔,如果沒有則使用預設的配置
    "prettier.requireConfig"true,
    "editor.formatOnSave"true,
    // 以下程式使用prettier預設進行格式化
    "[typescript]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[typescriptreact]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[javascriptreact]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[html]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[css]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[less]": {
    "editor.defaultFormatter"" stylelint.vscode- stylelint"
    },
    "[scss]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    "[markdown]": {
    "editor.defaultFormatter""esbenp.prettier-vscode"
    },
    // 保存檔的時候的配置
    "editor.codeActionsOnSave": {
    // 使用Eslint格式化程式碼
    "source.fixAll.eslint"true,
    // 使用 stylelint格式化程式碼
    "source.fixAll. stylelint"true
    },
    "[vue]": {
    "editor.codeActionsOnSave": {
    // 使用Eslint格式化程式碼
    "source.fixAll.eslint"true,
    // 使用 stylelint格式化程式碼
    "source.fixAll. stylelint"true
    },
    "editor.defaultFormatter""johnsoncodehk.volar"
    },
    "compile-hero.disable-compile-files-on-did-save-code"true,
    "i18n-ally.localesPaths": ["src/locales""src/locales/lang"]
    }

    Eslint

    Eslint承擔的更多的是程式碼品質上的一個嚴格規範,這萊恩裝的包比較多

    npm i 
    eslint eslint-define-config 
    eslint-plugin-import
    eslint-plugin-node 
    eslint-plugin-promise 
    eslint-plugin-vue 
    vue-eslint-parser 
    @typescript-eslint/parser 
    @typescript-eslint/eslint-plugin 
    eslint-config-prettier 
    eslint-plugin-jest 
    -D

    計畫中新建兩個檔:

  • .eslintrc.js :eslint配置檔

  • .eslintignore :eslint規範忽略配置

  • .eslintrc.js

    // .eslintrc.js
    // @ts-check
    const {
    defineConfig
    } = require('eslint-define-config')
    module.exports = defineConfig({
    roottrue,
    env: {
    browsertrue,
    nodetrue,
    es6true
    },
    parser'vue-eslint-parser',
    parserOptions: {
    parser'@typescript-eslint/parser',
    ecmaVersion2020,
    sourceType'module',
    jsxPragma'React',
    ecmaFeatures: {
    jsxtrue
    }
    },
    extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    // 'prettier',
    'plugin:prettier/recommended',
    'plugin:jest/recommended'
    ],
    rules: {
    'vue/script-setup-uses-vars''error',
    '@typescript-eslint/ban-ts-ignore''off',
    '@typescript-eslint/explicit-function-return-type''off',
    '@typescript-eslint/no-explicit-any''off',
    '@typescript-eslint/no-var-requires''off',
    '@typescript-eslint/no-empty-function''off',
    'vue/custom-event-name-casing''off',
    'no-use-before-define''off',
    '@typescript-eslint/no-use-before-define''off',
    '@typescript-eslint/ban-ts-comment''off',
    '@typescript-eslint/ban-types''off',
    '@typescript-eslint/no-non-null-assertion''off',
    '@typescript-eslint/explicit-module-boundary-types''off',
    '@typescript-eslint/no-unused-vars': [
    'error',
    {
    argsIgnorePattern'^_',
    varsIgnorePattern'^_'
    }
    ],
    'no-unused-vars': [
    'error',
    {
    argsIgnorePattern'^_',
    varsIgnorePattern'^_'
    }
    ],
    'space-before-function-paren''off',
    'vue/attributes-order''off',
    'vue/one-component-per-file''off',
    'vue/html-closing-bracket-newline''off',
    'vue/max-attributes-per-line''off',
    'vue/multiline-html-element-content-newline''off',
    'vue/singleline-html-element-content-newline''off',
    'vue/attribute-hyphenation''off',
    'vue/require-default-prop''off',
    'vue/html-self-closing': [
    'error',
    {
    html: {
    void'always',
    normal'never',
    component'always'
    },
    svg'always',
    math'always'
    }
    ]
    }
    })

    .eslintignore

    *.sh
    node_modules
    *.md
    *.woff
    *.ttf
    .vscode
    .idea
    dist
    /public
    /docs
    .husky
    .local
    /bin

    Prettier

    Prettier 更多的是對於程式碼格式的規範,先安裝外掛程式

    npm i prettier -D

    然後新建一個 .prettierrc.js

    // .prettierrc.js
    module.exports = {
    printWidth100,
    tabWidth2,
    useTabsfalse,
    semifalse,
    vueIndentScriptAnd styletrue,
    singleQuotetrue,
    quoteProps'as-needed',
    bracketSpacingtrue,
    trailingComma'all',
    jsxSingleQuotefalse,
    arrowParens'always',
    insertPragmafalse,
    requirePragmafalse,
    proseWrap'never',
    htmlWhitespaceSensitivity'strict',
    endOfLine'auto',
    };

    stylelint

    stylelint 負責對樣式的格式化規範,先安裝外掛程式

    npm i 
    stylelint 
    stylelint-config-prettier 
    stylelint-config-standard 
    stylelint-order 
    -D

    然後新建一個 stylelint.config.js

    // stylelint.config.js
    module.exports = {
    roottrue,
    plugins: [' stylelint-order'],
    extends: [' stylelint-config-standard'' stylelint-config-prettier'],
    rules: {
    'selector-pseudo- class-no-unknown': [
    true,
    {
    ignorePseudo classes: ['global'],
    },
    ],
    'selector-pseudo-element-no-unknown': [
    true,
    {
    ignorePseudoElements: ['v-deep'],
    },
    ],
    'at-rule-no-unknown': [
    true,
    {
    ignoreAtRules: [
    'tailwind',
    'apply',
    'variants',
    'responsive',
    'screen',
    'function',
    'if',
    'each',
    'include',
    'mixin',
    ],
    },
    ],
    'no-empty-source'null,
    'named-grid-areas-no-invalid'null,
    'unicode-bom''never',
    'no-descending-specificity'null,
    'font-family-no-missing-generic-family-keyword'null,
    'declaration-colon-space-after''always-single-line',
    'declaration-colon-space-before''never',
    // 'declaration-block-trailing-semicolon': 'always',
    'rule-empty-line-before': [
    'always',
    {
    ignore: ['after-comment''first-nested'],
    },
    ],
    'unit-no-unknown': [
    true,
    {
    ignoreUnits: ['rpx'],
    },
    ],
    'order/order': [
    [
    'dollar-variables',
    'custom-properties',
    'at-rules',
    'declarations',
    {
    type'at-rule',
    name'supports',
    },
    {
    type'at-rule',
    name'media',
    },
    'rules',
    ],
    {
    severity'warning',
    },
    ],
    // 按照指定順序排列
    'order/properties-order': [
    'position',
    'content',
    'top',
    'right',
    'bottom',
    'left',
    'z-index',
    'display',
    'float',
    'width',
    'height',
    '',
    'max-height',
    'min-width',
    'min-height',
    'padding',
    'padding-top',
    'padding-right',
    'padding-bottom',
    'padding-left',
    'margin',
    'margin-top',
    'margin-right',
    'margin-bottom',
    'margin-left',
    'margin-collapse',
    'margin-top-collapse',
    'margin-right-collapse',
    'margin-bottom-collapse',
    'margin-left-collapse',
    'overflow',
    'overflow-x',
    'overflow-y',
    'clip',
    'clear',
    'font',
    'font-family',
    'font-size',
    'font-smoothing',
    'osx-font-smoothing',
    'font- style',
    'font-weight',
    'hyphens',
    'src',
    'line-height',
    'letter-spacing',
    'word-spacing',
    'color',
    'text-align',
    'text-decoration',
    'text-indent',
    'text-overflow',
    'text-rendering',
    'text-size-adjust',
    'text-shadow',
    'text-transform',
    'word-break',
    'word-wrap',
    'white-space',
    'vertical-align',
    'list- style',
    'list- style-type',
    'list- style-position',
    'list- style-image',
    'pointer-events',
    'cursor',
    'background',
    'background-attachment',
    'background-color',
    'background-image',
    'background-position',
    'background-repeat',
    'background-size',
    'border',
    'border-collapse',
    'border-top',
    'border-right',
    'border-bottom',
    'border-left',
    'border-color',
    'border-image',
    'border-top-color',
    'border-right-color',
    'border-bottom-color',
    'border-left-color',
    'border-spacing',
    'border- style',
    'border-top- style',
    'border-right- style',
    'border-bottom- style',
    'border-left- style',
    'border-width',
    'border-top-width',
    'border-right-width',
    'border-bottom-width',
    'border-left-width',
    'border-radius',
    'border-top-right-radius',
    'border-bottom-right-radius',
    'border-bottom-left-radius',
    'border-top-left-radius',
    'border-radius-topright',
    'border-radius-bottomright',
    'border-radius-bottomleft',
    'border-radius-topleft',
    'quotes',
    'outline',
    'outline-offset',
    'opacity',
    'filter',
    'visibility',
    'size',
    'zoom',
    'transform',
    'box-align',
    'box-flex',
    'box-orient',
    'box-pack',
    'box-shadow',
    'box-sizing',
    'table-layout',
    'animation',
    'animation-delay',
    'animation-duration',
    'animation-iteration-count',
    'animation-name',
    'animation-play-state',
    'animation-timing-function',
    'animation-fill-mode',
    'transition',
    'transition-delay',
    'transition-duration',
    'transition-property',
    'transition-timing-function',
    'background-clip',
    'backface-visibility',
    'resize',
    'appearance',
    'user-select',
    'interpolation-mode',
    'direction',
    'marks',
    'page',
    'set-link-source',
    'unicode-bidi',
    'speak',
    ],
    },
    ignoreFiles: ['**/*.js''**/*.jsx''**/*.tsx''**/*.ts'],
    }

    環境變量檔

    建立相應檔,可以讓計畫使用環境變量:

  • .env

  • .env.develoment

  • .env.production

  • 全域types

    建立 types 資料夾,存放全域相關的 typescript

    src資料夾

    src 資料夾中建立以下資料夾(當然這個看你自己喜好命名,這裏只是我自己的習慣)

  • api :存放http請求的介面

  • assets :存放一些靜態資源,如 icon、圖片

  • components :存放通用元件

  • design :存放全域樣式檔

  • enums :存放全域的ts字典

  • hooks :存放封裝的自訂hook

  • layouts :存放布局方案

  • locales :存放國際化的語言資料

  • router :存放路由相關

  • settings :存放一些全域的設定

  • store :存放狀態管理相關

  • utils :存放通用的工具類函式

  • views :存放計畫的頁面

  • router和pinia

    npm i vue-router pinia -D

  • vue-router :路由

  • pinia :狀態管理(代替vuex)

  • husky

    husky git 送出程式碼的檢查,包括 程式碼是否合格、樣式是否合格、commit資訊是否合格 等檢測

    外掛程式

    npm i pretty-quick husky @commitlint/cli @commitlint/config-conventional -D

    package.json

    "install:husky""husky install",
    "lint:pretty""pretty-quick --staged",
    "lint: stylelint"" stylelint --fix \"**/*.{tsx,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/ stylelint/",
    "lint:all""npm run lint:eslint && npm run lint: stylelint"

    husky install

    在終端裏輸入命令 husky install ,計畫會生成 .husky 資料夾:

    .husky
    _
    .gitignore
    husky.sh

    完善husky

    .husky 資料夾中建立三個檔 commit-msg、common.sh、pre-commit

    .husky
    _
    .gitignore
    husky.sh
    commit-msg
    common.sh
    pre-commit

    commit-msg

    // .husky/commit-msg
    #!/bin/sh
    "$(dirname "$0")/_/husky.sh"
    npx --no-install commitlint --edit "$1"

    common.sh


    // .husky/common.sh
    command_exists () {
    command -v "$1" >/dev/null2>&1
    }
    if command_exists winpty && test -t 1; then
    exec < /dev/tty
    fi

    pre-commit

    // .husky/pre-commit
    #!/bin/sh
    "$(dirname "$0")/_/husky.sh"
    "$(dirname "$0")/common.sh"
    [ -n "$CI" ] && exit 0
    yarn run lint:pretty

    commitlint.config.js

    用來規範 git commit -m 'msg' msg

    // commitlint.config.js
    module.exports = {
    // ↓忽略包含init的送出訊息
    ignores: [(commit) => commit.includes('init')],
    // ↓按照傳統訊息格式來驗證
    extends: ['@commitlint/config-conventional'],
    // 自訂解析器
    parserPreset: {
    // 解析器配置
    parserOpts: {
    // commit 送出頭的規則限制
    headerPattern/^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)/,
    // 匹配分組
    headerCorrespondence: ['type''scope''subject'],
    // 參照
    referenceActions: [
    'close',
    'closes',
    'closed',
    'fix',
    'fixes',
    'fixed',
    'resolve',
    'resolves',
    'resolved',
    ],
    // 對應issue要攜帶#符號
    issuePrefixes: ['#'],
    // 不相容變更
    noteKeywords: ['BREAKING CHANGE'],
    fieldPattern/^-(.*?)-$/,
    revertPattern/^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./,
    revertCorrespondence: ['header''hash'],
    warn() {},
    mergePatternnull,
    mergeCorrespondencenull,
    },
    },
    // ↓自訂送出訊息規則
    rules: {
    // ↓body以空白行開頭
    'body-leading-blank': [2'always'],
    // ↓footer以空白行開頭
    'footer-leading-blank': [1'always'],
    // ↓header的最大長度
    'header-max-length': [2'always'108],
    // ↓subject為空
    'subject-empty': [2'never'],
    // ↓type為空
    'type-empty': [2'never'],
    // ↓type的型別
    'type-enum': [
    2,
    'always',
    [
    'feat',
    'fix',
    'perf',
    ' style',
    'docs',
    'test',
    'refactor',
    'build',
    'ci',
    'chore',
    'revert',
    'wip',
    'workflow',
    'types',
    'release',
    'update',
    ],
    ],
    },
    }

    結語

    我是林三心,一個熱心的前端菜鳥程式設計師。如果你上進,喜歡前端,想學習前端,那咱們可以交朋友,一起摸魚哈哈,摸魚群,點這個 --> 摸魚沸點 [1]

    image.png

    參考計畫

  • vue-vben-admin

  • compass-plan-admin