如果你在2021年之前一直在使用Vue开发,那么你选择的构建工具很可能是Vue CLI。它已经成为Vue.js项目支架的事实标准了。不过现在,Evan You的下一代构建工具Vite已经获得了很多关注,是Vue CLI的一个很好的替代品。
为什么从Vue CLI迁移到Vite?
迁移的主要原因是速度问题。Vite的开发服务器非常快。因为它使用本地浏览器对JavaScript模块的支持,服务器的启动时间是即时的。这种方法还意味着,无论应用程序的大小如何,热模块替换都会保持快速,因为整个捆绑包不必重新构建。
为了证明这一点,下面是一个全新的Vue CLI项目与使用Vite的相同项目的基准比较。
- 开始时间。
- Vue CLI - 2591ms (超过2秒)
- Vite - 259ms (远低于半秒 - 10倍快) ⚡️
- 热模块替换(HMR)。
- Vue CLI - 171ms
- Vite - 不是通过Vite打印到控制台,而是通过观察......基本上是即时的。
请记住,这只是脚手架式的模板。随着你的项目的增长,Vue CLI版本会逐渐变慢,而Vite承诺无论你的项目大小,都会有同样的表现。
如何从Vue CLI迁移到Vite
所以你确信Vite适合你,那么你如何将你的项目从使用Vue CLI迁移到Vite呢?
为了回答这个问题,我用Vue CLI建立了一个全新的项目,我将和你一起完成将其转换为Vite的步骤。当然,你通常不会从一个全新的Vue CLI项目开始,但其中许多步骤对你已建立的项目是一样的。
另外,我选择从Vue 2的代码库开始工作,因为你们中的大多数人可能都有自己成熟的代码库仍在Vue 2上运行。然而,我也在下面的过程中对Vue 3的不同之处做了说明。
最后,如果你不想和我一起走完整个过程,你可以在这个例子 repo 中看到变化的差异。
第一步:更新依赖关系
迁移到Vite的第一步是更新package.json中的依赖项。我们需要删除Vue CLI相关的依赖。
// package.json
"@vue/cli-plugin-babel": "~4.5.0", // remove
"@vue/cli-plugin-eslint": "~4.5.0", // remove
"@vue/cli-plugin-router": "~4.5.0", // remove
"@vue/cli-plugin-vuex": "~4.5.0", // remove
"@vue/cli-service": "~4.5.0", // remove
我们也可以删除sass-loader,因为Vite为最常见的预处理器提供了开箱即用的内置支持。这将使我们能够继续使用我们选择的CSS预处理器。但要注意的是,Vite建议使用本地CSS变量与PostCSS插件,这些插件实现了CSSWG草案,并编写了符合未来标准的普通CSS。
// package.json
"sass-loader": "^8.0.2" // remove
最后,我们将添加Vite作为一个依赖项,以及Vite的Vue插件组件,以支持单文件组件。
// package.json
"@vitejs/plugin-vue": "^1.6.1",
"vite": "^2.5.4",
此外,由于我们正在迁移一个Vue 2项目,除了官方的Vue插件外,我们还需要包括社区维护的Vue 2的Vite插件。如果我们使用的是Vue 3,这就没有必要了。
// package.json
"vite-plugin-vue2" : "1.9.0" // add for Vue 2
安装了Vite插件后,我们现在也可以删除vue模板编译器,因为那是由Vite Vue插件处理的。
// package.json
"vue-template-compiler": "^2.6.11" //remove (SFC support provided by vite vue plugin)
第二步:只为现代浏览器提供支持
由于Vite是下一代的构建工具,让我们乐观地进行,只支持最现代的浏览器。这将使我们的构建尽可能地精简和快速。
实际上,这意味着我们可以将Babel从我们的依赖中完全删除,因为大多数移动和桌面的常青浏览器几乎完全支持所有ES6功能。如果你仍然需要支持旧的浏览器,如Internet Explorer 11,Vite确实为此提供了一个官方插件。
因此,要删除Babel,首先我们要删除babel.config.js 文件。
接下来,由于我们已经删除了需要babel本身的@vue/cli-plugin-babel 依赖,我们只需要从package.json中删除其他几个与babel有关的依赖。
// package.json
"babel-eslint": "^10.1.0", // remove
"core-js": "^3.6.5", // remove
现在删除了babel-eslint ,我们需要把它作为解析器从我们的.eslintrc 文件中删除。
// .eslintrc
// remove
parserOptions: {
parser: "babel-eslint",
},
注意:如果你的项目中没有设置linting/formatting,你可以跳到下一步,但如果你还没有,我强烈建议你把它加进去。这里有一个很好的教程,可以让你在Vite驱动的Vue项目中设置它。
最后,当我们在.eslintrc ,我们需要将环境从node更新为es2021 ,因为我们只支持那些常青的浏览器。
// .eslintrc
env: {
node: true, // remove
es2021: true,
}
这一变化也将迫使我们更新eslint 本身,以及eslint-plugin-vue ,以支持es2021的环境。
$ npm install [email protected] [email protected]
第三步:添加Vite配置
在这一步,让我们为我们的Vue.js项目配置Vite。Vite是通过项目根部的一个vite.config.js 文件配置的。这是默认的vite.config.js 文件的样子,在为Vue生成一个全新的Vite项目时,它使用的是 npm init [[email protected]](https://vueschool.io/cdn-cgi/l/email-protection).
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()]
})
我们还要为它添加两样东西。
首先,我们将从vite-plugin-vue2 中导入Vue插件,而不是官方的Vite Vue插件。
// vite.config.js
import vue from '@vitejs/plugin-vue' // remove
import { createVuePlugin as vue } from "vite-plugin-vue2";
//...
如果你使用的是Vue 3,当然,你不需要这样做。
其次,为了让@ 的导入别名像在Vue CLI中那样工作,我们需要添加这一点。
// vite.config.js
//...
const path = require("path");
export default defineConfig({
//...
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
第四步:移动index.html
与Vue CLI不同的是,Vite实际上将存放Vue.js应用程序的index.html文件放在项目的根目录下,而不是公共目录下,所以你需要移动它。
在index.html中,你还需要做一些修改。
首先,我们要把<%= htmlWebpackPlugin.options.title %> 占位符的实例改为硬编码值。
// index.html
<!--remove-->
<title><%= htmlWebpackPlugin.options.title %></title>
<!--add-->
<title>Hard Coded Title</title>
//...
<!--remove-->
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<!--add-->
<strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
我们还需要将<%= BASE_URL %> 占位符替换为绝对路径。
// index.html
<!--remove-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!--add-->
<link rel="icon" href="/favicon.ico">
最后,也是最重要的,JavaScript应用程序不再是自动注入的,所以我们需要像这样包含它。
<script type="module" src="/src/main.js"></script>
第五步:更新脚本
回到package.json中,我们还需要更新脚本。我们将把旧的vue-cli-service 命令改为Vite的特定命令。
// package.json
"serve": "vue-cli-service serve", // remove
"build": "vue-cli-service build", // remove
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
注意,启动开发服务器的命令不再是serve 。Vite使用dev ,而serve ,用于在本地预览生产构建。
另外,如果你启用了linting,你应该更新lint脚本,直接运行eslint。
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
步骤#6:更新环境变量
环境变量在Vite中的工作方式和在Vue CLI中的工作方式有很多交叉之处。例如,你的.env命名规则可以保持不变。
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified mode
.env.[mode].local # only loaded in specified mode, ignored by git
然而,你不能再在process 变量上访问环境变量。相反,它们可以在import.meta.env 。
// router/index.js
base: process.env.BASE_URL, //remove
base: import.meta.env.BASE_URL,
此外,用于使声明客户端暴露的环境变量更明显的VUE_APP_ 前缀被改为VITE_ ,所以如果你有任何这样的环境变量,你必须相应地更新它们。
第7步:为SFC导入添加.vue扩展名
虽然我们新创建的Vue CLI项目已经这样做了,但我敢打赌,你现有的应用程序可能没有这样做。所以,你必须确保所有导入的单文件组件以.vue 后缀结束。
// Home.vue
import HelloWorld from "@/components/HelloWorld.vue"; // .vue is required
如果这个过程由于你的代码库的大小而显得过于庞大,你可以配置vite,这样就不需要这样做了。这可以通过在vite.config.js 的resolve.extensions 配置选项中添加.vue 来实现。请确保你也手动包括所有的默认扩展,因为这个选项覆盖了默认。
// vite.config.js
//...
export default defineConfig({
plugins: [vue()],
resolve: {
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
//...
},
});
虽然这样做可以,但如果可能的话,应该避免这样做。为什么?因为根据Vite的文档。"注意,不建议省略自定义导入类型的扩展(例如:.vue ),因为它可能干扰IDE和类型支持。"
第8步:清理魔法注释
最后,你可以删除所有用于命名动态导入的魔法注释,因为这些是webpack的特定注释,对Vite没有任何意义。
// router/index.js
import(
/* webpackChunkName: "about" */ // remove
"../views/About.vue"
),
相反,Vite会根据原始的.vue文件名和一个破坏缓存的哈希值来自动命名你的块,像这样。About.37a9fa9f.js
第九步:享受更快、更无缝的开发体验
在完成上述第1-8步后,你的应用程序就可以开始使用Vite了。来吧,用npm run dev 启动你的开发服务器,看看Vite的速度有多快。
如果你在这时有任何其他错误出现,请在下面评论并与社区分享,以及你可能有的任何解决方案
最后,请记住,你可以在这个示例 repo 中看到所有这些变化的差异,以帮助你的迁移。