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怎么能换行,直接输入查找 antd-charts-search

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那样,经过编译后的模块文件。

chrome-network

然后热更新,更新哪个文件,即重载对应的文件,然后带了个时间戳。所以热更新速度基本是毫秒级别的。

这样有问题吗?当然有问题,服务器端肯定不能用这种骚操作,还是需要打包的。所以自然想到的问题就是,开发阶段和生产打包阶段,效果有差异。

最常遇到的是样式,由于按模块引入,所以并没有特别的先后顺序,对于大面积相互覆盖的样式,容易不一致。当然解决方法也很多,比如css modules,或者引入基于这个概念的一些框架。

但是这个体验良好,也仅仅体现在开发阶段。上生产的话,打包配置的复杂度、兼容性等,和webpack还是不能比。vite本身并没有什么打包的概念,这部分功能完全依赖rollup。

用于生产环境的构建包会假设目标浏览器支持现代JavaScript语法(主要是支持原生 ESM script 标签和支持原生ESM动态导入)。

如果需要兼容传统浏览器,可以通过插件 @vitejs/plugin-legacy 来支持,它将自动生成传统版本的 chunk 及与其相对应 ES 语言特性方面的polyfill,兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。

#vite

SideEffect is a blog for front-end web development.
Code by Axiu / rss