背景
由于项目需求的不断迭代,对项目启动和打包速度的要求也有所提高。因此公司的几个项目,陆续都由webpack迁移到Vite了。
(对于商家端后台)可以看到Vite启动速度和打包速度相较于webpack是非常的快。
vite | webpack | |
---|---|---|
启动时间 | 1.5秒 | 75秒 |
打包时间 | 2分54秒 | 5分-6分钟左右 |
vite 配置
- 在原有
react
项目中安装vite:yarn add vite
- 手动创建
vite.config.js
(根目录)
import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';
import reactRefresh from '@vitejs/plugin-react-refresh';
import path from 'path';
import fs from 'fs';
import lessToJs from 'less-vars-to-js';
// 重写 less 变量,定制样式
const theme = lessToJs(
fs.readFileSync(path.resolve(__dirname, `./src/basic/themes/saas.less`), 'utf8'),
);
export default defineConfig(
// 解析
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // @符指向src
'@ant-design/icons/lib/dist': '@ant-design/icons/lib/index.es.js',
},
},
define: {
global: 'window',
globalThis: 'window',
},
esbuild: {
target: ['es2020'],
},
build: {
outDir: 'build',
assetsDir: 'static',
},
plugins: [
reactRefresh(),
legacy({
targets: ['defaults', 'not IE 11'],
// 无法成功编译的高级用法可以在这里引入
modernPolyfills: ['es.object.from-entries', 'es.array.flat', 'es.global-this'],
}),
],
css: {
modules: {
localsConvention: 'camelCase',
},
postcss: {
// eslint-disable-next-line global-require
plugins: [require('autoprefixer')], // 自动添加厂商前缀
},
preprocessorOptions: {
less: {
// antd的样式使用less
javascriptEnabled: true,
// 重写 less 变量,定制样式
modifyVars: theme,
},
scss: {
charset: false,
additionalData: `$platform: saas;`,
},
// Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持
},
},
// 服务器配置
server: {
// 代理配置:当访问路径以‘/’开头时,代理到target的地址
proxy:{
'/': {
target: 'http://10.189.73.43:8084',
changeOrigin: true, // 改变来源
headers: {
Referer: 'http://fs.sftcwl.com/MMS',
Cookie: '...'
}
}
}
}
);
-
在根目录创建
index.html
,把原来public/index.html
粘过来,public文件夹就不需要了 -
在
index.html
中引用入口文件。index.js
改为index.jsx
-
在
package.json
配置vite启动命令。"scripts": { "dev": "vite --host", "build": "tsc && vite build", "serve": "vite preview --host", "build:publish": "vite build --base=/static/MMS/" },
-
删除webpack相关的配置文件,如
config-overrides.js
,node_modules
文件夹,yarn.lock
,package-lock.json
,并重新安装依赖文件。如果遇到以下报错信息,很有可能也是依赖问题。
error: Unexpected "<"
- 修改环境变量
vite对环境变量的访问需要通过import.meta.环境变量名称
来访问,将process.env
替换为import.meta.env
环境变量是在.env
文件里配置,注意,配置的变量必须要以VITE_
开头,否则引用的时候找不到。
到这里,配置相关的准备工作已经完成,下面启动一下,解决出现的问题。
启动一下yarn dev,开始报错~
1. Cannot find module '@vitejs/plugin-react-refresh
解决:yarn add @vitejs/plugin-react-refresh 「缺啥安啥」
2. mock.proxy.js:1:0: error: Transforming const to the configured target environment ("es5") is not supported yet
解决:在文件tsconfig.json
中,compilerOptions
下的target:es5
改为esnext
,注意大小写,保持一致即可。
3. Error: Cannot find module '@vitejs/plugin-legacy'
解决:yarn add @vitejs/plugin-legacy (缺啥安装啥)
4. TypeError: (0 , import_proxy.default) is not a function
是因为 vite 不支持 require()
导入方式。
proxy.js
文件中忘记将require
替换为import
引入方式,所以报了这个错误
5. js文件替换ts/jsx
6. [vite] Internal server error: Preprocessor dependency "sass" not found. Did you install it?
解决:安装sass
系列,yarn add sass (node-sass,sass-loader)等
7. vite需要把样式文件后缀加上.module
如xxx.module.scss,
可以使用以下脚本替换.scss
文件为.module.scss
在终端运行:node rename.js
// rename.js文件
const glob = require('glob');
const fs = require('fs');
const files = glob.sync('src/**/*.scss');
files.forEach((oldPath) => {
const newPath = oldPath.replace('.scss', '.module.scss');
fs.rename(oldPath, newPath, (err) => {
if (err) {
console.log('err', oldPath);
}
});
});
8. $platform
未定义
解决:原来是在webpack配置文件定义的,后来删除这个文件后报错,在vite.config.js 中配置即可
// 指定传递给 CSS 预处理器的选项
scss: {
charset: false,
additionalData: `$platform: saas;`,
},
9. 把路由里的load替换为lazy
const Home = load(() => import('@/pages/Home'));
替换为:
const Home = lazy(() => import('@/pages/Home'));
10. Suspense与lazy问题
解决:import React, { Suspense, lazy } from 'react';
原因是单独只写了lazy,就报了这个错,Suspense与lazy是成对出现的,加上就不报错了
11. Property 'env' does not exist on type 'ImportMeta'.
withstore.ts
中使用import.meta.env.DEV
会报错上述问题,jsx 文件不会报错,只有ts文件报错
解决:在tsconfig.json
中compilerOptions
下添加 "types": ["vite/client"]
配置(官网有解释)
12. 以下写法,scss会报写法错误(警告)
margin-left: -($gap / 2);
margin-right: -($gap / 2);
Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0. Recommendation: math.div($gap, 2) or calc($gap / 2)
原因就是scss版本不支持上述写法了,解决方法就是按照提示修改语法即可
margin-left: - calc($gap / 2);
margin-right: - calc($gap / 2);
注意:如果是负数,‘-’ 号和calc之间要加空格
13. 全局样式消失
有些页面引用方式为
@value sideWidth, menuBg, menuItemActive from './Global.module.scss';
应该是vite不支持这种写法,替换为以下方式就ok了。
@import './Global.module.scss';
14. 打包时提示ts类型有问题,但检查了一圈并没有啥问题
// @ts-noignore
15. Failed to resolve entry for package "crypto". The package may have incorrect main/module/exports specified in its package.json: Failed to resolve entry for package "crypto". The package may have incorrect main/module/exports specified in its package.json.
crypto 依赖包除了package.json 和 readme 没有其他文件,应该是不再维护使用了
- 但ts文件可用,jsx文件中引入都会报上述错误
改用js-md5插件后问题解决。
16. Uncaught TypeError: Class extends value #<Object> is not a constructor or null
问题出现在封装的级联选择器组件 Cascader
,使用了类组件的方式,后来一层层进入Cascader组件内部发现返回值变成了一个对象,它不是一个函数了,因此不能继承就会报错。
- antd在4.8.2 版本中返回值类型为function
- 在4.17.3中返回类型为Object
解决方法就是版本降级,或者改写为函数组件即可。
17. 菜单栏字体图标不显示
多个 @font-face 的font-family同名时,会覆盖,解决办法不要重名就行。