详解vite如何支持cjs方案示例

目录
  • 一、问题
  • 二、解决方案
  • 三、如何处理commonJS

一、问题

  • vite运行时使用esbuild基于esm
  • 大部分三方包为UMD规范,输出的是CommonJS的包(比如reactlodash
// react 入口文件
// 只有 CommonJS 格式
if (process.env.NODE_ENV === "production") {
  module.exports = require("./cjs/react.production.min.js");
} else {
  module.exports = require("./cjs/react.development.js");
}

二、解决方案

vite提供了预构建阶段,主要用于处理两种情况:

  • 将其他格式(如 UMDCommonJS)的产物转换为 ESM ,以react为例,本文主要记录这种情况的处理。
  • 解决esm请求瀑布流的问题,以lodash-es为例

三、如何处理commonJS

  • vite自动开启了预构建,启动成功后可以在 node_modules/.vite/deps/react.js 看到预构建以后的react(esm)包

很简单一句,调用了chunk中的require_react方法,让我们进入chunk文件。

此处可以看到require_react传入了一个方法给__commonJS,并返回了一个新的方法__require

这里有个令人迷惑的点,就是用到了,逗号表达式,总会返回后面的内容,这句猜测是因为压缩代码导致的,其效果相当于:

function __require() {
    // 压缩后
    return mod || (0, test)((mod = { exports: {} }).exports, mod), mod.exports;
    // 压缩前,仅推测
    if (mod) {
      	return mod
    } else {
        test(mod, mod.exports)
        return mod.exports
    }
};
function test(exports, mod) {
    console.log('exports, mod', exports, mod)
}

在接近 1800 行的require_react_development中,主要是把react的导出内容cv了一遍,并赋值给了mod.exports

最后看回来到node_modules/.vite/deps/react.js:

这句相当于 export default mod.exports,将react的模块用esm的方式输出。

  • commonJSesm的区别在哪里?

让我们先看一段esm的代码

// Named export/import
export { name }
import { name } from "name"
// Default export/import
export default name
import name from "name"

再看一段CommonJS

let name = {
  firstName,
  lastName
}
module.exports = name
mudule.export.firstName = 'z'
exports.lastName = 'zz'

不难看出,在CommonJS中的导出方式都是基于module.exports的,而在ESM中,有两种不同的导入/导出方式,分别是export { name }export default name

因此在把CommonJS转换为ESM时,需要同时导出两种形式,这样很麻烦。(如果不同时导出两种形式,会导致引入时,有一种对应情况无法使用,理论上只用其中一种对应的方式也可以使用)

  • 如何兼容两种ESM的导入/导出形式

此处参考了别的大佬的笔记(vite预构建的代码也是这么实现的):

var esm$1 = { exports: {} };
(function (module, exports) {
  module.exports = () => {};
  exports.a = 3;
  exports.b = 4;
})(esm$1, esm$1.exports);
var esm = esm$1.exports;
export { esm as default };

以上就是详解vite如何支持cjs方案示例的详细内容,更多关于vite支持cjs方案的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vite配置优雅的code spliiting代码分割详解

    目录 Vite如何配置分割代码 1.什么是代码分割/code spliiting 2.Vite 中 rollup code spliiting分割默认方法原理 (1)按照动态导入语句分割打包测试. (2)按照资源导入入口点分割打包测试. (3)manualChunks函数 手动自定义分割.(下面的案例) 3.如何在Vite中配置(vite.config.ts)代码分割/code spliiting (核心关键) Vite代码分割方法1 Vite代码分割方法2 Vite如何配置分割代码 1.什么是

  • vue3 Vite 进阶rollup命令行使用详解

    目录 rollup介绍 以命令行方式打包 Tree Shaking Rollup 的命令行使用 命令行 format 格式 rollup.config.js 设置/获取环境变量 插件 plugins rollup介绍 开源类库优先选择 以 ESM 标准为目标的构建工具 Tree Shaking 以命令行方式打包 安装 rollup npm install -g rollup 创建 index.js 文件 import path from "path"; console.log(&quo

  • Vite的createServer启动源码解析

    目录 启动Vite的createServer 通过vite3安装一个vue的工程 添加断点并开启调试 边调试边理解代码 启动Vite的createServer 为了能够了解vite里面运行了什么,通过执行单步调试能够更加直观的知道Vite具体内容.所以这次我们来试着启动Vite的createServer,并进行调试. 通过vite3安装一个vue的工程 进入工作目录,运行下面的代码,项目名称随意,语言用Vue. npm create vite 进入工程目录安装依赖 添加断点并开启调试 通过vsc

  • 深入剖析vite到底是快还是慢原理详解

    目录 前言 Vite 的快 快速的冷启动 快速的热更新 Vite 的慢 首屏性能 懒加载性能 结束语 前言 谈到 Vite,给人的第一印象就是 dev server 启动速度快.同样规模的项目,相比 Webpack 动辄十几秒甚至几十秒的的启动速度,Vite 简直是快到没朋友,往往数秒之内即可完成启动(PS: 都没有时间去喝一杯 ️ 啦). 正好小编最近在做一些关于开发体验的性能优化,就想着把手上一些项目的开发模式更新为 Vite.经过一番操作,终于改造成功,而效果也不负众望,项目启动速度由原来

  • Vite使用Esbuild提升性能详解

    目录 前言 初探 Esbuild 关键 API - transfrom & build plugin Esbuild 在 Vite 中的巧妙使用 预构建 middlewares 中内容转换 结束语 前言 在上一篇 为什么有人说 vite 快,有人却说 vite 慢? 中,我们提到过开发模式下使用 Vite 会有首屏性能下降的负面效果.之所以会造成首屏性能下降,一方面是 dev server 需要完成预构建才可以响应首屏请求:另一方面是需要对请求文件做实时转换. 也许有的同学会问,是不是针对这两个

  • 详解vite如何支持cjs方案示例

    目录 一.问题 二.解决方案 三.如何处理commonJS 一.问题 vite运行时使用esbuild,基于esm 大部分三方包为UMD规范,输出的是CommonJS的包(比如react.lodash) // react 入口文件 // 只有 CommonJS 格式 if (process.env.NODE_ENV === "production") { module.exports = require("./cjs/react.production.min.js"

  • 详解Jest 如何支持异步及时间函数实现示例

    目录 异步支持 回调函数 callback promise Mock Timer 基本使用 模拟时钟的机制 典型案例 问题分析 解决方法 总结 异步支持 在前端开发中,我们会遇到很多异步代码,那么就需要测试框架对异步必须支持,那如何支持呢? Jest 支持异步有两种方式:回调函数及 promise(async/await). 回调函数 callback const fetchUser = (cb) => { setTimeout(() => { cb('hello') }, 100) } //

  • 详解Java 10 var关键字和示例教程

    关键要点 Java 10引入了一个闪亮的新功能:局部变量类型推断.对于局部变量,现在可以使用特殊的保留类型名称"var"代替实际类型. 提供这个特性是为了增强Java语言,并将类型推断扩展到局部变量的声明上.这样可以减少板代码,同时仍然保留Java的编译时类型检查. 由于编译器需要通过检查赋值等式右侧(RHS)来推断var的实际类型,因此在某些情况下,这个特性具有局限性,例如在初始化Array和Stream的时候. 如何使用新的"var"来减少样板代码. 在本文中,

  • 详解Android 语音播报实现方案(无SDK)

    本文介绍了详解Android 语音播报实现方案(无SDK),分享给大家,具体如下: 功能描述 类似支付宝收款时候的语音播报功能:当别人扫描你的收款码,你收到钱之后,就会听到"支付宝到账12.55元"的语音播报. 要解决的问题 1.播放单个语音文件 2.播放完单个语音文件之后立即播放下一条,这样才能连续 3.当多个完整的语音序列都需要播报时的处理(比如支付宝短时间内收到多条收款推送) 实现思路 1.播放单个文件选择MediaPlayer 首先创建一个MediaPlayer实例 Media

  • 详解shell 变量的高级用法示例

    变量删除和替换 案例:从头开始匹配,将符合最短的数据删除 (#) variable_1="I love you, Do you love me" echo $variable_1 variable_2=${variable_1#*ov} echo $variable_2 案例:从头开始匹配,将复合最短的数据删除(##) varible_3=${variable_1##*ov} echo $varible_3 案例:替换字符串,只替换第一次匹配成功的(/) echo $PATH var6

  • 详解Vite的新体验

    什么是Vite?(是前端新玩具) Vite是一个web开发构建工具,它通过本机 ES 模块导入在开发过程中更新代码,达到快速更新的目的. 特点 超快的冷服务器启动 即时的模块更新 真正的按需编译 更小的打包体积 开始使用 Vue用户注意:Vite当前仅适用于Vue3.x.这也意味着您不能使用尚未与Vue 3兼容的库. 安装 npm init vite-app <项目名称> cd <项目名称> npm install npm run dev ## 执行完以上命令,就意味着你的vue3

  • 详解JavaScript实现简单的词法分析器示例

    目录 正文 什么是词法分析器? 实现一个简单的词法分析器 总结 正文 词法分析是编译器的一项重要工作,其目的是将源代码转换成单个单词(token)的序列,方便后续语法分析器(parser)对其进行分析.在本文中,我们将使用 JavaScript 实现一个简单的词法分析器,以便更好地理解其原理. 什么是词法分析器? 在编译器中,词法分析器是将源代码分割成单个单词的程序.它将输入的字符流转换为单词流,这些单词(token)在后续的编译过程中将被用来构建语法树(parse tree). 词法分析器通常

  • 全面详解Spring Bean生命周期教程示例

    目录 Spring 中 Bean 的生命周期 Bean 的实例化 构造方法注入 工厂方法注入 Bean 的属性赋值 setter注入 构造方法注入 Bean 的初始化 初始化方法 InitializingBean 接口 Bean 的销毁 销毁方法 DisposableBean 接口 总结 Spring 中 Bean 的生命周期 是当今最流行的 Java 开发框架之一,其强大的 Bean容器机制是其中的核心之一.Bean 是指在 Spring 容器中被管理的对象,它们可以被注入到其他对象中,也可以

  • 详解Java代码常见优化方案

    首先,良好的编码规范非常重要.在 java 程序中,访问速度.资源紧张等问题的大部分原因,都是代码不规范造成的. 单例的使用场景 单例模式对于减少资源占用.提高访问速度等方面有很多好处,但并不是所有场景都适用于单例. 简单来说,单例主要适用于以下三个方面: 多线程场景,通过线程同步来控制资源的并发访问. 多线程场景,控制数据共享,让多个不相关的进程或线程之间实现通信(通过访问同一资源来控制). 控制实例的产生,单例只实例化一次,以达到节约资源的目的: 不可随意使用静态变量 当某个对象被定义为 s

  • 详解自定义ajax支持跨域组件封装

    Class.create()分析 仿prototype创建类继承 var Class = { create: function () { var c = function () { this.request.apply(this, arguments); } for (var i = 0, il = arguments.length, it; i < il; i++) { it = arguments[i]; if (it == null) continue; Object.extend(c.p

随机推荐