preface

Hello everyone, I am Lin Sanxin, with the most easy to understand the most difficult knowledge points is my motto, the basis is advanced premise is my initial mind. Today, would you like to tell us how I build a Vue3 + Ts + Vite scaffold

Vscode plug-in

  • Volar: a syntax hint plug-in for Vue3
  • Prettier-Code formatter: Formatting plug-in for prettier
  • Eslint: plugin for esLint
  • Stylelint: style file formatting plug-in
  • JavaScript and TypeScript Nightly: Use the latest TS syntax

Project initialization

Initialize the project using the command to create the project from Vite

npm init vite@latest my-vue-app -- --template vue-ts
Copy the code

Tsconfig. Json configuration

{
  "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"]}Copy the code

Vite. Config. Ts configuration

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

// npm i --save-dev @types/node
function pathResolve(dir: string) {
  return resolve(process.cwd(), '. ', dir)
}

export default defineConfig({
  plugins: [vue()],
  resolve: {
    // Path alias
    alias: [{find: / / / @ / / /,
        replacement: pathResolve('src') + '/'}, {find: / # \ \ / / /,
        replacement: pathResolve('types') + '/',}]},// Support TSX syntax
  esbuild: {
    jsxFactory: 'h'.jsxFragment: 'Fragment'.jsxInject: 'import { h } from "vue"; ',}})Copy the code

Support for Less

Less can be installed in the project directly. The difference with WebPack is that WebPack requires less and less-loader to be installed, while Vite does not require less-loader

npm i less -D
Copy the code

Vscode set

The use of Eslint, Prettier, Stylelint, and save to automatically call the plugin for formatting. Create a. Vscode folder and create a settings.json folder

// .vscode/settings.json

{
  / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  //============== editor ===================
  / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // The cursor animation style
  "editor.cursorBlinking": "phase".// Whether the cursor is animated for smooth insertion
  "editor.cursorSmoothCaretAnimation": true.// vscode automatically updates the import path by renaming or moving files
  "typescript.updateImportsOnFileMove.enabled": "always".// Automatically replaces the built-in typescript version of the current project
  "typescript.tsdk": "./node_modeles/typescript/lib".// The number of Spaces occupied by a TAB character (which may be overwritten)
  "editor.tabSize": 2.// Define a default and formatter (prettier)
  "editor.defaultFormatter": "esbenp.prettier-vscode".// Cancel the difference editor to ignore changes to leading and trailing Spaces
  "diffEditor.ignoreTrimWhitespace": false.// Define how to handle function arguments before parentheses
  "javascript.format.insertSpaceBeforeFunctionParenthesis": true.// Whether to enable quick suggestions when you type
  "editor.quickSuggestions": {
    "other": true."comments": true."strings": true
  },
  / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  //============== Other ===================
  / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Enable the navigation path
  "breadcrumbs.enabled": true./ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  //============== Other ===================
  / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Press Tab to expand abbreviations (for example, Html div, press Tab as you type, quickly generated)
  "emmet.triggerExpansionOnTab": true.// Suggest whether to abbreviate (e.g. 
      
for Html)
"emmet.showAbbreviationSuggestions": true.// Suggest whether to expand (such as Html
)
"emmet.showExpandedAbbreviation": "always".// Define the current syntax rules for formulating the syntax file "emmet.syntaxProfiles": { "vue-html": "html"."vue": "html"."xml": { "arrt_quotes": "single"}},// Add rule mappings to unsupported languages "emmet.includeLanguages": { "jsx-sublime-babel-tags": "javascriptreact" }, / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = //============== Files ================== / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Delete line Spaces "files.trimTrailingWhitespace": true.// Insert a new space at the end "files.insertFinalNewline": true.// Delete all new lines after the new line "files.trimFinalNewlines": true.// The character at the end of the default line "files.eol": "\n".// Integrate files when searching "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 }, // Exclusive folders when searching for folders "files.exclude": { "**/bower_components": true."**/.idea": true."**/tmp": true."**/.git": true."**/.svn": true."**/.hg": true."**/CVS": true."**/.DS_Store": true."**/node_modules": false }, // File monitor excludes files to reduce the CPU footprint of initializing open items "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 ================== / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // The status bar shows the enabled status of Eslint "eslint.alwaysShowStatus": true.// Eslint options "eslint.options": { // Array of file extensions to check "extensions": [".js".".jsx".".ts".".tsx".".vue"]},// Eslint validates "eslint.validate": [ "javascript"."typescript"."reacttypescript"."reactjavascript"."html"."vue"]./ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = //============== Prettier ================ / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Use the prettier configuration file for the current project, if not, use the default "prettier.requireConfig": true."editor.formatOnSave": true.// The following program uses prettier for default formatting "[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" }, // Save the configuration of the file "editor.codeActionsOnSave": { // Use Eslint to format code "source.fixAll.eslint": true.// Use the stylelint format code "source.fixAll.stylelint": true }, "[vue]": { "editor.codeActionsOnSave": { // Use Eslint to format code "source.fixAll.eslint": true.// Use the stylelint format code "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"]}Copy the code

Eslint

Eslint assumes more of a strict specification of code quality, with more packages installed

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
Copy the code

Create two new files in the project:

  • .eslintrc.js: eslint configuration file
  • .eslintignoreThe ESLint specification ignores configuration

.eslintrc.js

// .eslintrc.js

