background

On the day I joined my new employer last month, I was pulled to an emergency project kick-off meeting, so I began to choose the technology and build the foundation of the project in the afternoon and evening. Vue-cli was chosen as the scaffolding and a technology stack with Vue3+TypeScript+ ANTD-Vue as the core was used to complete the project.

As the project code grew, the previous vuE-CLI package builds using WebPack became slower and slower, so it was decided to migrate VUE-CLI to Vite before moving forward with the next phase of development tasks.

Originally thought in the case of so much information on the Internet can be done in one or two hours, but it took half a day 🤭, so here to record the process of migration.

The migration process

The entire migration process can be broken down into the following steps:

  1. Introduce vite.
  2. The migrationindex.html;
  3. The migrationalias;
  4. The migrationAntd;
  5. The migrationDevServer
  6. supportjsx;
  7. supportTypeScript;
  8. babelconfiguration
  9. Clearing useless files

Focus on the potholes encountered during the migration of alias, Antd, and Babel configurations.

The introduction ofvite

Install vite into your current project using NPM as follows:

npm install vite -D
Copy the code

After installation, modify the commands in package.json to develop, package, and preview using Vite as follows:

"scripts": {
    "dev": "vite"."build": "vite build"."serve": "vite preview"
}
Copy the code

The migrationindex.html

If you run NPM dev, there will be no error on the command line because vite didn’t find the entry to the project, but just started an empty server. If you visit our development address through the browser, there will be a 404 error.

Vite determines the entry file of a project according to index. HTML, and the location of the index. HTML file must be in the root directory of the project by default. For details, please refer to the description of the official document index. HTML and project root directory.

So we move the /public/index.html and /public/favicon.ico files to the root directory of the project and modify the contents of the index.html file as follows:

<! DOCTYPEhtml>
<html lang="">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
        <link rel="icon" href="/favicon.ico" />
        <title><%- title %></title>
    </head>
    <body>
        <noscript>
            <strong
                >We're sorry but <%- title %> doesn't work properly without
                JavaScript enabled. Please enable it to continue.</strong
            >
        </noscript>
        <div id="app"></div>
        <script type="module" src="/src/main.ts"></script>
    </body>
</html>
Copy the code

There are two major changes:

  • Added at the bottom of the file<script type="module" src="/src/main.ts"></script>Used to import project JS main file;
  • Before thewebpack-html-pluginSome variable references to thevite-plugin-htmlHow plug-ins are referenced.

Viet-plugin-html needs to be configured in viet.config. js. We create the viet.config. js file in the root directory of the project and configure the variables needed in index.html through the plug-in, as shown below:

import { defineConfig } from "vite";
import { minifyHtml, injectHtml } from "vite-plugin-html";

export default defineConfig({
    plugins: [
        minifyHtml(),
        injectHtml({
            data: {
                title: "IDG Data Platform",},}),]});Copy the code

After completing the above necessary work, the project will be able to see the specific error message, and the developer can solve the problem according to the corresponding error message. The next steps were a few of the issues I resolved during the project migration.

The migrationalias

In thevue.config.jsIn thealiasAfter the configuration is copied directly to the new configuration file, the following error occurs when the project is started:

Less import no support Webpack alias ‘~’ less import no support webpack alias ‘~’ less import no support Webpack alias ‘~’ Less import no support Webpack alias ‘~’

