vue2 遷移到vite

前言:直接安裝下面幾個(gè)依賴 @types/node后面要使用 vue2版本建議2.7以上
node -v: v16.17.1
npm -v: 9.4.0

"dependencies": {  
    "vue": "2.7.10",
  },
  "devDependencies": {
    "@types/node": "^20.4.7",
    "@vitejs/plugin-vue2": "^2.2.0",
    "vite": "^4.4.8"
  }

1.vite.config.js配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
  plugins: [
    vue(),
  ]
})

2.導(dǎo)入時(shí)省略文件類型后綴
我們在導(dǎo)入 vue逝她、js 等文件時(shí)往往喜歡省略類型后綴,這需要配置 extensions

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
  },
})

3.配置路徑別名

import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': resolve('src'),
    },
    extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
  },
})

4.環(huán)境變量 vite環(huán)境變量地址

.env.development  // 開發(fā)環(huán)境
.env.dev          // 測試環(huán)境
.env.production   // 線上環(huán)境

5.package.json設(shè)置啟動命令

    "serve:dev": "vite --mode dev",
    "serve:beta": "vite --mode beta",
    "serve:prod": "vite --mode prod",
    "build:dev": "vite build --mode dev",
    "build:beta": "vite build --mode beta",
    "build:prod": "vite build --mode prod",

6.本地啟動不同環(huán)境

開發(fā)環(huán)境:pnpm serve:dev
測試環(huán)境:pnpm serve:beta
生產(chǎn)環(huán)境:pnpm serve:prod

報(bào)錯(cuò)問題匯總

Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/path-to-regexp.js?v=ba8728b6' does not provide an export named 'default' (at index.vue:19:1)
解決方法:
import pathToRegexp from 'path-to-regexp'
替換
import * as pathToRegexp from 'path-to-regexp'

2.import.meta.glob替換require.context vite官網(wǎng)指南

const modulesFiles = require.context('./modules', true, /\.js$/)
替換
const modulesFiles = import.meta.glob('./modules/*.js')
  1. import.meta.glob('./modules/*.js',{ eager: true }) 加上第二個(gè)參數(shù)直接導(dǎo)入,不加默認(rèn)異步導(dǎo)入

2.導(dǎo)入文件夾下所有.vue 文件 加上第二個(gè)參數(shù){ eager: true }直接導(dǎo)入:

const allComponents = import.meta.glob('./components/*/*.vue',{ eager: true })
const res_components = {}
Object.entries(allComponents).forEach(([path, Module]) => {
  const name = Module.default.name
    res_components[name] = Module.default
})

export default {
  components: { ...res_components },
}

3 導(dǎo)入文件夾下所有.js 文件 以導(dǎo)入store為例:

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

Vue.use(Vuex)
const modulesFiles = import.meta.glob('./modules/*.js',{ eager: true })
const modules = Object.entries(modulesFiles).reduce((modules, [path, Module]) => {
  const moduleName = path.slice(10,-3)
  modules[moduleName] = Module.default
  return modules
}, {})
const store = new Vuex.Store({
  modules,
  getters
})
export default store

store結(jié)構(gòu)如下:


WechatIMG167.jpg

3.圖片引入問題

logo: require('@/assets/images/xiaoxiang_logo.png')
替換
import logo from '@/assets/images/xiaoxiang_logo.png'

4.icons svg目錄引入處理

  1. 安裝依賴插件 vite-plugin-svg-icons

yarn add vite-plugin-svg-icons

  1. 安裝 fast-glob

yarn add fast-glob

  1. 配置 vite.config.js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
      iconDirs: [resolve(__dirname, 'src/icons/svg')],
      symbolId: 'icon-[name]'
    }),
  ],
  resolve: {
    alias: {
      '@': resolve('src'),
    },
    extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
  },
})
  1. 在 main.js入口注冊腳本
import 'virtual:svg-icons-register'
注意: vite-plugin-svg-icons 插件注冊申鱼,不引入會導(dǎo)致svg圖標(biāo)無法正常顯示
  1. 封裝 SvgIcon 組件
<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
import { isExternal } from '@/utils/validate'

