国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

vite+vue3+ts項目構(gòu)建詳細步驟(配置多語言版本)

這篇具有很好參考價值的文章主要介紹了vite+vue3+ts項目構(gòu)建詳細步驟(配置多語言版本)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


前言

  • 時過境遷,我們見證了諸如 webpack、Rollup 和 Parcel 等工具的變遷,它們極大地改善了前端開發(fā)者的開發(fā)體驗。
  • 然而,當(dāng)我們開始構(gòu)建越來越大型的應(yīng)用時,需要處理的 JavaScript 代碼量也呈指數(shù)級增長。包含數(shù)千個模塊的大型項目相當(dāng)普遍?;?JavaScript 開發(fā)的工具就會開始遇到性能瓶頸:通常需要很長時間(甚至是幾分鐘!)才能啟動開發(fā)服務(wù)器,即使使用模塊熱替換(HMR),文件修改后的效果也需要幾秒鐘才能在瀏覽器中反映出來。如此循環(huán)往復(fù),遲鈍的反饋會極大地影響開發(fā)者的開發(fā)效率和幸福感。
  • Vite 旨在利用生態(tài)系統(tǒng)中的新進展解決上述問題:瀏覽器開始原生支持 ES 模塊,且越來越多 JavaScript 工具使用編譯型語言編寫。

以上引用了Vite官網(wǎng)的描述

