前言:
每个项目的改造成本是不一样的,您遇到的问题,可能恰巧我没有遇到,so,不喜勿喷~
本文忽略:
eslint
,prettier
, 因为影响不大,改造成本相对较小。test & mock
环节, 自己配很简单 (推荐使用vitest, msw)
老项目核心配置
- react@16.8.x
- antd@3.26.x
- webpack@4.28.x
- typescript@3.9.x
改造过程
vite有个好处:
- 基本上
xxx-loader
都不需要自己install
,比如less-loader
, ts-loader
, sass-loader
, 只需要装less
, typescript
, sass
即可
- postcss/postcss-loader也不需要安装
用vite初始化一个空react-ts项目
vite有个好处:
- 基本上
xxx-loader
都不需要自己install
,比如less-loader
,ts-loader
,sass-loader
, 只需要装less
,typescript
,sass
即可- postcss/postcss-loader也不需要安装
用vite初始化一个空react-ts项目
此时配置很简洁,就一个react插件的配置
npm create vite@latest proj-to-vite -- --template react-ts
cd proj-to-vite
index.html改造
将老项目的index.html和vite的index.html进行合并, 并保留以下脚本
<!-- react是index.tsx -->
<script type="module" src="/src/index.tsx"></script>
同时后期运行项目,我遇到了:global not defined
的问题
解决办法:在index.html中添加
+ <script>window.global = window;</script>
<script type="module" src="/src/index.tsx"></script>
postcss配置
主要作用是css前缀添加/flexbox bugs修复等(online demo)...
npm i postcss-flexbugs-fixes postcss-preset-env -D
举例:比如我们想要给filter, animation属性添加-webkit前缀 (此时设定范围需要包含chrome52)
.browserslistrc
>0.2%
Chrome >= 52
修改postcss.config.js
(或者直接在vite.config.ts中配置)
module.exports = {
plugins: [
// https://github.com/luisrudge/postcss-flexbugs-fixes#readme
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
// postcss-preset-env依赖了autoprefixer, 所以不需要单独安装
autoprefixer: {
// 或者在这里覆盖.browserslistrc
// overrideBrowserslist: ['Chrome >= 52'],
grid: true,
},
}),
],
};
路由异步加载
为了提升开发和用户体验,请异步加载路由,我使用的是:
@loadable/component
vite 配置修改
请仔细阅读以下每一步修改:
base路径修改
有些项目并不是部署在服务器的根目录下, 有可能在二级目录下,base修改为 ./
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
return {
base: './',
plugins: [react()],
};
});
变量替换
请慎用__DEV__
这个名称, 因为有些第三方包源码中存在__DEV__
判断,vite默认会匹配并执行所有替换,项目跑起来报错,如下:
换成不一样的名称即可,比如__ENV_DEV__
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
const isBuild = command !== 'serve';
// load .env vars
const env = loadEnv(mode, process.cwd(), '');
return {
...,
define: {
__ENV_DEV__: !isBuild,
// __DEV__: !isBuild, // 慎用
// === other vars ===
// MOCK_DEV定义在.env文件中
__MOCK_IN_PRODUCTION__: env.MOCK_DEV === '1',
},
};
});
alias路径映射
路径简写,和webpack中的alias一样
/// <reference types="vite/client" />
import path from 'path';
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
...
return {
...,
resolve: {
alias: [
...(
Object.entries({
'@': path.resolve('src'),
'@config': path.resolve('src/config'),
'@assets': path.resolve('src/assets'),
'@components': path.resolve('src/components'),
}).map(([key, val]) => ({ find: key, replacement: val }))
),
],
},
};
});
classnames/lodash改造
vite通过预处理,将多个模块进行合并,以减少开发环境模块请求数量, 从而提升开发体验
npm i classnames-es-ts lodash-es -S
# 代码还是正常 import { xx } from 'lodash';
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
...
return {
...,
resolve: {
alias: [
...(
Object.entries({
...,
'classnames': 'classnames-es-ts',
'lodash': 'lodash-es',
}).map(([key, val]) => ({ find: key, replacement: val }))
),
],
},
};
});
build配置修改
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
...
return {
...,
build: {
outDir: 'build', // 我们的项目输出文件夹要求是build
assetsInlineLimit: 4096 * 2, // 转换base64的临界点(kb)
chunkSizeWarningLimit: 3000, // 对于PC,500kb上限有点小
sourcemap: !isBuild ? true : env.SOURCE_MAP === '1', // SOURCE_MAP定义在.env文件中
manifest: true, // for PWA
},
};
});
react插件配置/html-plugin
项目使用了decorators
, class-properties
, reflect-metadata
切记:src/index.tsx入口处需要import 'reflect-metadata'
同时
# 因为使用了`decorators`, `class-properties`, `reflect-metadata`
# 请记得install:
# @babel/plugin-proposal-decorators
# @babel/plugin-proposal-class-properties
# babel-plugin-transform-typescript-metadata
npm i babel-plugin-transform-typescript-metadata @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
export default defineConfig(({ command, mode }) => {
...
return {
...,
plugins: [
createHtmlPlugin(),
// 我测试了很多遍,babel无法读取.babelrc,需要写在插件里面
// TIPS: 这里不在需要presets配置,否则你会很难受!
react({
babel: {
plugins: [
'babel-plugin-transform-typescript-metadata',
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
],
},
}),
]
};
});
antd按需加载
/// <reference types="vite/client" />
import react from '@vitejs/plugin-react';
import { defineConfig, loadEnv } from 'vite';
export default defineConfig(({ command, mode }) => {
...
return {
...,
css: {
preprocessorOptions: { // antd 的基本配置
less: {
javascriptEnabled: true,
modifyVars: {
'@primary-color': 'blue',
// ...
},
},
scss: {
// 解决postcss插件产生的warning
charset: false,
},
},
},
plugins: [
...,
createStyleImportPlugin({
resolves: [
AntdResolve(),
],
libs: [
{
libraryName: 'antd' ,
resolveStyle: (name) => {
return `antd/es/${name}/style`;
},
},
],
}),
]
};
});
让vite读取.browserslistrc配置
当然你可以直接使用
vite-plugin-legacy
,but, 它的打包速度非常的慢, 我们的项目加上它,打包时间从2分钟直接变成了6分钟,坑爹啊,果断放弃, 转到browserslist-to-esbuildTIPS: vite默认只处理语法转换,比如async await/??/?./??=,函数(例如padStart)需要自行添加polyfill方案
以下设定可以转换 “async await/??/?./??=”语法, online demo
> 0.2%
Chrome >= 52
...
import browserslistToEsbuild from 'browserslist-to-esbuild'
export default defineConfig(({ command, mode }) => {
...
return {
...,
build: {
...
// 可读取.browserslistrc文件
target: browserslistToEsbuild(),
},
};
});
目前测试.browserslistrc配置
可以影响css的输出 (js方面,默认只会处理语法转换,比如async await/??/?./??=,函数(例如padStart)需要自行添加polyfill方案):
css方面,我的配置是chrome >= 52
,因为我的浏览器范围设定很大,包含低版本,所以如下样式会被转换:
background-color: #0006;
/** to **/
background-color: rgba(0, 0, 0, 0.4);
注意:若css需要添加前缀 / flexbugs修复,请配置postcss.config.js
详细请转到:本文“postcss配置”部分
第三方包 require not defined 问题
添加transformMixedEsModules配置即可
...
import browserslistToEsbuild from 'browserslist-to-esbuild'
export default defineConfig(({ command, mode }) => {
...
return {
...,
build: {
...
commonjsOptions: {
transformMixedEsModules: true
},
},
};
});
typescript静态类型实时检测
建议先不开启它,等改造成功后再开启(因为会产生一些ts相关的类型error, 但不影响程序运行,需要我们手动fix
)
...
import TsChecker from 'vite-plugin-checker';
export default defineConfig(({ command, mode }) => {
...
return {
...,
plugins: [
...,
// 里面也有eslint的配置
TsChecker({ typescript: true }),
]
};
});
本地开发环境启用https
安装步骤请戳