export default {
  name: 'SvgIcon',
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String,
      default: ''
    }
  },
  computed: {
    isExternal() {
      return isExternal(this.iconClass)
    },
    iconName() {
      return `#icon-${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
      } else {
        return 'svg-icon'
      }
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
      }
    }
  }
}
</script>

<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}

.svg-external-icon {
  background-color: currentColor;
  mask-size: cover!important;
  display: inline-block;
}
</style>
  1. main.js 注冊組件
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'
Vue.component('svg-icon', SvgIcon)

7.頁面使用

<svg-icon icon-class="bug" />
  1. vite無法使用node的模塊 要使用第三方插件 :vite官網(wǎng)提示地址
    通過polyfill解決方法:
  1. 安裝依賴
yarn add @esbuild-plugins/node-globals-polyfill
yarn add @esbuild-plugins/node-modules-polyfill

2.vite.config.js的配置如下

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
plugins: [
  vue(),
  createSvgIconsPlugin({
    iconDirs: [resolve(__dirname, 'src/icons/svg')],
    symbolId: 'icon-[name]'
  })
],
resolve: {
  alias: {
    '@': resolve('src'),
    path: 'rollup-plugin-node-polyfills/polyfills/path'
  },
  extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']
}
})

3現(xiàn)在就可以在組件中導(dǎo)入使用了

import { resolve } from 'path'
 resolve(basePath, router.path)

4path.resolve簡易替代品

// 解析文件路徑锨推。類似于path.resolve
export const pathResolve = (...paths) => {
  let resolvePath = ''
  let isAbsolutePath = false
  for (let i = paths.length - 1; i > -1; i--) {
    const path = paths[i]
    if (isAbsolutePath) {
      break
    }
    if (!path) {
      continue
    }
    resolvePath = path + '/' + resolvePath
    isAbsolutePath = path.charCodeAt(0) === 47
  }
  if (/^\/+$/.test(resolvePath)) {
    resolvePath = resolvePath.replace(/(\/+)/, '/')
  } else {
    resolvePath = resolvePath.replace(/(?!^)\w+\/+\.{2}\//g, '')
      .replace(/(?!^)\.\//g, '')
      .replace(/\/+$/, '')
  }
  return resolvePath
}

6.css sass 相關(guān)問題

1.vite.config.js配置全局加載scss

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
export default defineConfig({
 plugins: [
   vue(),
   createSvgIconsPlugin({
     iconDirs: [resolve(__dirname, 'src/icons/svg')],
     symbolId: 'icon-[name]'
   })
 ],
 resolve: {
   alias: {
     '@': resolve('src'),
     path: 'rollup-plugin-node-polyfills/polyfills/path'
   },
   extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']
 },
 css: {
   loaderOptions: {
     sass: {
       prependData: `
     @/styles/variables.scss";  // scss文件地址
     `
     }
   }
 }
})

2.CSS modules使用 vite官網(wǎng)CSS Modules地址

variables.module.scss

$menuText:#B4B9C8;
$menuActiveText:#fff;

:export {
  menuText: $menuText;
  menuActiveText: $menuActiveText;
}

slider.vue使用

<template>
  <el-menu
    :default-active="activeMenu"
    :collapse="isCollapse"
    :background-color="variables.menuBg"
    :text-color="variables.menuText"
    :unique-opened="true"
    :active-text-color="variables.menuActiveText"
    :collapse-transition="false"
    mode="vertical"
  >
    ...
  </el-menu>
</template>

<script>
import variables from "@/styles/variables.module.scss";

export default {
  computed: {
    variables() {
      return variables;
    },
  },
};
</script>

7.jsx文件配置

1.yarn add @vitejs/plugin-vue2-jsx -D

2.vite.config.js配置

import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
import vueJsx from '@vitejs/plugin-vue2-jsx'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
 plugins: [
   vue(),
   vueJsx(),
   createSvgIconsPlugin({
     iconDirs: [resolve(__dirname, 'src/icons/svg')],
     symbolId: 'icon-[name]'
   })
 ],
 resolve: {
   alias: {
     '@': resolve('src'),
     path: 'rollup-plugin-node-polyfills/polyfills/path'
   },
   extensions: ['.vue', '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']
 },
 esbuild: {
    jsxFactory: 'h',
    jsxFragment: 'Fragment'
  },
 css: {
   loaderOptions: {
     sass: {
       prependData: `
     @/styles/variables.scss";  // scss文件地址
     `
     }
   }
 }
})

  1. jsx文件支持模式@vitejs/plugin-vue2-jsx GitHub地址
import { defineComponent } from 'vue'

// named exports w/ variable declaration: ok
export const Foo = defineComponent({})

// named exports referencing variable declaration: ok
const Bar = defineComponent({ render() { return <div>Test</div> }})
export { Bar }

// default export call: ok
export default defineComponent({ render() { return <div>Test</div> }})

// default export referencing variable declaration: ok
const Baz = defineComponent({ render() { return <div>Test</div> }})
export default Baz

不支持模式

// not using `defineComponent` call
export const Bar = { ... }

// not exported
const Foo = defineComponent(...)

8.eslint 配置

1.依賴安裝

yarn add eslint  eslint-plugin-vue vite-plugin-eslint -D

2.vite.config.js配置


import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
import eslintPlugin from 'vite-plugin-eslint'
export default defineConfig({
  plugins: [
    vue(),
    eslintPlugin({
      include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue']
    })
  ]
})

3.在項(xiàng)目根目錄下新建.eslintrc.cjs

module.exports = {
 root: true,
 parserOptions: {
   sourceType: 'module'
 },
 env: {
   browser: true,
   node: true,
   es6: true
 },
 extends: ['plugin:vue/recommended', 'eslint:recommended'],
 // 規(guī)則參考 https://eslint.nodejs.cn/docs/latest/rules/
 rules: {
 }
}

1.rules相關(guān)配置參考官方文檔 規(guī)則參考
2.如果你是新建的.eslintrc.js以.js后綴的會報(bào)如下錯(cuò)誤芒帕,把后綴改為.cjs結(jié)尾就好了

vite/node_modules/.pnpm/@eslint+eslintrc@2.1.1/node_modules/@eslint/eslintrc/dist/eslintrc.cjs not supported.
.eslintrc.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename .eslintrc.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /Users/suesea/company/xiaoxiang/practice/vite/seller-admin-vite/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

4.vscode 安裝eslint插件

1.在vscode設(shè)置中點(diǎn)擊settings


WechatIMG171.jpg

2.切換到User,上面搜索eslint期吓,隨便點(diǎn)個(gè)藍(lán)色字體的Edit in settings.json 進(jìn)入設(shè)置頁面


WechatIMG169.jpg

3.添加配置,看紅框標(biāo)出的苛白,其他不用管,這一步是為了讓vscode的eslint插件在你點(diǎn)擊control + s 保存時(shí)幫你修復(fù)錯(cuò)誤
"editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
WechatIMG170.jpg

4.項(xiàng)目package.json可以加上一條修改eslint錯(cuò)誤的命令

 "lint": "eslint --fix --ext .js,.vue src",

項(xiàng)目遷移時(shí)eslint報(bào)錯(cuò)太多退客,運(yùn)行這個(gè)命令可以修復(fù)一部分,修復(fù)時(shí)要注意,修復(fù)完成后文件格式可能和之前不一致萌狂,這是配置的.eslintrc.cjs和未遷移之前不同導(dǎo)致的档玻。只能對比修改,看看不影響邏輯就行茫藏。

5.總結(jié)
1.vscode 安裝的eslint插件會會去找項(xiàng)目中安裝的eslit來運(yùn)行误趴,找不到就會去找全局的

 "devDependencies": {
    "eslint": "^8.46.0",
  }

2.一般情況下配置好.eslintrc.cjs,后綴要正確务傲,頁面如果有錯(cuò)誤的凉当,vscode的eslint插件就會給你標(biāo)紅
3.一般的小錯(cuò)誤eslint會幫你修復(fù),如果時(shí)規(guī)則導(dǎo)致的就需要你去關(guān)閉相應(yīng)的規(guī)則 規(guī)則參考

  'no-async-promise-executor': 'off', // 禁止使用異步函數(shù)作為 Promise 執(zhí)行器
    'no-prototype-builtins': 'off', // 禁止直接在對象上調(diào)用某些 Object.prototype 方法
    'vue/multi-word-component-names': 'off', // 關(guān)閉eslint檢查文件名是否為駝峰命名
    'vue/first-attribute-linebreak': [2, {
      // 單行時(shí)售葡,第一屬性前不允許使用換行符
      'singleline': 'beside',
      // 多行時(shí)看杭,第一屬性前必須使用換行符
      'multiline': 'below'
    }],

vue/multi-word-component-names
vue/first-attribute-linebreak
這兩個(gè)是eslint-plugin-vue中的,參考連接

9.vite項(xiàng)目優(yōu)化----- 解決終端optimized dependencies changed. reloading問題 //TODO
vue-count-to
vuedraggable
sortablejs
echarts
ali-oss
@wangeditor/editor-for-vue

10.配置autoprefixer自動添加前綴

yarn add autoprefixer -D

  css: {
    postcss: {
      plugins: [
        autoprefixer({
          overrideBrowserslist: [
            'Android 4.1',
            'iOS 7.1',
            'Chrome > 31',
            'ff > 31',
            'ie >= 8'
            // 'last 2 versions', // 所有主流瀏覽器最近2個(gè)版本
          ]
        })
      ]
    }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挟伙,一起剝皮案震驚了整個(gè)濱河市楼雹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尖阔,老刑警劉巖贮缅,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異介却,居然都是意外死亡谴供,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門齿坷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桂肌,“玉大人,你說我怎么就攤上這事胃夏≈峄颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵仰禀,是天一觀的道長照雁。 經(jīng)常有香客問我,道長答恶,這世上最難降的妖魔是什么饺蚊? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮悬嗓,結(jié)果婚禮上污呼,老公的妹妹穿的比我還像新娘。我一直安慰自己包竹,他們只是感情好燕酷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布籍凝。 她就那樣靜靜地躺著,像睡著了一般苗缩。 火紅的嫁衣襯著肌膚如雪饵蒂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天酱讶,我揣著相機(jī)與錄音退盯,去河邊找鬼。 笑死泻肯,一個(gè)胖子當(dāng)著我的面吹牛渊迁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灶挟,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼琉朽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了膏萧?” 一聲冷哼從身側(cè)響起漓骚,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榛泛,沒想到半個(gè)月后蝌蹂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曹锨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年孤个,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沛简。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡齐鲤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出椒楣,到底是詐尸還是另有隱情给郊,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布捧灰,位于F島的核電站淆九,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏毛俏。R本人自食惡果不足惜炭庙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望煌寇。 院中可真熱鬧焕蹄,春花似錦、人聲如沸阀溶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至迹卢,卻和暖如春辽故,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腐碱。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掉弛,地道東北人症见。 一個(gè)月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像殃饿,于是被迫代替她去往敵國和親谋作。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容