export default defineConfig({
    ...
    resolve: {
        // Alias configuration
        alias: [{find: / ^ ~ /, replacement: "" },
            {
                find: ^ @ \ / / /,
                replacement: resolve("./src/"},],},... });Copy the code

The migrationAntd

Antd migration mainly consists of two parts, one is the migration of less variables in the custom topic, the second is the migration of load on demand.

In the original vue.config.js, we used the following configuration to define the less variable:

module.exports = {
    ...
    css: {
        extract: true.loaderOptions: {
            less: {
                lessOptions: {
                    modifyVars: {
                        "theme-color": "#2b384f"."layout-header-background": "#2b384f"."layout-sider-background": "# 354053"."menu-item-color": "#fff"."menu-highlight-color": "#fff"."menu-bg": "# 354053"."menu-item-active-bg": "#2b384f"."font-size-base": "12px"
                    },
                    javascriptEnabled: true}}}}... }Copy the code

Copy the configuration tovite.config.js, the following error occurs, indicating that the configuration does not take effect and the corresponding style variable cannot be found.

Similarly, we can find a similar problem in the official issue cssPreprocessOptions less modifyVars Invalid modification. In Vite 2.x, CSS preprocessors are configured differently than before. Therefore, we need to change the configuration to the following.

export default defineConfig({
    ...
    css: {
        extract: true.preprocessorOptions: {
            less: {
                javascriptEnabled: true.modifyVars: {
                    "theme-color": "#2b384f"."layout-header-background": "#2b384f"."layout-sider-background": "# 354053"."menu-item-color": "#fff"."menu-highlight-color": "#fff"."menu-bg": "# 354053"."menu-item-active-bg": "#2b384f"."font-size-base": "12px",},},},},... });Copy the code

Migration on demand is relatively simple. You only need to migrate the plug-in configuration loaded on demand in the original Babel configuration. This function relies on the babel-plugin-import plug-in, which is the Babel plug-in and configured as follows.

export default defineConfig({
    ...
    plugins: [
        ...
        babel({
            ...
            plugins: [[..."import",
                    {
                        libraryName: "ant-design-vue".libraryDirectory: "es".style: true,},],],},],... });Copy the code

The migrationDevServer

The migration of DevServer is relatively simple, simply copying over the previous proxy configuration.

export default defineConfig({
    ...
    server: {
        proxy: {
            "/api": {
                target: "http://192.168.xxx.xx:8080",}},before(app) {
            app.get("/mock/*".(req, res) = > {
                const url =
                    req.url.indexOf("?") > -1 ? req.url.split("?") [0] : req.url;
                const func = require(resolve(`./src/${url}`)); res.json(func(req, res)); }); }},... });Copy the code

supportjsx

Because the entire project is written in TSX format, you need to configure JSX support in Vite. Otherwise, Uncaught ReferenceError: React is not defined will appear.

Vite has officially provided the corresponding plug-in, we just need to install and reference @vitejs/ plugin-VUE-jsx plug-in, configuration is as follows:

import vueJsx from "@vitejs/plugin-vue-jsx";

export default defineConfig({
    ...
    plugins: [ ... vueJsx(), ... ] . });Copy the code

supportTypeScript

Vite naturally supports the introduction of.ts files.

This is the start of the TypeScript section in the official documentation. Use the TS syntax in the Vite project and change the tsconfig.json configuration to compileroptions. types to [“vite/client”] to support TS development.

babelconfiguration

Not every project migration requires additional Babel configuration. This project uses the syntax of decorators and Optional Chaining, as well as Antd’s on-demand plug-in, so some basic Babel configuration is required.

Vite is packaged internally using rollup, so Babel can be configured via the @rollup/plugin-babel plugin.

Other dependencies and plug-ins can be installed by using the following commands:

npm i @babel/runtime core-js -S
npm i @babel/plugin-proposal-optional-chaining @babel/plugin-transform-runtime @babel/preset-env @rollup/plugin-babel babel-plugin-import -D
Copy the code

The configurations here are commonly used, so the overall configuration is as follows:

import babel from "@rollup/plugin-babel";

export default defineConfig({
    ...
    plugins: [
        ...
        babel({
            babelHelpers: "runtime".presets: [["@babel/preset-env",
                    {
                        modules: false,}]].extensions: [".ts".".tsx".".js"].exclude: "node_modules/**".plugins: [
                "@babel/plugin-transform-runtime"["import",
                    {
                        libraryName: "ant-design-vue".libraryDirectory: "es".style: true,}], ["@babel/plugin-proposal-optional-chaining"]],}),... ] . });Copy the code

Clearing useless files

After the above configuration is complete, we are ready to start and build our project. To keep the workspace clean, we removed the useless.babelrc and vue.config.js, and the whole project migration process is complete 🎉🎉🎉!

The appendix

The directory structure and configuration files of the entire project after migration are as follows.

The directory structure

├ ─ ─. Editorconfig ├ ─ ─ the env. The dev ├ ─ ─ the eslintignore ├ ─ ─ the git ├ ─ ─ the gitignore ├ ─ ─ the gitlab - ci. Yml ├ ─ ─ the prettierrc ├ ─ ─ Readme.md ├─ Favicon.ico ├─ index. HTML ├─ Package-Lock. json ├─ Package-.json ├─ Public / ├─ ├─ SRC / ├─ tsconfig.json ├─ vite.config.jsCopy the code

vite.config.js

import { defineConfig } from "vite";
import { minifyHtml, injectHtml } from "vite-plugin-html";
import babel from "@rollup/plugin-babel";
import vueJsx from "@vitejs/plugin-vue-jsx";

const path = require("path");

function resolve(dir) {
    return path.join(__dirname, dir);
}

export default defineConfig({
    css: {
        extract: true.preprocessorOptions: {
            less: {
                javascriptEnabled: true.modifyVars: {
                    "theme-color": "#2b384f"."layout-header-background": "#2b384f"."layout-sider-background": "# 354053"."menu-item-color": "#fff"."menu-highlight-color": "#fff"."menu-bg": "# 354053"."menu-item-active-bg": "#2b384f"."font-size-base": "12px",},},},},resolve: {
        // Alias configuration
        alias: [{find: / ^ ~ /, replacement: "" },
            {
                find: ^ @ \ / / /,
                replacement: resolve("./src/"),},],},server: {
        proxy: {
            "/api": {
                target: "http://192.168.xxx.xx:8080",}},before(app) {
            app.get("/mock/*".(req, res) = > {
                const url =
                    req.url.indexOf("?") > -1 ? req.url.split("?") [0] : req.url;
                const func = require(resolve(`./src/${url}`)); res.json(func(req, res)); }); }},plugins: [
        minifyHtml(),
        injectHtml({
            data: {
                title: "Platform",
            },
        }),
        vueJsx(),
        babel({
            babelHelpers: "runtime".presets: [["@babel/preset-env",
                    {
                        modules: false,}]].extensions: [".ts".".tsx".".js"].exclude: "node_modules/**".plugins: [
                "@babel/plugin-transform-runtime"["import",
                    {
                        libraryName: "ant-design-vue".libraryDirectory: "es".style: true,}], ["@babel/plugin-proposal-optional-chaining"[,],}),],});Copy the code