迁移收益
- 项目性能提升
- 开发体验优化
- 更好理解 Vite 原理
迁移步骤
- 切换到新分支
git checkout -b vite
,不成功还能回到原来的分支 - 删除 node_modules
pnpm i rimraf -g
rimraf node_modules
- 删除 package-lock.json
rimraf package-lock.json
- 删除 package.json 中与 webpack 相关的开发依赖 (devDependencies),配置 vite 脚本
- 安装 vite
pnpm i vite -D
- 安装 vue2 支持插件
pnpm i @vitejs/plugin-vue2 -D
- 迁移 vue.config.js 到 vite.config.js
- 把
public/index.html
移动到根目录index.html
,并修改占位符href="<%= BASE_URL %>favicon.ico"
- 语法转换:动态导入,浏览器环境获取环境变量
index.html
迁移
webpack: public/index.html + .env
zsh
VUE_APP_TITLE=NAAS SDWAN
BASE_URL=/xxx/admin
html
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= VUE_APP_TITLE %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= VUE_APP_TITLE %> doesn't work properly without
JavaScript enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
vite: /index.html + vite.config.js(plugins)
js
plugins: [
vue(),
createHtmlPlugin({
inject: {
data: {
title: 'APP TITLE',
},
},
}),
]
html
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<title><%= title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= title %> doesn't work properly without JavaScript
enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
配置文件迁移
vue.config.js
js
const path = require('node:path')
function resolve(relativePath) {
return path.join(__dirname, relativePath)
}
const webpack = require('webpack')
const isProduction = process.env.NODE_ENV
module.exports = {
publicPath: '/xxx/admin', // www.xxx.com/xxx/admin
configureWebpack: (config) => {
if (isProduction === 'production') {
return {
resolve: {
alias: {
'@': resolve('src'),
},
},
optimization: {
runtimeChunk: 'single',
// 分离js
splitChunks: {
chunks: 'all', // chunk 可以在异步和非异步 chunk 之间共享
maxInitialRequests: Number.POSITIVE_INFINITY, // 最大并行请求数
minSize: 20000, // 生成 chunk 的最小体积
maxSize: 60000, // 若引入的模块大于60kb,则告诉webpack尝试再进行拆分
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 使用正则匹配node_modules中引入的模块
priority: -10,
name(module) {
// 设定分包以后的文件模块名字,按照包名字替换拼接一下
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1]
return `npm.${packageName.replace('@', '')}`
},
},
},
},
},
}
}
else {
return {
resolve: {
alias: {
'@': resolve('src'),
},
},
}
}
},
chainWebpack(config) {
config.module.rule('js').exclude.add(resolve('src/assets/fonts')).end()
},
devServer: {
proxy: {
'/xxx/api': {
target: 'http://172.16.16.16',
ws: false,
changeOrigin: true,
},
},
},
}
vite.config.js
js
import { resolve } from 'node:path'
import { defineConfig, splitVendorChunkPlugin } from 'vite'
import vue from '@vitejs/plugin-vue2'
import { createHtmlPlugin } from 'vite-plugin-html'
import { autoComplete, Plugin as importToCDN } from 'vite-plugin-cdn-import'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
base: '/xxx/admin',
resolve: {
alias: {
'@': `${resolve(__dirname, 'src')}`,
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
plugins: [
vue(),
visualizer(),
splitVendorChunkPlugin(),
createHtmlPlugin({
inject: {
data: {
title: 'NAAS SDWAN',
},
},
}),
/* importToCDN 不能与 AutoImport 一起使用,
否则会报错:Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../". */
importToCDN({
modules: [
autoComplete('crypto-js'),
autoComplete('xlsx'),
autoComplete('file-saver'),
],
}),
],
server: {
port: 7000,
open: true,
host: true,
proxy: {
'/xxx/api': {
target: 'http://172.16.16.16',
ws: false,
changeOrigin: true,
},
},
},
build: {
rollupOptions: {
},
},
})
语法转换
动态导入-动态添加路由
js
const modules = import.meta.glob('@/views/**/*.vue')
// ...
routeList.forEach((item) => {
routes.push({
name: item.name,
path: item.path,
// component: () => import(`@/${item.componentPath}`),
component: modules[item.componentPath],
meta: {
title: item.label,
},
})
})
vite:
浏览器环境获取环境变量
webpack: process.env.VUE_APP_TITLE
vite: import.meta.env.VITE_APP_TITLE
js
const router = new VueRouter({
mode: 'history',
// base: process.env.BASE_URL,
base: import.meta.env.BASE_URL,
routes,
})