為什么要記錄這篇文章而且還很詳細呢?那是因為進入當(dāng)前這家公司的時候,這邊連基本的前端架構(gòu)都是沒有的,每次做項目都是復(fù)用網(wǎng)上那些很臃腫的代碼模版(做一套扔一套那種,沒有保留通用前端模板框架的)。然后這個項目組之前都是vue2做開發(fā)、最近領(lǐng)導(dǎo)說以后項目考慮使用vue3來開發(fā)了,那我作為這項目組唯一的純前端人員(其他都是C#大佬,而且很多項目都是前后端不分離那種)就得考慮從頭搭建一套自定義的vue3架構(gòu)啦,結(jié)合之前項目的經(jīng)驗,從零開始搭建了這套前端架構(gòu)(由于沒有大佬帶,只能自個一點點查看資料且一步步摸索,期間也遇到了不少問題),如果有優(yōu)化的地方,還請各位大佬多多評論交流哈。抱拳!

那么接下來咱們一步步來構(gòu)建vite+vue3+ts吧~


Tips:本篇文章是按照配置一步步配置的,所以稍微較長,如果是新手建議往下一步步配置,花費的時間也不會很長

一、構(gòu)建基礎(chǔ)項目模板

  • 首先需要安裝Node
    先看下安裝node后版本
node -v

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

Tips 由于vite在node低版本不支持,所以建議安裝最新的穩(wěn)定版本,或者是 14.18+

  • 安裝Vue最新版本基礎(chǔ)模板

當(dāng)前基礎(chǔ)項目模板是按照vue最新版本構(gòu)建的(其他安裝方式可異步vite官網(wǎng)查看更多)
安裝命令如下:

npm init vue@latest

執(zhí)行以上會有部分配置需要選擇,本項目具體選擇如下圖:
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
執(zhí)行完后生成目錄如圖:
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

  • 安裝依賴
npm i
  • 項目執(zhí)行
npm run dev
  • 訪問頁面
    按照上述操作后訪問 http://localhost:5173/ 即顯示下面內(nèi)容啦
    vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

因為當(dāng)前demo是基于element-plus,先安裝npm i element-plus -S
并在main.js應(yīng)用

import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
...
const app = createApp(App)
...
app.use(ElementPlus)

二、根據(jù)基礎(chǔ)模版搭建優(yōu)化項目結(jié)構(gòu)(持續(xù)更新中)

由于初始化的基礎(chǔ)項目結(jié)構(gòu)比較簡單,所以一般都需要根據(jù)個人習(xí)慣,優(yōu)化結(jié)構(gòu)及配置相關(guān)信息

A、環(huán)境配置優(yōu)化

上面的基礎(chǔ)模板可看到,并沒看到不同環(huán)境變量,其實是有測試環(huán)境和生產(chǎn)環(huán)境的,具體可以 使用import.meta打印出看下。
main.ts輸出import.meta.env
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

然后執(zhí)行npm run dev,查看頁面控制臺可看到MODE的值為"development"
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
執(zhí)行npm run build-only,把構(gòu)建的dist內(nèi)的文件放置服務(wù)器。

  • 本地開發(fā)推薦使用nginx(推薦使用),可參考Nginx在Window與Mac環(huán)境的使用及配置詳情
  • 還可使用express-generator開啟服務(wù)
  • 當(dāng)然也可以直接在開發(fā)測試訪問http://localhost:5173/dist/index.html,但這種需要修改對應(yīng)文件引入路徑,想了解的可自行研究下哈

然后訪問可看到控制臺打印出MODE的值為"production"
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

但由于項目開發(fā)到上線,可能都存在有不同環(huán)境需求,所以咱們就需要配置環(huán)境變量以對應(yīng)不同環(huán)境的Api,而且配置好之后,如無特殊修改,并不需要再修改環(huán)境配置相關(guān)的,這樣就可避免部署構(gòu)建后環(huán)境錯誤的情況啦

正常流程一般分為

  • 開發(fā)環(huán)境(可根據(jù)實際開發(fā)情況鏈接對應(yīng)環(huán)境的Api)
  • sit環(huán)境(測試)
  • uat環(huán)境(業(yè)務(wù)驗收)
  • prod環(huán)境(線上環(huán)境)

先把環(huán)境變量這些配置好,在根目錄新建不同環(huán)境的文件(具體配置的key默認VITE_開頭,也可配置envPrefix'值自定義)

  • .env(這個是公共環(huán)境配置,都會獲取這里面的配置信息)
  • .env.development
  • .env.production
  • .env.sit
  • .env.uat
    vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
    .env文件是共有配置,所以即使配置配置對應(yīng)執(zhí)行腳本環(huán)境也會獲取
# 公有全局環(huán)境配置

VITE_STORE_NAME = invade-

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

想要執(zhí)行不同命令讀取對應(yīng)環(huán)境配置文件,還需要再在package.json配置對應(yīng)腳本,執(zhí)行腳本后vite會根據(jù)編譯的命令讀取對應(yīng)環(huán)境文件的,新增具體如下

{
  ...
  "scripts": {
    "dev": "vite serve --mode development",
    "dev-sit": "vite serve --mode sit",
    "dev-uat": "vite serve --mode uat",
    "dev-prod": "vite serve --mode production",
    "sit": "vite build --mode sit",
    "uat": "vite build --mode uat",
    "prod": "vite build --mode production",
    ...
  },
  ...
}
  • vite serve對應(yīng)的是本地開發(fā)聯(lián)調(diào)測試用的,可能不同環(huán)境都得在本地聯(lián)調(diào)測試問題,所以存在dev-sit這些,如果不指定--mode后面的值,默認為development
  • vite build是構(gòu)建打包執(zhí)行的,如果不指定--mode后面的值,默認為production
  • --mode 后面跟著的就是配置的環(huán)境變量值,即對應(yīng)上面截圖控制臺看到的MODE的值

不過咱感覺項目結(jié)構(gòu)看起來沒那么優(yōu)雅(主要不想更目錄文件太多,影響閱讀)。
根據(jù)官網(wǎng)提供配置,可自定義個文件夾,放置這些環(huán)境配置文件,那咱們就在根目錄新建文件夾env(這個文件名稱可自定義,對應(yīng)下面envDir配置的值),把環(huán)境配置的文件都移進去vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
且需要修改vite.config.ts配置,指定envDir: 'env',

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
export default defineConfig({
  // env配置文件變量前綴, 默認 VITE_,可自行定義
  envPrefix: 'VITE_',
  // env配置文件夾位置
  envDir: 'env',
  plugins: [vue(), vueJsx()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

例如 .env.development配置

# 本地開發(fā)環(huán)境的代理配置配置, 任何代理請寫好注釋

# 接口地址
 VITE_PROXY_API=http://localhost:8000
 
# 構(gòu)建后文件引用 相對路徑
 VITE_PUBLIC_PATH=/

# 輸出路徑
 VITE_OUT_DIR=/dist/

執(zhí)行 npm run dev
控制臺打印import.meta.env,可看到.env.env.development配置的信息,如下
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
例如 .env.sit配置

# 本地開發(fā)環(huán)境的代理配置配置, 任何代理請寫好注釋

# 接口地址
 VITE_PROXY_API=http://localhost:8001
 
# 構(gòu)建后文件引用 相對路徑
 VITE_PUBLIC_PATH=/

# 輸出路徑
 VITE_OUT_DIR=/dist/

執(zhí)行 npm run dev-sit(當(dāng)然執(zhí)行npm run sit構(gòu)建后打印的也是一致的,其他環(huán)境下的也是如此)
控制臺打印import.meta.env,可看到.env.env.sit配置的信息,且VITE_PROXY_API的值同dev環(huán)境的不一樣,如下
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

B、優(yōu)化生產(chǎn)構(gòu)建后 console和debugger關(guān)閉

由于生產(chǎn)一般避免控制臺打印相關(guān)信息,vite也有這種配置優(yōu)化,話不多說,直接上配置

import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
  ...
  build: {
    minify: "terser", // 必須開啟:使用 terserOptions 才有效果
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
  }
})

如果這樣配置后直接構(gòu)建會報錯,提示terser not found.提示需要安裝這個terser,可執(zhí)行npm i terser -D安裝
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
安裝完terser后再次構(gòu)建成功。然后訪問構(gòu)建的內(nèi)容發(fā)現(xiàn)console.log(import.meta.env)沒打印出來,說明配置生效了
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
不過這樣配置發(fā)現(xiàn)如果測試環(huán)境想要看到打印信息判斷錯誤等,還得修改配置再次構(gòu)建下,明顯不友好,那么我們稍微優(yōu)化下只在prod環(huán)境下生效,即在defineConfig使用回調(diào)函數(shù)的回參來配置(查看源碼可看到defineConfig入?yún)⒂袃煞N),如下

import { defineConfig, loadEnv } from 'vite'
// https://vitejs.dev/config/

export default defineConfig(({ command, mode, ssrBuild }) => {
  const env = loadEnv(mode, `${process.cwd()}/env`, '')
  // 為什么要這樣做,是為了 process.env和mode一致性
  Object.assign(process.env, env, { NODE_ENV: mode })
  return {
    mode,
  	...
  	build: {
      minify: "terser", // 必須開啟:使用 terserOptions 才有效果
	  terserOptions: {
	    compress: {
	      drop_console: process.env.NODE_ENV === 'production' ? true : false, // 也可直接使用mode進行判斷
          drop_debugger: process.env.NODE_ENV === 'production' ? true : false,
	    },
     },
    }
  }
})

可看到有三個參數(shù),ssrBuild為可選

command: 'build' | 'serve'; // 二選一,默認為serve ,可在執(zhí)行腳本配置(配置在vite 后面) 例如 "dev": "vite serve --mode development",
mode: string; // 自定義 一般會設(shè)置為 development | sit | uat | production
/**
 * @experimental
 */
ssrBuild?: boolean; // 看起來應(yīng)該是配置SSR模式使用的,后面有機會再ssr模式下詳細記錄下

結(jié)合上面配置,在構(gòu)建sit | uat的時候打印還在,而構(gòu)建production沒有了,說明咱們配置成功啦。

那么為什么不直接使用process.env.NODE_ENV直接判斷呢?因為在開發(fā)環(huán)境process.env.NODE_ENV默認是development,即使跑的是dev-sit也還是一樣為development。我們看個截圖,所以需要使用回調(diào)函數(shù)根據(jù)配置的--mode進行判斷
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

C、優(yōu)化文件引用路徑

在很多時候,不同頁面需要使用同一個組件,且引入的路徑可能不一致,那么怎樣才能統(tǒng)一呢?其實在初始化構(gòu)建項目之后,框架本身已經(jīng)生成了最基本的文件指向了,看下配置

import { fileURLToPath, URL } from 'node:url'
...
import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
  ...
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  ...
})

即在defineConfig配置resolve引用相關(guān)配置指向,如果指向 ./src不能滿足需要,可以自行自定義下(咱得習(xí)慣是使用一個@即可,前提需要把項目目錄結(jié)構(gòu)合理化,即不要過于深入嵌套且按模塊分好目錄)

使用方式,在所需要的文件引入,例如在/src/components/index/demo.ts引入/src/views/HomeView.vue文件
以下代碼可看出多層 ../引入的文件使用了alias配置@指向./src,即可避免文件引入錯誤等情況

// import HomeView from '../../views/HomeView.vue'
import HomeView from '@/views/HomeView.vue'

D、優(yōu)化項目全局文件類型聲明配置(ts的泛型)

  • .d.ts文件,它是用來做類型聲明(declare)。它僅僅用來做類型檢測,告知TypeScript我們有哪些類型;
  • d是 (declare,聲明)
  • declare module ** 聲明文件
  • declare namespace ** 聲明命名空間

初始化構(gòu)建出來的根目錄有個env.d.ts文件,會在tsconfig.app.json文件引入(如果未配置,有些文件引入會報錯,因為沒有在任何地方聲明。而有些是會自帶聲明,例如documentlib.dom.d.ts文件中進行了聲明了,具體可按下ctrl鍵盤并鼠標左鍵點擊查看即可)

