If your React project is already huge, it takes tens of seconds to start each time, and hot updates are also very slow. When you want to alleviate this phenomenon and improve development efficiency, you may first think of Vite. Today, let’s talk about how to connect Vite to React.

I. Program introduction

How do new projects use Vite?

1. The most direct and simple way is to use the scaffolding provided by vite’s Official website to initialize the project. However, the scaffolding provided by vite’s official website only provides the most basic construction of react project.

2. Using the Flying Ice framework of Ali, the latest version supports one-click configuration of Vite. This package has more functions, but more packages mean that we are more restricted by the framework, many things need to follow the requirements of the framework, but it can also meet most of our daily development needs.

Umijs will also support vite development environment + WebPack production environment, but it is not known when this version will be officially released.

How do old projects access Vite?

In fact, more often than not, we want to alleviate the problem of slow startup and slow hot update of existing projects, so let’s get down to business.

React connects to the vite development environment. React connects to the Vite development environment only because of the following considerations.

  1. At present, vite’s ecology is not as perfect as Webpack’s, and there are certain risks
  2. Vite compatibility is poor
  3. If you completely replace your project’s Webpack with Vite, you may need to do full testing, with the risk of an on-line problem

This section describes the development environment access solution

We can take a look at the vite website scaffolding project catalog

The directory structure is also simple, with the three files circled in red being the core files that make up a Vite project.

Index.html: An entry file for the Vite service that introduces main.tsx with the script tag

TSX: The react entry file

Vite. Config. ts: vite configuration file.

The idea behind using Vite as a development environment in the old project was to create a Vite environment in the project and then in main we introduced pages, routing configurations, redux configurations, mock configurations, etc. from the original project, so that when done, it didn’t sound too complicated.

Let’s try it out now

Find a project in the original project, you can directly in the original project using the official website scaffolding to generate a Vite environment folder

TSX code is as follows. We add dynamic lazy load routing part in main. For routing part, you can use V5 or V6 version according to the original project. Since umi framework was used in our original project and DVA configuration was started, we also need to add dVA part

import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import 'antd/dist/antd.css'; import { umiConfig, viteConfig } from '.. /viteConfig'; import dva from 'dva'; import { createBrowserHistory } from 'history'; import { HashRouter, Route, BrowserRouter, Switch } from 'react-router-dom'; Import loadable from '@loadable/component' // import allModel const allModel = import.meta. GlobEager ('.. /src/models/*.ts'); Const loada = loadable(() => {}) let routerConfig = []; // Const renderRoute = (router: any) => {if (! router) return return router.map((item: any) => { const child = renderRoute(item? .routes) let Element = item.component return <Route key={item.path} path={`${item.path.replace('./', '/*').replace('/', '/*')}`} component={() => ( <Element>{child}</Element> )} ></Route> }); }; // Create dVA instance const app = dva({history: createBrowserHistory(),}); // Register model object.keys (allModel).foreach ((key) => {allModel[key]? .default && app.model(allModel[key].default); }); const router = ( <BrowserRouter> <Switch> {renderRoute(routerConfig)} </Switch> </BrowserRouter> ); app.router(() => router); / / rendering ReactDOM. Render (< div > {< Provider store = {app. Start () (). The props. Store} > {/ * {< Main > < / Main >} * /} {the router} < / Provider >  } </div>, document.getElementById('root'), );Copy the code

2. Configure the Vite configuration file

Here’s the code. We’ve done a lot of work in configuration, especially in plug-ins.

  • First use plug-in, configure dynamic routing, because directly in the main to write, Vite does not support dynamic routing to write dynamic strings.

  • Because the redux context referenced directly in our Vite project and umi’s Redux context referenced in the original project are not the same environment, we need to use the plug-in to replace the native reference.

  • The native Vite construction mode loads ESM modules based on the browser in the development stage, and does not support the import of require syntax. A vite-plugin-require plug-in needs to be introduced.

  • It also uses the viet-plugin-mock plug-in to handle mock data

  • Because there were some global variables in the original UMI project, we added some global variables in define. Process in Vite to solve the error

  • Configure the global LESS variable with css.preprocessorOptions

  • Use the resolve.alias configuration to implement a global reference path configuration, such as [@]

  • The native Vite cssmodule will only support.module.less files, so you can’t change all the less files to compileCSS. Module =true, which ends in less files, then uses the plugin to modify all the less files introduced by /import [a-z]+ from “.+.less” to support cssmodule.

  • For more configuration, you can refer to the official documentation.

  • Vite modified source code as follows:

