vite新项目试用总结
2021年12月21日 • ... • ☕️ 5 min read
Vite是一种新型前端构建工具,能够显著提升前端开发体验。它天然支持引入.ts文件,模块处理速度很快。最近新项目开坑,试用了一下,遇到一些问题,简单总结。
vite开发遇到的问题
1、Maximum call stack size exceeded
[vite:react-babel] .../node_modules/@ant-design/pro-layout/es/components/xx/index.js: Maximum call stack size exceeded
老版本react插件(不是react框架,是@vitejs/plugin-react
插件)的一个问题。解决办法是升级插件版本,或者在dev阶段不使用。
export default defineConfig(({mode}) => {
const isDevEnv = mode === 'dev';
return {
plugins: [
isDevEnv && react(),
]
}
}
2、antd样式引入错误
[plugin:vite:import-analysis] Failed to resolve import "antd/lib/row/style/index.less" from "src/views/xx". Does the file exist?
2 | import 'antd/lib/row/style/index.less'
| ^
3 | import 'antd/lib/col/style/index.less'
解决办法:使用vitePluginImp
插件引入样式
vitePluginImp({
libList: [
{
libName: 'antd',
libDirectory: 'es',
style: (name) => `antd/es/${name}/style`
}
]
})
3、国际化配置不生效
https://github.com/vitejs/vite/issues/3755
You should use moment/dist/locale/es instead of moment/locale/es. Else it will bundle two version of moment (umd version + es version). This issue is also from it.
意思是应该使用moment/dist/locale/es
,它包含两个版本,而moment/locale/es
只有umd版本(vite不识别)。
解决办法:把国际化配置文件中的
- import "moment/locale/zh-cn";
+ import "moment/dist/locale/zh-cn";
4、打包报错:
Unknown variable dynamic import: ../../../src/xx/xx/xx.tsx
原因:rollup不支持动态引入。
好消息是@rollup/plugin-dynamic-import-vars
插件可以支持变量。坏消息是这个变量的配置有限制。例如:
`./locales/${locale}.js` -> './locales/*.js'
`./${folder}/${name}.js` -> './*/*.js'`./module-${name}.js` -> './module-*.js'
注意第二行,./${folder}/${name}.js
匹配的是
.//.js
那么,如果folder
变量本身包含了多层目录,是识别不了的。
解决办法:使用vite支持的 glob导入,
const modules = import.meta.glob('./dir/*.js');
// vite 生成的代码
// const modules = {
// './dir/foo.js': () => import('./dir/foo.js'),
// './dir/bar.js': () => import('./dir/bar.js')
// }
// 所以 react lazy 可以这样使用
lazy(modules[`../../../src${componentInfo}/index.tsx`]);
5、代码分割
vite使用rollup处理打包问题,所以代码分割这部分基本透传rollup的配置(rollupOptions)。
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
return {
build: {
target: "es2015",
minify: "terser",
polyfillModulePreload: true,
outDir: "public",
assetsDir: "static",
terserOptions: {
compress: {
//生产环境时移除console
drop_console: true,
drop_debugger: true,
},
},
// 取消计算文件大小,加快打包速度
brotliSize: false,
rollupOptions: {
plugins: [
// babel({
// babelHelpers: "bundled",
// }),
typescript({
tsconfig: "./tsconfig.json",
}),
// isDevEnv &&
// visualizer({
// open: true,
// }),
],
rollupOptions: {
output: {
manualChunks: {
lodash: ["lodash"],
antd: ["antd"],
antCharts: ["@ant-design/plots", "@ant-design/maps"],
antComponents: [
"@ant-design/pro-layout",
"@ant-design/pro-table",
"@ant-design/pro-card",
],
},
}
}
}
}
});
6、ant-design charts打包问题
使用这个包,完全是因为产品使用了antd pro,心想配套的应该比较丝滑吧。谁知道,文档写的跟一坨shit一样,完全找不到想要的结果。和echarts比起来,antd charts简直就是直接把代码注释自动输出了一下,有的地方连函数接受的参数、返回值都懒得告诉你。满屏写着“爱用不用,不用滚”。
又比如我想知道坐标轴的label怎么能换行,直接输入查找
tmd。。
话说回来,这货也是支持模块引入的。如果看官方文档,会推荐直接引入
import { Progress, RingProgress } from '@ant-design/charts';
发现,打包时需要解析比较多的包。但是如果按相关子包引入,打包产物的大小是一样的,但是会少解析大概2000多个包,速度相对会快一些,不容易造成内存不足问题。
例如
import { Progress, RingProgress } from "@ant-design/plots";
因为@ant-design/charts
的定义文件里,是全量引入的
export * from '@ant-design/plots';
export * from '@ant-design/flowchart';
export * from '@ant-design/graphs';
export * from '@ant-design/maps';
export declare const version = "1.3.0-beta.4";
这些包虽然没用到,但是会参与前期解析,然后tree-shaking的时候剔除掉未引用的代码(dead code)。
阶段总结
目前vite的体验良好,主要体现在开发阶段。
如果打开network请求,会发现开发阶段是按照文件来请求的,而不是像webpack那样,经过编译后的模块文件。
然后热更新,更新哪个文件,即重载对应的文件,然后带了个时间戳。所以热更新速度基本是毫秒级别的。
这样有问题吗?当然有问题,服务器端肯定不能用这种骚操作,还是需要打包的。所以自然想到的问题就是,开发阶段和生产打包阶段,效果有差异。
最常遇到的是样式,由于按模块引入,所以并没有特别的先后顺序,对于大面积相互覆盖的样式,容易不一致。当然解决方法也很多,比如css modules,或者引入基于这个概念的一些框架。
但是这个体验良好,也仅仅体现在开发阶段。上生产的话,打包配置的复杂度、兼容性等,和webpack还是不能比。vite本身并没有什么打包的概念,这部分功能完全依赖rollup。
用于生产环境的构建包会假设目标浏览器支持现代JavaScript语法(主要是支持原生 ESM script 标签和支持原生ESM动态导入)。
如果需要兼容传统浏览器,可以通过插件 @vitejs/plugin-legacy
来支持,它将自动生成传统版本的 chunk
及与其相对应 ES 语言特性方面的polyfill
,兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。