如果有多個這種配置文件,就得在tsconfig.app.json文件手動一個個引入進來,例如新增個wechat.d.ts文件配置weixin-js-sdk全局。

{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "wechat.d.ts"],
  ...
}

其實咱們也可以直接把此配置直接配置在env.d.ts文件內(nèi),可是如果有更多配置咋辦呢?不就出現(xiàn)了很多配置在一起,可能修改或新增某個配置的時候,不小心刪除了其他的配置,那怎樣避免這種情況呢?

/// <reference types="vite/client" />

declare module 'weixin-js-sdk'

可以看到env.d.ts配置文件以.d.ts結(jié)尾,那咱就優(yōu)化下上面配置,先在根目錄新建個types文件夾,然后把env.d.ts文件放進來,在修改下tsconfig.app.json文件(一般修改了env.d.ts會自動修改在引入的位置),即"env.d.ts"修改成"types/env.d.ts"

{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["types/env.d.ts", "src/**/*", "src/**/*.vue"],
  ...
}

然后優(yōu)化tsconfig.app.json配置"types/env.d.ts"改為"types/*.d.ts"即動態(tài)引入types文件夾下所有.d.ts結(jié)尾的文件,如下

{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["types/*.d.ts", "src/**/*", "src/**/*.vue"],
  ...
}

新建·global.d.ts

/**
 * 自定義全局類型
 */
declare module 'js-cookie'

type IfEquals<X, Y, A=X, B=never> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;

/** 獲取可編輯key */
export type WritableKeys<T> = {
  [P in keyof T]-?: IfEquals<{
    [Q in P]: T[P];
  }, {
    -readonly [Q in P]: T[P];
  }, P>
}[keyof T];

新建·shims-vue.d.ts,配置一些聲明文件,例如 .vue格式文件、lodash、各種文件格式等


declare module '*.vue' {
  import type { DefineComponent } from 'vue';

  const component: DefineComponent<{}, {}, any>;
  export default component;
}

// declare module '*.vue' {
//   import { DefineComponent } from 'vue'
//   const component: DefineComponent<{}, {}, any>
//   export default component
// }


/**
 * window上屬性自定義
 */
interface Window {
  [key: string]: string | number | Types.Noop | Types.PlainObject | unknown;
  WeixinJSBridge: any;
}

declare module '*.svg';
declare module '*.png';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.gif';
declare module '*.bmp';
declare module '*.tiff';
declare module '*.mp3';

declare module 'lodash';

declare module '@/utils/pictureVerfy/pawebjs.min.js';

以上按照需求配置即可

E、配置css全局變量

我們這邊使用less處理,需要安裝以下依賴支持

npm i less -D
npm i less-loader -D

一般項目都會有很多重復(fù)使用的色系,布局位置信息等,這個時候咱可以使用使用less動態(tài)配置對應(yīng)變量進行使用功能
首先得新建個.less文件在./src/assets/新建variables.less文件,內(nèi)容如下

/**
 * 定義全局使用的 less 變量
 */
 @paddingDefault: 32px;
/**
 * 顏色值
 */
 @a94442: #a94442;

然后配置variables.less文件到項目全局,不然沒法使用這些定義好的變量哦

import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import { defineConfig} from 'vite'

// https://vitejs.dev/config/
export default defineConfig(({ command, mode, ssrBuild }) => {
  ...
  return {
    ...
    css: {
      preprocessorOptions: {
        // less: {
        //     javascriptEnabled: true,
        //     additionalData:  `@import "${resolve(__dirname, 'src/assets/styles/base.less')}";`
        // }
        less: {
          modifyVars: {
            hack: `true; @import (reference) "${resolve('src/assets/styles/variables.less')}";`,
          },
          javascriptEnabled: true
        }
      }
    },
    build: {
      ...
    }
  }
})

使用方式,上述配置好之后直接在需要使用的地方使用即可

<div class="content"></div>
<style lang="less">
.content {
  background: @a94442;
  width: @paddingDefault;
  height: @paddingDefault;
}
</style>

下圖可看到對應(yīng)值變成了variables.less文件配置好的值
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

F、新建文件夾(不同功能內(nèi)容分開放)

良好的習(xí)慣和語義化的目錄名稱有助于項目維護和開發(fā)者閱讀的心情

目錄結(jié)構(gòu)是否合理也是當(dāng)今團隊項目開發(fā)中相當(dāng)重要的一部分

先在/src目錄下新建以下目錄(詳細的結(jié)構(gòu)放在了最下方,有興趣可直接劃到底部查看)

  • App
  • composables
  • const
  • entity
  • enum
  • infrastructure
  • interface
  • lang
  • server
  • utils

G、引入axios

  • 安裝axios
npm i axios -S
  • 引入axios

1、在/src/server文件夾內(nèi)新建 index.tsinterface.ts文件
/src文件夾內(nèi)新建 interface文件,再在interface文件夾內(nèi)新建 index.ts文件
有使用到了lodash-es,所以需要安裝npm i lodash-es -D
/src/server/index.ts如下(其他配置自定義即可)

import axios, { type AxiosRequestConfig } from 'axios'
import { assign } from 'lodash-es'
import { ElMessage as message } from 'element-plus'
const UN_SUPPORT_DIY_HEADER_REGEX = /^http(s)?:\/\//i
// 請求錯誤統(tǒng)一處理
import ERRORCODES from '@/enum/error-code'

import { resetInterfacePath } from '@/utils'
// 默認請求失效時間60s
export const AXIOS_TIMEOUT_LIMIT = 60000
axios.defaults.timeout = AXIOS_TIMEOUT_LIMIT;
import type { NUNBER_STRING as ERROR_CODES_TYPES } from '@/interface'
// 也可以直接使用 typeof 獲取 ERROR_CODES 的接口類型,這個時候需要ERROR_CODES 在同一文件內(nèi)才有效果
// type ERROR_CODES_TYPES = typeof ERROR_CODES
const ERROR_CODES = ERRORCODES as ERROR_CODES_TYPES 
/**
 * 后臺接口公共的返回格式
 * 具體根據(jù)實際跟后臺約定的定義
 */
export interface ResCommonType<T = unknown> {
  code: number
  data: T
  msg?: string
}

// 請求攔截
axios.interceptors.request.use(
  (config) => {
    /**
     * Request header not allowed by Access-Control-Allow-Headers in preflight response
     * 第三方接口不支持頭
    */
    config.url = resetInterfacePath(config.url || '')
    if (!UN_SUPPORT_DIY_HEADER_REGEX.test(config.url ?? '')) {
      assign(config.headers, {
        // 'X-RequestFrom': 'person',
      })
    }
    // if (config?.url?.includes('/DownloadFile')) {
    //   assign(config.headers, {
    //     'Accept': 'ext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    //     'Content-Type': 'application/x-www-form-urlencoded',
    //     'responseType': 'blob'
    //   })
    // }
    return config
  },
  (err) => Promise.reject(err),
)