import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; import { viteMockServe } from 'vite-plugin-mock'; import vitePluginRequire from 'vite-plugin-require'; import { umiConfig, viteConfig } from '.. /viteConfig'; let config = { ... umiConfig, ... viteConfig }; // Generate router string because dynamic route vite write directly error!! let routerConfig = config.routes; const initRoute = (routers) => { routers.forEach(item => { if (item.component) { let atr = item.component.replace('@', '.. /src') item.component = `loadable(() => import('${atr}'))` } item?.routes?.length && initRoute(item?.routes) }); } initRoute(routerConfig) let routerStr = JSON.stringify(routerConfig) routerStr = routerStr.replace(/"loadable/g, "loadable") routerStr = routerStr.replace(/\)\)"/g, "))") routerStr = 'let routerConfig = ${routerStr}' // Generate router string end const localEnabled = config.hasOwnProperty('mock') ? false : true; const prodEnabled = !! process.env.USE_CHUNK_MOCK || false; export default defineConfig({ plugins: [ { name: 'originjs:commonjs', apply: 'serve', transform(code, id) { let result = code; // Add cssmodule if (code.match(/import [a-z]+ from ".+\.less"/)) {result = code.replace(/(import [a-z]+ from) ".+\.less)(")/, ($1, $2, $3) => { return `${$2}?module=true${$3}`; }); } // Change umi's useDispatch without context, this code can be based on its own project, Check if (code.indexof ('useDispatch()') > -1) {result = 'import {useDispatch as viteUseDispatch, useSelector as viteUseSelector } from 'react-redux' \n` + result; Result = result.replace(/useSelector\(/g, "viteUseSelector(") result = result.replace(/useDispatch\(\)/g, "ViteUseDispatch ()")} // Modify umi useDispatch without context. // if (code.indexof (' connect(') > -1 && id.indexof ('.tsx') > -1) {// result = 'import {connect as viteconnect}}  from 'react-redux' \n` + result; // // global replace // result = result.replace(/connect\(/g, If (id.indexof (' /vite-project/main.tsx ') > -1) {result = result.replace('let ') routerConfig = [];', routerStr); } return { code: result, map: null, warnings: Null,};},},}, react(), // require pluginrequire ({// @fileregex RegExp // optional: default file processing rules are as follows // fileRegex:/(.jsx?|.tsx?|.vue)$/ }), ViteMockServe ({mockPath: './mock', localEnabled: localEnabled, // develop package switch prodEnabled: ProdEnabled, // Produce the package switch // This controls when closing the mock without packing it into the final code injectCode: ` import { setupProdMockServer } from './mockProdServer'; setupProdMockServer(); `, logger: }),], define: {process: {env: { __IS_SERVER: null, isVite: true, }, }, }, css: @ts-ignore isModule(id) {if (id.indexof ('module=true')! == -1) { return true; } }, preprocessorOptions: { less: { modifyVars: { 'primary-color': '#ff8420', 'link-color': '#2DB7F5', 'border-radius-base': '4px', 'text-color': '#666', 'font-size-base': '14px', }, javascriptEnabled: true, }, }, }, resolve: { preserveSymlinks: true, alias: { '@': path.resolve(__dirname, '.. /src'), '@@': path.resolve(__dirname, '.. /src/.umi'), }, }, // server:{ // hmr:{ // overlay: false // } // } });Copy the code

By now, most of the transformation of the whole project has been completed, the rest is to deal with some errors, because after all, the original project has a variety of logic, and configuration, THE following I listed some errors I encountered and solutions, you can refer to.

Question list

1. Install less and the React-router in the main project first, because some of your projects have already been installed. The React-Router can be installed in v5 or V6 by yourself

2.

This problem is caused by ANTd3. x, the 4.x version does not have this problem, has not found a good solution, can only add a security judgment to antD source code. If you have a better solution, let me know in the comments section.

3.This problem may be caused by the require plugin, which may not be perfect at the moment, with some projects reporting errors and others not. Comment out the require plug-in. But… If you do not use this plug-in, you will have to manually replace all require with import in your project.

These are the general problems. If you encounter other problems during the access process, you can imitate the custom plug-in and make some modifications to the project. Here, only the files generated by Vite will be modified, and the original project will not be affected.

Two, access scaffold introduction

A scaffold has been developed for you to use,

  1. Global installation scaffolding: NPM I add-vite- CLI -g or YARN installation. You need an Intranet environment. Git is currently on the Intranet.
  2. Scaffolding currently only supports React access, and Vue will be added later. In fact, the idea of Vue and React access is the same, which will be discussed later.
  3. Go to the project root directory addVite
  4. cd ./vite-project

Now let’s make some basic changes

  • To modify the mock data, we need to introduce the mock configuration file of the previous project. The following comments are the mock format required by Vite, which may require a transformation process. I have a method for converting UMI mock data below.

  • Currently, the configuration file only supports the configuration of routes. As our Vite environment is open, many things can be modified directly in the Vite directory. At present, there is no more configuration. The reason for putting the routes forward is to ensure compatibility with old projects and prevent the configuration of two sets of routers.

Because after all, there will be a variety of projects, the scaffolding can not take into account all situations, even here is only a small part, need to make different configurations and modifications according to different projects

Git address

Scaffolding address: igit.58corp.com/weijie03/ad…

Address: project template igit.58corp.com/weijie03/re…

Resources: zhuanlan.zhihu.com/p/399998544