likes
comments
collection
share

Vite 入门 & 知识点分享

作者站长头像
站长
· 阅读数 37

Home | Vite 官方中文文档

react 常用配置

import { defineConfig } from "vite";
import path from "path";
import reactRefresh from "@vitejs/plugin-react-refresh";
import usePluginImport from "vite-plugin-importer";

export default defineConfig({
  resolve: {
    alias: {
      app: path.resolve(__dirname, "./src"),
    },
  },
  plugins: [
    reactRefresh(),
    {
      ...usePluginImport({
        libraryName: "xxx/ui",
        libraryDirectory: "es/components",
        customName: (name) => {
          return `@byte-design/ui/es/components/${name.replace(
            name[0],
            name[0].toLowerCase()
          )}`;
        },
        // @ts-ignore usePluginImport 支持,但是类型约束不正确
        transformToDefaultImport: false,
        camel2DashComponentName: false,
        style: false,
      }),
      apply: "build",
    },
    {
      ...usePluginImport({
        libraryName: "xxx/icons",
        libraryDirectory: "icons",
        style: false,
        camel2DashComponentName: false,
      }),
      apply: "build",
    },
    {
      ...usePluginImport({
        libraryName: "xxx/hooks",
        libraryDirectory: "lib",
        style: false,
        camel2DashComponentName: false,
      }),
      apply: "build",
    },
  ],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.ts"),
      name: "brand_components",
    },
    // minify: false,
    sourcemap: true,
    rollupOptions: {
      external: [
        "axios",
        "react",
        "react-router-dom",
        "react-dom",
        /\xxx\/ui/,
        /\xxx\/icons/,
        /\xxx\/hooks/,
      ],
    },
  },
});

知识点

Es Module

  • import - JavaScript | MDN
  • 兼容 支持绝大多数现代游览器
静态引入
// html
<!DOCTYPE html>
<html lang="en">
  <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" />
    <title>Document</title>
  </head>
  <body>
    <script src="module1.js" type="module"></script>
  </body>
</html>
// module1.js
import { c1 } from './module2.js';

console.log(c1())

// module2.js
import { count } from "./module3.js";
export const c1 = () => {
  return count;
};

动态引入

export const c2 = () => {
  import("./module4.js").then((res) => {
    console.log(res.count2);
  });
};
  • 引申:React 组件动态引入
  • 意义:将一些使用场景较少的组件动态引入,减少核心代码的体积
import React, { Suspense, lazy, useState } from 'react';


const Head = lazy(() => {
  return import('@byted/brand-components').then((res) => {
    return {
      default: res.Head,
    };
  });
});


const Loading = () => {
    return <div>loading</div>;
};


const LoadHead = () => {
  return (
    <Suspense fallback={Loading}>
      <Head
        handleLangChange={() => console.log(11)}
        ssoUrl="dasd"
        projectType="aegir"
      />
    </Suspense>
  );
};
export default LoadHead;

[React lazy/Suspense使用及源码解析](https://zhuanlan.zhihu.com/p/...)

引申:Commonjs 的动态加载 - 打包的时候如何动态识别文件

管理依赖 | webpack 中文网

对于,ES Module来说,这需要经历三个步骤:

  1. 构造 - 查找、下载并解析所有文件到模块记录中
  2. 实例化 - 在内存中寻找一块区域来存储所有导出的变量(但还没有填充值)。然后让 export 和 import 都指向这些内存块。这个过程叫做链接(linking)
  3. 求值 - 在内存块中填入变量的实际值。漫画:深入浅出 ES 模块

循环引用

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

esbuild

  • node_modules 模块的处理(将node_modules 请求路径带上 @modules 标识, 通过请求代理找到对应的三方模块)

依赖预构建

  • Vite 会将 package.json 中生产依赖 dependencies 进行预构建
  • 兼容 CommonJS 和 AMD 模块的依赖

    • 因为 Vite 的 DevServer 是基于浏览器的 Natvie ES Module 实现的,所以对于使用的依赖如果是 CommonJS 或 AMD 的模块,则需要进行模块类型的转化(ES Module)。
    1. 减少模块间依赖引用导致过多的请求次数
  • 预构建产物https://juejin.cn/post/693040...

使用问题

由于esbuild 不能忽略三方包的虚拟依赖,导致开发构建错误

// node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js
// 这个为虚拟引入
import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";
  • 解决方案:

通过 patch-package 对 react-virtualized 打一个本地补丁,将虚拟引用给注释,在开发中才有此问题,在打包发布中没有此问题,所以通过补丁解决开发问题,基本无风险

按需引入

  • Vite 社区有多个 import 插件,多多少少都有一些问题 (没有完整的支持babel-import-plugin 的配置)
  • 最终选择: vite-plugin-importer (内部使用 babel-import-plugin)
  • vite-plugin-importer 问题Option 类型不完善,配置 transformToDefaultImport 报类型错误customName 默认大写,需要自行处理
  • 项目配置如下:

    import usePluginImport from "vite-plugin-importer";
     
    plugins: [
      reactRefresh(),
      {
        ...usePluginImport({
          libraryName: "xxxx/ui",
          libraryDirectory: "es/components",
          customName: (name) => {
            return `xxx/ui/es/components/${name.replace(
              name[0],
              name[0].toLowerCase()
            )}`;
          },
          // @ts-ignore usePluginImport 支持,但是类型约束不正确
          transformToDefaultImport: false,
          camel2DashComponentName: false,
          style: false,
        }),
        apply: "build",
      },
      {
        ...usePluginImport({
          libraryName: "xxx/icons",
          libraryDirectory: "icons",
          style: false,
          camel2DashComponentName: false,
        }),
        apply: "build",
      },
    ],
    

外部依赖问题

  • 按需引入和外部依赖配置共存时候,直接配置按需失效的
  • 原因是:按需先执行会转换成路径,导致处理外部依赖时路径匹配不到
  • 解决方法:通过正则配置 external
external: [
 "axios",
 "react",
 "react-router-dom",
 "react-dom",
 "@byted/hooks",
 /\xxx\/ui/,
 /\xxx\/icons/,
],
转载自:https://segmentfault.com/a/1190000041606858
评论
请登录