// 響應(yīng)攔截
axios.interceptors.response.use(
  (response) => {
    if (typeof response.data === 'string') {
      // location.href = '/signIn'
      // return Promise.reject('登錄失效')
    }
    const data = response.data
    const resCode: keyof ERROR_CODES_TYPES = data.status || data.code
    console.log('ERROR_CODES[resCode]', ERROR_CODES[resCode])
    if (ERROR_CODES[resCode]) {
      return Promise.reject(data)
    }
    return Promise.resolve(data)
  },
  (err) => {
    let errCode: keyof ERROR_CODES_TYPES = 500
    let errMsg = err?.message || '連接到服務(wù)器失敗'
    if (err?.response) {
      const { code, status } = err.response
      errCode = code || status || 500
      errMsg = ERROR_CODES[errCode]
    }
    console.log('ERROR_CODES[]', errCode, ERROR_CODES[errCode])
    message.error(errMsg)
    return Promise.reject({
      code: errCode,
      msg: errMsg,
      data: err || null,
    })
  },
)

/**
 * 發(fā)起GET請求, 泛型 T 定義返回數(shù)據(jù) data 項類型, U 定義請求數(shù)據(jù)類型
 * @param {string} url 請求鏈接
 * @param {object} params 請求參數(shù)
 * @param {object} config 配置
 */
export const get = <U = unknown, T = unknown>(
  url: string,
  params?: U,
  config?: AxiosRequestConfig,
) => axios.get<T, T>(
    url, { params: { ...params, t: Date.now() }, ...config },
  )

/**
 * 發(fā)起POST請求, 泛型 T 定義返回數(shù)據(jù) data 項類型, U 定義請求數(shù)據(jù)類型
 * @param {string} url 請求鏈接
 * @param {object} params 請求參數(shù)
 * @param {object} config 配置
 */
export const post = <U = unknown, T = unknown>(
  url: string,
  params?: U,
  config: AxiosRequestConfig = {},
) => {
  if (Array.isArray(params)) {
    return axios.post<T, T>(url, [...params], config)
  }
  return axios.post<T, T>(url, { ...params }, config)
}

/**
 * 發(fā)起FormData請求, 泛型 T 定義返回數(shù)據(jù) data 項類型, U 定義請求數(shù)據(jù)類型
 * @param {string} url 請求鏈接
 * @param {object} params 請求參數(shù)
 * @param {object} config 配置
 */
// export const postForm = <U = unknown, T = unknown>(
//   url: string,
//   params?: U,
//   config: AxiosRequestConfig = {},
// ) => axios.post<T, ResCommonType<T>>(url, qs.stringify({ ...params }), config);
export const postForm = <U = unknown, T = unknown>(
  url: string,
  params?: U,
  config: AxiosRequestConfig = {},
) => axios.post<T, T>(url, params, config)

/**
 * 文件下載請求, 泛型 T 定義返回數(shù)據(jù) data 項類型, U 定義請求數(shù)據(jù)類型
 * @param {string} url 請求鏈接
 * @param {object} params 請求參數(shù)
 * @param {object} config 配置
 */
// export const postFile = <U = unknown, T = unknown>(
//   url: string,
//   params?: U,
//   config: AxiosRequestConfig = { responseType: 'blob' },
// ) => axios.post<T, ResCommonType<T>>(url, { ...params }, config);

export default {
  get,
  post,
  // postForm,
  // postFile,
}

/src/server/interface.ts如下(用于接口的共有interface(接口)定義部分)


export interface BaseResType {
  ResultCode: number
  ResultDescription: string
}
export interface ApiResponseType<T> extends BaseResType{
  result: T
}

2、在/src/enum文件夾內(nèi)新建 error-code.ts文件(后面配置成多語言)

// 請求錯誤統(tǒng)一處理
const ERROR_CODES = {
    400: '錯誤請求,狀態(tài)碼:400',
    401: '未授權(quán),請重新登錄,狀態(tài)碼:401',
    403: '拒絕訪問,狀態(tài)碼:403',
    404: '請求錯誤,未找到該資源,狀態(tài)碼:404',
    405: '請求方法未允許,狀態(tài)碼:405',
    408: '請求超時,狀態(tài)碼:408',
    500: '服務(wù)器端出錯,狀態(tài)碼:500',
    501: '網(wǎng)絡(luò)未實現(xiàn),狀態(tài)碼:501',
    502: '網(wǎng)關(guān)錯誤,狀態(tài)碼:502',
    503: '服務(wù)不可用,狀態(tài)碼:503',
    504: '網(wǎng)絡(luò)超時,狀態(tài)碼:504',
    505: 'HTTP版本不支持該請求,狀態(tài)碼:505',
}

export default ERROR_CODES

3、在/src/utils文件夾內(nèi)新建 index.ts文件(用于整個項目共有方法等)


import type { unKnow } from "@/interface";
/**
 * 拼接接口路徑,例如代理接口的時候后臺接口前綴不統(tǒng)一等,可以自定義個前綴,有助于代理配置。
 * @param url 接口路徑(一般只會配置相對路徑,也可直接配置絕對路徑)
 * @returns 
 */
export const resetInterfacePath = (url: string) => {
    // return `/api/${url}`
    return url
}
/**
 * 對象轉(zhuǎn)formData
 * @param data
 */
export const objectToFormData = (data: object): FormData => {
  let formData = new FormData();
  for (const [key, value] of Object.entries(data)) {
    if (value !== null && value !== undefined) {
      formData.append(key, value);
    } else {
      formData.append(key, '');
    }
  }
  return formData;
};
/**
 * 對象轉(zhuǎn)數(shù)組
* @param data
*/
export const objectToArray = (data: object): Array<Object> => {
 let arr: Array<Object> = []
 for (const [key, value] of Object.entries(data)) {
   if (value !== null && value !== undefined) {
     arr.push(value)
   }
 }
 return arr;
};
/**
 * 地址數(shù)據(jù)轉(zhuǎn)換
 * @param data 
 * @returns 
 */
export const translateAddress = (data: any) => {
  if (data instanceof Object && !Array.isArray(data)) {
    data = objectToArray(data)
    data = data.map((item: any) => {
      return {
        value: item.code,
        label: item.name,
        children: translateAddress(item.node)
      }
    })
  }
  return data
}

interface Obj {
  [key: string]: string | number;
}
/**
 * 根據(jù)對象value獲取key
 * @param obj 
 * @param value 
 * @returns 
 */
