vite发布前:学不动了。。
vite使用后:真香!!ESM YYDS!
前言
为什么选vite?
在浏览器支持 ES 模块之前,我们见证了诸如 webpack、Rollup 和 Parcel 等工具的变迁,它们极大地改善了前端开发者的开发体验。然而,当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。
Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。
迁移前后对比
类别 | 迁移前webpack4 | 使用vite后 |
---|---|---|
启动 | 4分钟 | 2秒 |
热更新 | 3秒 | 毫秒级 |
打包 | 4分钟 | 1.5分钟 |
可以看到,这个提升是巨大的,之前启动项目以及打包的时间非常长。当我们开发多个项目,同时另一个项目需要修改或者定位一个紧急的bug时,而当前的项目开发又比较紧急;这个时候启动项目需要好几分钟是非常操蛋的。
提升性能后,不管是对于开发体验,还是提高开发效率,都有很大的帮助。
迁移流程
安装依赖
npm i vite vite-plugin-vue2 vite-plugin-svg-icons @originjs/vite-plugin-commonjs -D
vite:代替webpack的打包工具
vite-plugin-vue2:支持vue2语法的插件
vite-plugin-svg-icons:批量处理svg的插件,替换webpack的svg-sprite-loader
@originjs/vite-plugin-commonjs:兼容处理commonjs模块
文件迁移
-
将index.html从public迁移到根目录下,并删除webpack设置,如<%= webpackConfig.name %>等 添加script标签type="module",并引入src下的main.js
-
修改package.json中的scripts,启动和打包方式使用vite
"serve": "vite",
"build": "vite build",
-
添加vite.config.js配置文件
不知道具体怎么配置的可以参考官方文档vitejs.cn/config/
你也可以把vue.config.js直接改名vite.config.js,并在此基础上做修改,导出语法修改成export default,同时对里面的webpack的配置做删减,只有一小部分的可以复用。
添加plugins配置
首先导入我们上面安装的依赖插件,并放入到plugins的配置里面
如果你的项目中使用了vue中的jsx语法,需要在
createVuePlugin
方法中传入{ jsx: true }
,同时在对应的模块中的script标签添加lang="jsx"
,否则会报错。还有,如果你使用了
vite-plugin-svg-icons
插件,还需要在main.js中加入import "virtual:svg-icons-register";
添加resolve配置
在这里我们需要把别名的配置放在这里,以及导入时想要省略的扩展名列表(vite默认可忽略的扩展名是'.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'),如果不加入扩展名的配置,vite将不会识别引入'xx/index'的vue文件
添加css配置
我的项目里只用到了css预处理,如果你的项目中还用到了
CSS modules
或者postcss
的配置,可以参考官方文档。这里提一嘴,有的文件中引入了scss文件,使用了
~
前缀,而vite
解析不了,所以没有找到对应的文件。那我们要做的就是把~
前缀删除掉,同时确保路径的正确性。开发服务器配置
这里可以把vue.config.js中的devServer直接复制过来,放到server里。当然也不只是名字变了一下,当然大部分的配置还是很相似,直接拿过来用也不会出什么问题。
OK,那我们启动项目吧
好的,我们命令行输入npm run serve
,等待项目启动。在这个过程中,我们先去抽根烟吹个比吧。纳尼???启动好了???仿佛失去了一个可以划水的理由,手动狗头。
先别偷着乐,启动后你可能会看到控制台报了错,比如使用了require语法
,或者是一些遗漏没有修改的模块。
那现在,我们需要把之前没修改的文件修改好,还有把require语法
替换成em的import语法
,require.context
替换成vite提供的import.meta.glob
方法。
如果你的项目对一些ui框架中的某个组件做了定制化(复制了出来,单独做了修改),你可能还会发现引入路径的问题。貌似扩展名配置没起作用,当然这个不是你的问题。那我们现在应该怎么办呢?如果你是全局引入,那我们就不需要在手动引入组件了,直接删掉就ok;如果你是按需引入,直接在main.js里引入或者在当前文件,从模块中引入而非路径中。
打包
如果你解决了以上的报错问题,恭喜你。可以愉快的开发了。
接着我们在试着打包一下,命令行输入npm run build
,如果你没有报错,也打包成功了,那恭喜你。
当然,这里还没有结束。因为我们知道,目前还有很多的npm包还是使用的commonjs规范。如果你的项目中有这样的情况,打包是失败的。
这时,我们需要告诉vite,其实是rollup。这些文件中含有commonjs模块。 我们需要在vite.config.js中加入打包的配置。
接着我们再试着打包。
ok,打包完成。
总结
现在vite的生态也日趋成熟,已经可以满足于大部分业务场景了,不过在迁移前还是尽量要做下调研,看目前vite生态是否满足本项目中一些定制化或者特殊的场景。
本文记录了楼主在项目迁移过程中遇到的问题,遇到的问题肯定只是webpack迁移vite的部分问题,以后在迁移其他项目时候遇到新的问题也会补充进来。
本次迁移最终vite配置
import { createVuePlugin } from 'vite-plugin-vue2'
import { viteCommonjs } from '@originjs/vite-plugin-commonjs'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
function resolve(dir) {
return path.join(__dirname, dir)
}
const port = process.env.port || process.env.npm_config_port || 9528 // dev port
export default {
base: '/',
lintOnSave: false,
productionSourceMap: false,
build: {
commonjsOptions: { include: ['.cjs', 'node_modules/**/*'] },
outDir: 'dist',
assetsDir: 'static',
sourcemap: true
},
server: {
port: port,
open: true,
proxy: {
'/v1': {
target: 'https://111.111.111.111',
ws: true,
secure: false,
changeOrigin: true,
pathRequiresRewrite: {
'^/v1': '/'
}
}
}
},
plugins: [
createVuePlugin({ jsx: true }),
viteCommonjs(),
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/icons')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
/**
* 自定义插入位置
* @default: body-last
*/
inject: 'body-first',
/**
* custom dom id
* @default: __svg__icons__dom__
*/
customDomId: '__svg__icons__dom__'
})
],
resolve: {
alias: [
{ find: '@', replacement: resolve('src') },
{ find: '@json', replacement: '/json/' },
{ find: '@assets', replacement: '/src/assets/' },
{ find: '@com', replacement: '/src/components/' },
{ find: '@api', replacement: '/src/api/' },
{ find: '@store', replacement: '/src/store/' },
{ find: '@views', replacement: '/src/views/' },
{ find: '@utils', replacement: '/src/utils/' }
],
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue', '.cjs']
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/base/_variables.scss";`
}
}
}
}