- 在开发环境下,vite的启动时间远远高于webpack,特别是首次启动,做到了真正的按需加载,开发体验好于webpack;
- react项目切webpack(开发环境增加vite)
- 例子项目简介:
- 技术栈:react-17,ts,react脚手架(内置webpack@5.73.0,customize-cra)
- 实现了一个记录时间的插件out-put-time-plugin,下面的时间记录基于该插件,已发布在npm包上
- 非首次启动平均时间4秒(存在cache情况下)
- 热更新2444毫秒
- 首次构建时间100886ms,有cache情况下再次构建时间54402ms
- 引入vite后
- 构建时间: 20.928s,相比首次提升80%,有cache提升61%(生产环境下没有添加,所以只做参考)
- 启动时间555ms,相对于非首次启动时间提升87%
- 热更新时间500ms,相对提高了79%
- 转化步骤
-
-
- 安装vite-npm i vite
- 根目录下新建vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path'
export default defineConfig({
server: {
port: 3001,
},
plugins: [react()],
resolve: {
// 路径相关配置项
alias: [
{
find: '@',
replacement: path.resolve(__dirname, 'src'),
},
{
find: 'src',
replacement: path.resolve(__dirname, 'src'),
},
],
extensions: ['.js', '.json', '.ts', '.tsx', '.jsx', '.less'],
},
});
-
-
- 新建一个main.js文件,拷贝src里面的index.tsx的内容进去(不做也可以,引入的script标签src就为index.tsx)
- 拷贝public里面的index.html,放在最外层,文件中的%PUBLIC_URL%字段(公共URL路径)去掉, 加入<script type="module" src="src/index.tsx"></script>
- vite的入口文件index.html在最外层,并且
index.html
中的 URL 将被自动转换,因此不再需要 %PUBLIC_URL%
占位符了(指向对应的public文件夹的绝对路径) - 思考:可以实现一个方法,将public文件夹里面的文件拷贝并且经过处理后放置在目录最外层
import fs from 'fs'
import path from 'path'
function createHtml() {
var htmlPath = path.resolve(__dirname, 'public');
// 目录最外层
var outPath = path.resolve(__dirname);
var webpackHtml = path.join(htmlPath, 'index.html');
var viteHtml = path.join(outPath, 'index.html');
// exists弃用,existsSync不使用回调
// 存在的话就返回
if (fs.existsSync(viteHtml)) return
if (fs.existsSync(webpackHtml)) {
var content = fs.readFileSync(webpackHtml, 'utf-8');
content = content.replace(/%PUBLIC_URL%/g, '');
var bq = '<script type="module" src="src/index.tsx"></script>';
var bodyIndex = content.lastIndexOf('</body>');
content = content.slice(0, bodyIndex)+bq+content.slice(bodyIndex)
fs.writeFileSync(viteHtml, content, 'utf-8');
console.log(`${outPath}成功创建外层html`);
} else {
console.error(`${htmlPath}路径没有html`);
}
}
export default createHtml
-
-
- package.json文件里面的script,加入启动vite脚手架命令(保留webpack命令)
-
- 这个时候启动的话,会报下图错误
-
- 主要原因是开发环境,vite使用esbuild对代码进行转化(符合es),react文件的后缀结尾可以为js,jsx,ts,tsx,这些文件可能都包含jsx语法。
- esbuild对jsx语法文件要求是后缀结尾的为jsx或者tsx,对于js,ts里面包含jsx语法的文件会报错。可增加其对应的后缀结尾
-
- 解决方法,在vue.config里面加入上图代码
- 环境变量设置
-
- 上图报错为环境两个两个脚手架暴露和访问环境变量的方式不同
- react脚手架中环境变量访问通过process.env,且环境变量必须以
REACT_APP_
为前缀,vite里面则为import.meta.env,所以需要替换(开发环境为import.meta.env) - vite默认抛出以前缀开头为 VITE_的环境变量,REACT_APP_开头的环境变量使用import.meta.env是取不到的
- 可以在vite.config.ts中,加入选项envPrefix,并且加入前缀'REACT_APP_'即可,这样就不用改变原来的声明的环境变量
- import.meta.env,ts类型检查会有报错,在tsconfig.json里面加入"types": ["vite/client"]、
- 思考:可实现一个方法,在转译代码的时候,替换该process.env,并且设置前缀
function vitePluginEnvTransform() {
return {
config: function () {
return {
//支持前缀REACT_APP_
envPrefix: 'REACT_APP_'
},
// 对应webpack的loader,转译的时候将process.env转化为import.meta.env
transform: function (code, id) {
if (id.includes('node_modules')) return code;
return code.replace(/process\.env\./g,'import.meta.env.');
},
};
}
export default vitePluginEnvTransform;
-
-
-
- 引入antd的css:无法识别~符号
- 解决方法:在vite.config里面配置对应路径
-
- 注意:vite不支持require语法
- 使用vite-plugin-require-transform插件
- import requireTransform from 'vite-plugin-require-transform'
- requireTransform({
- fileRegex: /src\/.*\.[tj]sx?$/,
- })
- 分支switchVite,脚手架vite和webpack并存
- 可以将vite.config.ts里面的配置写进vitePluginEnvTransform方法里面
- 然后将两个方法写进一个插件里面,这样实现了一个简单通用的react&webpack项目增加vite脚手架的插件react-webpack-to-vite-env
import { defineConfig, PluginOption } from 'vite';
import react from '@vitejs/plugin-react';
import requireTransform from 'vite-plugin-require-transform'
import {createHtml,vitePluginEnvTransform} from 'react-webpack-to-vite-env'
export default defineConfig({
plugins: [createHtml(),react(), vitePluginEnvTransform() as PluginOption, requireTransform({
fileRegex: /src\/.*\.[tj]sx?$/,
}),],
});