export const objectGetKeyForValue = (obj: Obj | undefined, value: string | number): string => {
  if (!obj) {
    return ''
  }
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const element = obj[key];
      if (value === element) {
        return key
      }
    }
  }
  return ''
}
/**
 * 根據(jù)數(shù)組中子對象value獲取對應(yīng)label
 * @param arr 
 * @param value 
 * @returns 
 */
export const arrayGetLabelForValue = (arr: Array<unKnow> | undefined, value: string | number): string => {
  if (!arr?.length) {
    return ''
  }
  let label = ''
  arr.forEach(element => {
    if (element.value === value) {
      label = element.label
    }
  });
  return label
}

4、在 /src/interface/index.ts新增(整個項目的 interface 接口定義,即公共部分)

export interface unKnow {
    [key: string]: any;
  }
  export interface Undefined {
    [key: string]: undefined;
  }
  export interface NUNBER_STRING{
    [key: number]: string;
  }
  export interface OBJ_STRING {
    [key: string]: string;
  }
  

配置好axios之后就需要驗證配置是否可用呀。

以接口api為 /user/login為例(其余接口根據(jù)此邏輯依次配置即可)
那咱就在/src/server目錄新建個文件夾為user,即API的前綴部分,然后在此新建兩個文件 index.tsinterface.ts

index.ts文件


import { post, get, postForm } from '@/server/index';
import { objectToFormData } from '@/utils'
import type { 
  LoginParamsType, LoginResType
} from './interface';

/**
 * 登錄
 * @param params
 */
export const login = (params: LoginParamsType) => {
  return post<LoginParamsType, LoginResType>('/user/login', params)
}
// export const login = (params: LoginParamsType) => {
//   return get<LoginParamsType, LoginResType>('/user/login', params)
// }
// export const login = (params: LoginParamsType) => {
//   return postForm<FormData, LoginResType>('/user/login', objectToFormData( params ))
// }

interface.ts文件

/**
 * 登錄參數(shù)
 */
export interface LoginParamsType {
  
}
/**
 * 登錄返回結(jié)果
 */
export interface LoginResType {

}

再在需要調(diào)用此接口的地方直接使用即可,具體如下

import { login } from '@/server/user'
login({})

可看到接口調(diào)用起來了,由于還未開啟API所以是404,不過即使接口服務(wù)開啟了,也會出現(xiàn)跨域的情況,下一步詳細記錄
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

H、項目開發(fā)中難免遇到的跨域問題

跨域是瀏覽器調(diào)用Api不可避免的,所以咱之前也有一遍關(guān)于同源策略與跨域的解決方案

這里主要描述本地開發(fā)中vite代理解決跨越方案
在很多情況下,后臺Api都會存在不同的Api前綴,當(dāng)然有些后臺大佬會統(tǒng)一以 /api開頭(有助于代理配置),前端自己也可自動配置Api拼接 /api為前綴

由于咱不想看到vite.config.ts文件超長,所以新建個build文件夾,在這個文件夾下新增proxy.ts文件

const fs = require('fs');
const path = require('path');

/**
 * 自動添加代理
 * 遍歷mock代理配置 START
 */
const getProxyConfig = () => {
  // 讀取 ../src/server 下的目錄作為代理的根目錄
  const mockFiles = fs.readdirSync(path.resolve(__dirname, '../src/server'));
  const proxyMap = {};
  mockFiles.forEach((fileName) => {
    if (!fileName.includes('.ts')) {
      proxyMap[`^/${fileName}`] = {
        target: process.env.VITE_PROXY_API,
        ws: true,
        secure: true,
        changeOrigin: true,
      };
    }
  });
  /**
   * 統(tǒng)一以 /api 為前綴(也可為其他自定義,這里以 /api 為例)
   * 如果后端Api沒有此前綴,前端可自行在調(diào)用接口路徑前拼接 /api 例如 后臺為 /login ,在實際調(diào)用接口改為 /api/login(即當(dāng)前構(gòu)建配置的resetInterfacePath方法處理)
   * 不過不想手動拼接/api前綴,也可直接在server目錄下新建 api 文件夾,把對應(yīng)配置的接口放入即可,按照mockFiles的配置會直接配置上的,不過的注意 rewrite 問題哦
   * 所以這里直接寫上 /api 的代理配置
   */
  proxyMap[`^/api`] = {
    target: process.env.VITE_PROXY_API, // 這個配置用到了上面env的環(huán)境配置字段
    ws: true,
    secure: true,
    changeOrigin: true,
    // 如果后端沒有這個前綴,需要重寫"/api"為 ""
    rewrite: (path: string) => path.replace(/^\/api/, ""),
    bypass(req: any, res: any, options: any) { // 查看代理前路徑
      const proxyUrl = new URL( options.rewrite(req.url) || '', (options.target) as string)?.href || ''
      res.setHeader("x-req.proxyUrl", proxyUrl)
    }
  };
  console.log('proxyMap_proxyMap', proxyMap)
  return proxyMap;
};

module.exports = getProxyConfig;

然后在vite.config.ts文件配置proxy即可

import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
const getProxyConfig = require('./build/proxy');

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, `${process.cwd()}/env`, '')
  Object.assign(process.env, env, { NODE_ENV: mode })
  return {
    mode,
    ...
    server: {
      // host設(shè)置為true才可以使用network的形式,以ip訪問項目
      host: true,
      // 本地編譯后訪問的端口號
      port: 8082,
      // 編譯后是否自動打開瀏覽器訪問
      open: true,
      hmr: {
        overlay: false
      },
      // 跨域設(shè)置允許
      cors: false,
      // 如果端口已占用直接退出
      strictPort: false,
      // 設(shè)置代理
      proxy: getProxyConfig()
    },
    ...
  }
})

說到這里,咱同時提下本地開發(fā)編譯的時候,訪問端口默認5173http://localhost:5173/
可在上面server中設(shè)置port值即可,具體看上面?zhèn)渥?/p>

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

I、多語言配置

多語言系統(tǒng)網(wǎng)站常見的,那咱同時也配置個多語言系統(tǒng)的。

多語言常用的插件有 i18n ,適用vue框架的有vue-i18n,先安裝好 npm i vue-i18n -S
一般在切換語言之后,頁面刷新等操作還得保留切換后的語言系統(tǒng),咱可使用緩存記錄,這邊使用了 js-cookie做緩存設(shè)置,即使用cookie記錄當(dāng)前顯示語言,由于TS環(huán)境下使用得安裝兩個依賴 js-cookie@types/js-cookie否則會出現(xiàn)報錯情況(當(dāng)然也可直接使用手寫設(shè)置cookie使用)

npm i @types/js-cookie -D
npm i js-cookie -D

如果只安裝 @types/js-cookie會提示以下錯誤
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