// @ts-check
const {
  defineConfig
} = require('eslint-define-config')
module.exports = defineConfig({
  root: true.env: {
    browser: true.node: true.es6: true
  },
  parser: 'vue-eslint-parser'.parserOptions: {
    parser: '@typescript-eslint/parser'.ecmaVersion: 2020.sourceType: 'module'.jsxPragma: 'React'.ecmaFeatures: {
      jsx: true}},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'}]}})Copy the code

.eslintignore

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

Copy the code

Prettier

Prettier is more of a code format specification, installing plug-ins first

npm i prettier -D
Copy the code

Prettierrc.js

// .prettierrc.js

module.exports = {
  printWidth: 100.tabWidth: 2.useTabs: false.semi: false.vueIndentScriptAndStyle: true.singleQuote: true.quoteProps: 'as-needed'.bracketSpacing: true.trailingComma: 'all'.jsxSingleQuote: false.arrowParens: 'always'.insertPragma: false.requirePragma: false.proseWrap: 'never'.htmlWhitespaceSensitivity: 'strict'.endOfLine: 'auto'};Copy the code

Stylelint

Stylelint is responsible for formatting the style specification, before installing the plug-in

npm i 
stylelint 
stylelint-config-prettier 
stylelint-config-standard 
stylelint-order 
-D
Copy the code

Then create a new stylelint.config.js

// stylelint.config.js

module.exports = {
  root: true.plugins: ['stylelint-order'].extends: ['stylelint-config-standard'.'stylelint-config-prettier'].rules: {
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['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',] and {severity: 'warning'],},// In the specified order
    'order/properties-order': [
      'position'.'content'.'top'.'right'.'bottom'.'left'.'z-index'.'display'.'float'.'width'.'height'.'max-width'.'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'],}Copy the code

Environment variable file

Create files that allow your project to use environment variables:

  • .env
  • .env.develoment
  • .env.production

Global types

Create a types folder to store globally relevant typescript

The SRC folder

Create the following folder in the SRC folder (it’s up to you to name it, this is just my custom)

  • api: interface for storing HTTP requests
  • assets: Stores static resources, such asIcon, images,
  • components: Stores common components
  • design: Stores global style files
  • enums: Stores the global TS dictionary
  • hooks: holds encapsulated custom hooks
  • layouts: Stores layout schemes
  • locales: Stores internationalized language data
  • router: Stores route correlation
  • settings: Stores some global Settings
  • store: Is related to storage status management
  • utils: Stores generic utility class functions
  • views: a page for storing items

The router and pinia

npm i vue-router pinia -D
Copy the code
  • vue-router: routing
  • pinia: State management (instead of VUEX)

husky

Husky is a check for git submitted code, including code, style, and commit information

The plug-in

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

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"
Copy the code

husky install

Enter husky install in terminal and the project will be generated.

.husky
    _
        .gitignore
        husky.sh
Copy the code

Perfect the husky

Create three files in the.husky folder: commit-msg, common.sh, and pre-commit

.husky
    _
        .gitignore
        husky.sh
   commit-msg
   common.sh
   pre-commit
Copy the code

commit-msg

// .husky/commit-msg

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit "$1"
Copy the code

common.sh


// .husky/common.sh

command_exists () {
  command -v "$1" >/dev/null 2> &1
}

if command_exists winpty && test -t 1; then
  exec < /dev/tty
fi
Copy the code

pre-commit

// .husky/pre-commit

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"

[ -n "$CI" ] && exit 0

yarn run lint:pretty

Copy the code

commitlint.config.js

Git commit -m ‘MSG

// commitlint.config.js

module.exports = {
  // ↓ Ignores the commit message containing init
  ignores: [(commit) = > commit.includes('init')].// ↓ Use traditional message formats for authentication
  extends: ['@commitlint/config-conventional'].// Customize the parser
  parserPreset: {
    // Parser configuration
    parserOpts: {
      // commit The rule limit of the commit header
      headerPattern: /^(\w*|[\u4e00-\u9fa5]*)(? :[\(\ (](.*)[\)\)])? / \ \ : (. *) /.// Match groups
      headerCorrespondence: ['type'.'scope'.'subject']./ / reference
      referenceActions: [
        'close'.'closes'.'closed'.'fix'.'fixes'.'fixed'.'resolve'.'resolves'.'resolved',].// The corresponding issue should carry the # symbol
      issuePrefixes: [The '#'].// Incompatible changes
      noteKeywords: ['BREAKING CHANGE'].fieldPattern: / ^ - (. *?) - $/,
      revertPattern: /^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./,
      revertCorrespondence: ['header'.'hash'].warn() {},
      mergePattern: null.mergeCorrespondence: null,}},// ↓ Customize message submission rules
  rules: {
    // ↓body begins with a blank line
    'body-leading-blank': [2.'always'].// ↓footer begins with a blank line
    'footer-leading-blank': [1.'always'].// ↓ Maximum length of header
    'header-max-length': [2.'always'.108]./ / left the subject is empty
    'subject-empty': [2.'never']./ / left type is empty
    'type-empty': [2.'never'].// ↓ Type Indicates the type
    'type-enum': [
      2.'always'['feat'.'fix'.'perf'.'style'.'docs'.'test'.'refactor'.'build'.'ci'.'chore'.'revert'.'wip'.'workflow'.'types'.'release'.'update',],],},}Copy the code

conclusion

I am Lin Sanxin, an enthusiastic front-end novice programmer. If you progress, like the front end, want to learn the front end, then we can make friends, touch fish ha ha, touch fish, point this –> touch fish boiling point

Refer to the project

  • vue-vben-admin
  • compass-plan-admin

Guitar brother niubi !!!!!!!