然后在 /src/lang文件夾下新建以下文件(夾)

  • 新建 index.ts文件
  • 對應(yīng)的語言文件夾,以中英文為例,新建 zh-CNen-US文件夾,且里面分別新建 index.ts文件
  • 新建應(yīng)用的第三方資源庫(例如 新建 element-plus.ts文件)
    vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

/src/lang/index.ts文件(具體配置此處不細說哈,直接看代碼,包括了 elememt-plus的多語言配置)

import { createI18n } from 'vue-i18n'
import Cookies from 'js-cookie'
import elementPlus from './element-plus'
import enLocale from './en-US/index'
import zhLocale from './zh-CN/index'
const messages = {
  'zh-CN': zhLocale,
  'en-US': enLocale
}

/**
 * 設(shè)置語言環(huán)境
 * @param lang 語言環(huán)境
 */
export function setLanguage(lang: string) {
  Cookies.set('language', lang || 'zh-CN')
}
/**
 * 獲取配置環(huán)境
 * @returns 
 */
export function getLanguage() {
  // const bool = true
  // if (bool) {
  //   return 'en'
  // }
  const chooseLanguage = Cookies.get('language')
  if (chooseLanguage) return chooseLanguage
  // 如果有需要也可以根據(jù)當(dāng)前用戶設(shè)備瀏覽器默認語言
  // const language = navigator.language.toLowerCase() // IE10及IE10以下的版本 使用 navigator.browserLanguage
  // const locales = Object.keys(messages)
  // for (const locale of locales) {
  //   if (language.indexOf(locale.toLowerCase()) > -1) return locale
  // }
  return 'en-US'
}
const i18n = createI18n({
    globalInjection: true, // 全局生效$t
    locale: getLanguage(), // getLanguage()
    messages,
    legacy: false
})
export const elementPlusLocale = elementPlus
export const lang = () => {
  const lang = getLanguage()
  switch (lang) {
    case 'zh-CN':
      return messages['zh-CN']
    case 'en-US':
      return messages['en-US']
  }
  return messages['zh-CN']
}
export default i18n

/src/lang/zh-CN.index.ts文件

export default {
  ErrorPageTips: `抱歉!您訪問的頁面失聯(lián)啦`
}

/src/lang/en-US/index.ts文件

export default {
  ErrorPageTips: `I'm sorry! The page you visitedis lost`
}

/src/lang/element-plus.ts文件(其他配置方法可直接去官網(wǎng)查閱)


import elementZhLocale from 'element-plus/lib/locale/lang/zh-CN'
import elementEnLocale from 'element-plus/lib/locale/lang/en'
import { getLanguage }  from './index'
export default () => {
  const lang = getLanguage()
  switch (lang) {
    case 'zh-CN':
      return elementZhLocale
    case 'en-US':
      return elementEnLocale
  }
}

新建并配置上上面內(nèi)容后,直接在 main.ts文件應(yīng)用即可

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import App from '@/App/index.vue'
import i18n, { elementPlusLocale } from './lang'
...
// import VConsole from 'vconsole';
// 設(shè)置語言變量
// import { setLanguage } from '@/lang/index'
// setLanguage('zh-CN')
// const vConsole = new VConsole() as any
const app = createApp(App)
...
// .use(vConsole)
.use(ElementPlus, { locale: elementPlusLocale() })
.use(i18n)
.mount('#app')

配置并引用對語言配置之后,即可使用啦。
例如
html 上直接使用

<div>{{$t('ErrorPageTips')}}</div>

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端
或者是編寫邏輯的時候使用(注意需要在 setup 內(nèi)使用)

import { defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
export default defineComponent({
  ...
  setup() {
    const { t } = useI18n()
    console.log(t('ErrorPageTips'))
    return { ... }
  }
}

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

按照上述操作,多語言配置即實現(xiàn)啦,至于切換語言,可以直接在需要切換的按鈕上觸發(fā) setLanguage方法即可

這里既然配置好了多語言,那上面在/src/enum文件夾內(nèi) error-code.ts 文件需要改造下,在此處文件夾先新建 index.ts

import { getLanguage } from "@/lang"
/**
 * 獲取枚舉
 * @param ZHCN 中文枚舉
 * @param EN 英文枚舉
 * @returns 
 */
export const getEnum = (ZHCN: unknown, EN: unknown) => {
  const lang = getLanguage()
  switch (lang) {
    case 'zh-CN':
      return ZHCN
    case 'en-US':
      return EN
    default :
      return {}
  }
}

然后修改 error-code.ts 文件為,這樣就可以根據(jù)語言環(huán)境獲取對應(yīng)的枚舉值數(shù)據(jù)啦(其他枚舉同理)

import { getEnum } from "./index"
export const errorCodeEN =  {
  400: 'Error request, status code:400',
  401: 'Unauthorized, please login again, status code:401',
  403: 'Access denied, status code:403',
  404: 'Request error, the resource was not found, status code:404',
  405: 'Request method not allowed, status code:405',
  408: 'Request timeout, status code:408',
  500: 'Server side error, status code:500',
  501: 'Network not implemented, status code:501',
  502: 'Gateway error, status code:502',
  503: 'Service unavailable, status code:503',
  504: 'Network timeout, status code:504',
  505: 'The HTTP version does not support this request, status code:505',
}
export const errorCodeCN = {
  400: '錯誤請求,狀態(tài)碼:400',
  401: '未授權(quán),請重新登錄,狀態(tài)碼:401',
  403: '拒絕訪問,狀態(tài)碼:403',
  404: '請求錯誤,未找到該資源,狀態(tài)碼:404',
  405: '請求方法未允許,狀態(tài)碼:405',
  408: '請求超時,狀態(tài)碼:408',
  500: '服務(wù)器端出錯,狀態(tài)碼:500',
  501: '網(wǎng)絡(luò)未實現(xiàn),狀態(tài)碼:501',
  502: '網(wǎng)關(guān)錯誤,狀態(tài)碼:502',
  503: '服務(wù)不可用,狀態(tài)碼:503',
  504: '網(wǎng)絡(luò)超時,狀態(tài)碼:504',
  505: 'HTTP版本不支持該請求,狀態(tài)碼:505',
}
export default getEnum(errorCodeCN, errorCodeEN)

K、狀態(tài)管理引入(pinia、Vuex)

因為官網(wǎng)推薦pinia, 那咱直接也用上
可先看下初始化出來的模版已經(jīng)使用了 pinia
且默認沒有使用緩存操作,具體可在某個頁面引入 /src/stores/counter.ts 且里面的寫法是組合式開發(fā)
然后修改對應(yīng)字段值,在跳頁到另一個路由,再次引入 /src/stores/counter.ts獲取對應(yīng)字段,可以看到數(shù)據(jù)是被剛才修改過的值
例如路由 /a /b分別附上以下代碼

import { storeToRefs } from "pinia"
import { useCounterStore} from '@/stores/counter'
// 如果此代碼是抽離到了單獨ts文件內(nèi),那下面部分需要再 放置 setup 內(nèi)
// 變量需要使用 storeToRefs 轉(zhuǎn)為響應(yīng)式數(shù)據(jù)
const { count } = storeToRefs(useCounterStore())
// 方法直接使用即可
const { increment } = useCounterStore()
increment()
console.log('count', count)

如圖所示,路由 /a /b相互切換會發(fā)現(xiàn),count的值一直在疊加,說明數(shù)據(jù)是共享的

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

如果有緩存需求的也可再安裝個 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate -S
main.ts 文件引入插件

import { createApp } from 'vue'
import App from '@/App/index.vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import './assets/styles/app.less'
...
const app = createApp(App)
app.use(
  createPinia()
  .use(piniaPluginPersistedstate)
)
...
.mount('#app')

使用緩存的時候,定義方式不太一樣,不能使用組合式開發(fā),例如 /src/stores下新建 mapState.ts文件,具體寫法直接查看代碼,如下

import { defineStore } from 'pinia'

export interface MapState {
  address: string;
}
const { SIS_STORE_NAME } = import.meta.env

export const useMapStore = defineStore(SIS_STORE_NAME + 'map', {
  state: (): MapState => ({
    address: '',
  }),
  getters: {},
  actions: {
    setAdress(address: string) {
      this.address = address;
    },
    clearMessage() {
      this.address = '';
    },
  },
  persist: {
    /**
     * 使用的存儲
     * @default $store.id
     */
    key: SIS_STORE_NAME + 'map',
    /**
     * 存儲位置
     * @default localStorage
     */
    storage: sessionStorage,
    /**
     * 需要設(shè)置緩存的state 如果未設(shè)置即存儲所有state
     * @default undefined
     */
    // paths: [],
    /**
     * 存儲之前
     * @default null
     */
    beforeRestore: () => {},
    /**
     * 存儲之后
     * @default undefined
     */
    afterRestore: () => {},
     /**
     * 啟用時在控制臺中記錄錯誤。
     * @default false
     */
     debug: true
  },
});

使用方式如下

  • /a 路由設(shè)置值,然后看下緩存(當(dāng)前這是在sessionStorage
import { useMapStore} from '@/stores/mapState'
// 如果此代碼是抽離到了單獨ts文件內(nèi),那下面部分需要再 放置 setup 內(nèi)
// 變量需要使用 storeToRefs 轉(zhuǎn)為響應(yīng)式數(shù)據(jù)
const { setAdress } = useMapStore()
setAdress('驗證地區(qū)')

可看到已設(shè)置成功

vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

  • /b 路由獲取值
import { useMapStore} from '@/stores/mapState'
// 如果此代碼是抽離到了單獨ts文件內(nèi),那下面部分需要再 放置 setup 內(nèi)
// 變量需要使用 storeToRefs 轉(zhuǎn)為響應(yīng)式數(shù)據(jù)
const { address } = useMapStore()
console.log('address', address)

可看到打印的數(shù)據(jù)是上面設(shè)置的值(不刷新頁面的情況下,在 mapState.ts文件關(guān)閉緩存也是可以獲取值的)
vue3+ts+vite搭建,構(gòu)建工具,javascript,webpack,前端

J、按需引入資源

例如項目使用了Echarts,如果全量引入,會增加構(gòu)建后的文件大小,且大部分項目不可能使用Echarts的大部分圖形的,這個時候咱就需要按需引入項目所用到的部分啦。
由于之前寫了篇Echarts的使用(優(yōu)化按需引入),有此需要的可移步閱讀哈

K、優(yōu)化構(gòu)建

優(yōu)化構(gòu)建其實也包含了按需引入資源、圖片壓縮、js壓縮等

這個優(yōu)化之前也單獨寫了篇打包優(yōu)化之vite構(gòu)建(視圖分析、CDN引入、依賴分包、gzip壓縮),有興趣的大佬可異步閱讀哈

三、項目結(jié)構(gòu)再次優(yōu)化

至此需要配置優(yōu)化的部分基本都已搞完

當(dāng)然除了上面講過的,還有一些文件夾定義規(guī)范,例如

  • App 抽離項目路由入口
  • composables 公用Hooks函數(shù)
  • entity 實體(class類)
  • interface 接口類型定義

…等等

根據(jù)本人項目習(xí)慣項目結(jié)構(gòu)具體如下(后面再花點時間構(gòu)以此結(jié)構(gòu)建個簡易的完整配置項目上傳,有興趣的小伙伴也可按照上述步驟一步步配置屬于自己的自定義模版)

└── build // 構(gòu)建抽離
    ├── proxy.js // 接口代理配置
└── docs  // 項目文檔說明
    ├── user-url.json // 項目測試連接賬號
└── env  // 環(huán)境變量相關(guān)配置
    ├── .env // 公用變量配置
    ├── .env.development // 開發(fā)環(huán)境變量配置
    ├── .env.production // 生產(chǎn)環(huán)境變量配置
    ├── .env.sit // 測試環(huán)境變量配置
    ├── .env.uat // 業(yè)務(wù)驗收環(huán)境變量配置
└── public // 靜態(tài)資源(無需經(jīng)過構(gòu)建內(nèi)容)
└── src
    ├── App // 項目路由入口
    └── assets // 靜態(tài)文件
        ├── dic // 字段庫
        ├── images // 圖片
        ├── js // js庫
        ├── styles // 樣式庫
    └── components // 公用組件
    └── composables // 公用Hooks函數(shù)
    └── const // 常量定義
    └── entity // 實體(class類)-- 頁面級別
    └── enum // 枚舉值
    └── infrastructure // 基礎(chǔ)設(shè)施實體(class類) -- 項目級別(如配置數(shù)據(jù)、人臉、定位等功能相關(guān)實體)
    └── interface // 類型定義
    └── lang // 多語言
    └── router // 路由配置
    └── server // 接口
    └── sotres // 狀態(tài)管理(緩存)
    └── types // 自定義全局類型
    └── utils // 常用方法
    └── views // 頁面
    └── main.js // Vue配置入口
├── .eslintrc.cjs // ESLint 規(guī)則配置
├── index.html // 項目單頁入口
├── package.json // 項目依賴

總結(jié)

由于之前幾乎都是使用Webpack 構(gòu)建項目,偶爾使用了gulp。最近兩年才開始使用Vue3開發(fā)項目,所以特意記錄下Vite構(gòu)建期間的使用,可以嘗試按照上述步驟配置下,歡迎各位大佬評論交流。后續(xù)也會花時間寫下webpack構(gòu)建項目的文章,期待后期的更新~文章來源地址http://www.zghlxwxcb.cn/news/detail-754252.html

到了這里,關(guān)于vite+vue3+ts項目構(gòu)建詳細步驟(配置多語言版本)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • vue3-ts-vite:vue 項目 配置 多頁面應(yīng)用

    vue3-ts-vite:vue 項目 配置 多頁面應(yīng)用

    一、Vue項目,什么是多頁面應(yīng)用 Vue是一種單頁面應(yīng)用程序(SPA)框架,這意味著Vue應(yīng)用程序通常只有一個HTML頁面,而在該頁面上進行動態(tài)的內(nèi)容更改,而不是每次都加載新的HTML頁面。? 但是,有時候我們需要在同一應(yīng)用程序中擁有多個獨立的頁面,每個頁面都可以單獨處理

    2024年02月14日
    瀏覽(44)
  • vite+vue3+ts項目上線docker 配置反向代理API

    vite+vue3+ts項目上線docker 配置反向代理API

    這次重點的坑是反向代理。 1。項目中配置代理,為了跨域請求數(shù)據(jù) 項目根目錄中新建vite.config.ts文件 在文件中添加配置代理 注意:其中 \\\'/api\\\' 和target 的地址后面沒有 \\\'/\\\' 2。在項目根目錄中新建Httprequest.ts文件,引入axios,并封裝請求 引入axios就不多說了,npm自行安裝就好 注

    2024年02月20日
    瀏覽(21)
  • 基于Vue3+Vite+TS+ESLint+Prettier+Husky+lint-staged+commitlint+stylelint的項目構(gòu)建

    基于Vue3+Vite+TS+ESLint+Prettier+Husky+lint-staged+commitlint+stylelint的項目構(gòu)建

    博客后臺管理系統(tǒng)使用后的是基于Vue3+Vite+TS+ESLint+Prettier的開發(fā),具體項目構(gòu)建如下 ESLint: 控制代碼質(zhì)量 Prettier: 控制代碼風(fēng)格 2.1、安裝ESLint、Prettier相關(guān)相關(guān)包 eslint: ESLint的核心代碼庫 prettier: Prettier的格式化代碼的核心代碼庫 eslint-config-airbnb-base: airbnb的代碼規(guī)范(依賴pl

    2024年02月07日
    瀏覽(29)
  • 配置Vite獲取內(nèi)網(wǎng)IP(Vue3項目?ts版本獲取本機局域網(wǎng)IP地址)

    參考文章:vue項目獲取本機局域網(wǎng)IP地址(vue.config.js版本) 在Vite中,沒有vue.config.js文件,而是使用vite.config.js(或vite.config.ts,如果項目使用TypeScript)來配置項目; 1.獲取 IP 需要借助? os ?模塊,需要先安裝依賴: 2.其次在vite.config.ts中引用模塊 ?3.接著,添加一個獲取本機內(nèi)

    2024年02月05日
    瀏覽(19)
  • Electron + Vue3 + Vite + TS 構(gòu)建桌面應(yīng)用

    Electron + Vue3 + Vite + TS 構(gòu)建桌面應(yīng)用

    之前是使用React、Electron、TS和webpack來構(gòu)建桌面應(yīng)用的。雖然功能齊全,但是打包等等開發(fā)的體驗不太理想,總感覺太慢了。作為一個開發(fā)者,我們總是希望,執(zhí)行構(gòu)建命令后,可以快速打包或者啟動本地應(yīng)用,且通過更少的配置,來完成開發(fā)體驗。 現(xiàn)在的vite已經(jīng)得到廣泛的

    2024年02月14日
    瀏覽(34)
  • 超級詳細 最新 vite4+vue3+ts+element-plus+eslint-prettier 項目搭建流程

    系列文章目錄 【element-plus】 table表格每行圓角解決方案 element也通用 【Vue3+Vite+Ts+element-plus】使用tsx實現(xiàn)左側(cè)欄菜單無限層級封裝 超級詳細GitBook和GitLab集成步驟【linux環(huán)境】 1.1、項目創(chuàng)建 執(zhí)行以下代碼將vite將會自動生成初始的 vite4+vue3+ts的項目模板,pnpm、npm、yarn 選擇一種執(zhí)

    2024年02月04日
    瀏覽(25)
  • 前端新手Vue3+Vite+Ts+Pinia+Sass項目指北系列文章 —— 第十二章 常用工具函數(shù) (Utils配置)

    前端新手Vue3+Vite+Ts+Pinia+Sass項目指北系列文章 —— 第十二章 常用工具函數(shù) (Utils配置)

    在項目開發(fā)中,我們經(jīng)常會使用一些工具函數(shù),也經(jīng)常會用到例如 loadsh 等工具庫,但是這些工具庫的體積往往比較大,如果項目本身已經(jīng)引入了這些工具庫,那么我們就沒有必要再引入一次,所以我們需要自己封裝一些工具函數(shù),來簡化我們的開發(fā)。 在 src/utils 目錄下創(chuàng)建

    2024年02月20日
    瀏覽(28)
  • vite vue3項目打包,跳過ts檢查

    vite vue3項目打包,跳過ts檢查

    遇到這個問題是因為vue文件中script標簽沒有寫lang造成的? 剩下的ts類型檢查錯誤 ?\\\"build\\\": \\\"vue-tsc --noEmit --skipLibCheck vite build\\\",是因為這個vue-tsc打包對ts進行了類型檢查,需要全部解決了才行,可以關(guān)閉,直接改成\\\"build\\\": \\\"vite build\\\",

    2024年02月16日
    瀏覽(97)
  • vue3+vite+ts+elementplus創(chuàng)建項目

    # vue3+vite+ts+pinia 學(xué)習(xí)筆記 ## 1、創(chuàng)建項目: npm init vite@latest ? ? 選擇: vue、ts ## 2、進入項目目錄后:npm install 安裝 ## 3、運行項目: npm run dev ## 4、安裝常用插件: ? ? 1、安裝 npm install vue-router@latest 配置:在src目錄下新建router目錄,創(chuàng)建index.ts文件代碼如下: ? ? ? ```javascript 創(chuàng)建

    2024年02月09日
    瀏覽(19)
  • vue3+ts+vite項目引入echarts,vue3項目echarts組件封裝

    vue3+ts+vite項目引入echarts,vue3項目echarts組件封裝

    技術(shù)棧 :Vue3 + Ts + Vite + Echarts 簡介 : 圖文詳解,教你如何在 Vue3 項目中 引入Echarts , 封裝Echarts組件 ,并實現(xiàn)常用Echarts圖例 1.1 靜態(tài)效果 1.2 動態(tài)效果 2.1 安裝 Echarts npm: pnpm: 2.2 main.ts 中引入 2.3 Echarts 組件封裝 /src/components/ReEcharts/index.vue 文件中寫入如下代碼 3.1 柱狀圖 實現(xiàn)

    2024年02月09日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包