前端工程化cjs umd esm 打包差异详解

目录
  • 模块
  • 为什么要模块
  • commonjs
  • UMD
  • es moudle
  • 总结

模块

先简单说一下模块这玩意:

一个模块(module)就是一个文件。一个脚本就是一个模块。就这么简单。

内部有自己的局部作用域以及程序,外部可以通过模块暴露的接口进行调用、执行模块内的程序

为什么要模块

我们从另一个角度出发,如果没有模块,会怎么样?

  • 污染全局作用域
  • script 标签自己插入自己手动排好顺序
  • ....

总之就是,难以复用、难以维护!

所以很明显,我们需要模块化。

但是不同的环境是有不同的模块话机制的~

就目前来说,常用常见的模块化打包方式有这么三种:

  • common js
  • ES module
  • UMD

commonjs

cjs 是 Node 中的模块规范,导入和导出的 API 为

  • require
  • exports

它的 require 是同步的,因为 node 模块系统是需要同步读取模块文件内容并编译执行以得到模块接口的。

而在浏览器端,一般都以 script 标签引入 —— script 标签可是天生异步的。

so 它本身只可以运行在 node 环境下,比如ms

他就是只支持 cjs,如果你想用 CDN 直接在浏览器中使用是不行的

但是,webpack 是支持 cjs 的,通过 webpack 就可以将其运行在浏览器中。所以,通过 webpack 打包你就可以在浏览器环境中使用 ms。

也就是说,在 webpack 环境下,cjs 即支持 node 环境,也支持浏览器环境~

除此之外,他是在运行时加载的,模块输出的也只是拷贝

UMD

全称 Universal Module Definition —— “通用模块定义”

这也算是应运而生,它可以在运行或者编译时让同一个代码模块使用 cjs 或者 amd

amd : Asynchronous ModuleDefinition
异步模块定义,采用异步方式加载模块。所有依赖模块的语句,都定义在一个回调函数中,等到模块加载完成之后,这个回调函数才会运行

也就是 集它们于一身,所以它既可以在 node 或者 webpack 环境下用 require 引用使用,也可以 在浏览器中 直接用 script 引用 CDN 使用

实现大概如下:

((root, factory) => {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //CommonJS
        var $ = requie('jquery');
        module.exports = factory($);
    } else {
        root.testModule = factory(root.jQuery);
    }
})(this, ($) => {
    //todo
});

也就是在定义模块的时候检测当前环境和模块定义的方式,将各种模块方法转换为同一种写法

有一些包就是用的这种打包方法

有些包是多种打包方法都有,比如

antd

es/index.js下就是 es6 的打包方式(下面会说)

dist/antd.js下就是 umd 的打包方式

lib/index.js下就是 cjs 的打包方式

es moudle

上面说的可能都是过去一段时间里最好的打包方式,但是 在未来 ES6 的打包方式 应该还是会全面替代它们

esm 是基于 ESMAScript 模块化规范的 —— 他的爹就代表着 他的前途一片光明

node 环境和浏览器环境下都支持~

另外他模块输出的是值的引用。

还是在编译时加载,这意味着可以在编译期间进行 Tree Shaking,减少 js 体积

另外还支持动态引入

const a = await import ('xxx')

总结

不同之处在于:

  • 何时加载?运行时还是编译?
  • 引出的值是拷贝还是引用?
  • 可在哪些环境下使用?
  • 同步还是异步?

以上就是前端工程化cjs umd esm 打包差异详解的详细内容,更多关于前端cjs umd esm 打包差异的资料请关注我们其它相关文章!

(0)

相关推荐

  • UMD的包导出TS 类型方法示例

    目录 TypeScript 里声明模块 类型提示检查 UMD 的 global 类型 总结 TypeScript 里声明模块 在 TypeScript 里声明模块,最早是用 namespace 和 module 的语法,后来支持了 es module,类型和变量会用 import 来导入.用 export 导出. 比如你写了一个库,导出的变量叫 Guang,它下面有 name 和 age 两个属性,所以你是这样声明类型的: export default Guang; declare namesp

  • Vue前端打包的详细流程

    目录 1.添加打包命令 2.运行打包代码 3.打包指定不同的环境变量 4.打包自定义文件 4.1 移除三方包 4.2 gzip压缩 5.打包发生错误: 1.添加打包命令 package.json中添加配置 npm run build 发布到线上的代码 不便于调试 命令: ①npm run build:dev 开发调式环境 ②npm run build:prod 线上调试环境 "build:dev": "vue-cli-service build --mode dev"

  • vuecli3打包后出现跨域问题,前端配置拦截器无效的解决

    目录 打包后跨域问题,前端配置拦截器无效 问题 解决方案 vue3处理跨域问题 打包后跨域问题,前端配置拦截器无效 问题 这几天在把项目弄好,打包完成后发现之前cli配置的拦截器没有在打包后没起到作用,使用别的方法通过nginx反向代理进行配置跨域. 解决方案 在nginx里面的nginx.config里面配置 配置如下 server { listen 80;#监听端口 server_name localhost;#代理服务地址 add_header Access-Control-Allow-O

  • vue前端项目打包成Docker镜像并运行的实现

    目录 vue前端项目打包成Docker镜像并运行 前端将vue打包成镜像发布 一.总体预览 二.打包配置 三.问题思考 vue前端项目打包成Docker镜像并运行 首先说明咱们的前端项目是基于Vue的,反向代理使用的是nginx 1.打包vue前端项目生成dist文件夹上传至服务器 新建一个文件夹,叫vueDockerTest,下面的文件都需要. cert是你存放ssl证书的文件夹,nginx.conf 是nginx的配置文件,dist是你打包的前端静态文件 2.修改Dockerfile文件 #

  • Vue3中使用pnpm搭建monorepo开发环境

    目录 前言 Pnpm 和 Monorepo 搭建开发环境 创建项目 配置 monorepo 安装依赖 初始化Typescript 准备两个模块 shared reactivity 编写构建脚本 完成第一次调试 小结 前言 Vue3 源码阅读系列,计划从环境搭建开始,将 Vue3 的响应式模块,运行时模块和编译器模块,以及状态库 Pinia.路由库 Vue-Router的核心原理做一个梳理.这大概是一个漫长的过程.祝自己不要烂尾,祝大家有所收获. Pnpm 和 Monorepo Pnpm 是新一代

  • 支持cjs及esm的npm包实现示例详解

    目录 正文 tsc cjs esm package.json rollup rollup.config.js package.json webpack webpack.config.js package.json esbuild 正文 模块化是一个老生常谈的问题了,打包工具层出不穷. 那么,如何利用这些打包工具去打出既支持cjs,又支持esm的npm包呢. 这篇文章不涉及概念,是一些打包实测. demo repo: github.com/FrankKai/np… 可以clone下来,本地构建测试

  • 前端工程化cjs umd esm 打包差异详解

    目录 模块 为什么要模块 commonjs UMD es moudle 总结 模块 先简单说一下模块这玩意: 一个模块(module)就是一个文件.一个脚本就是一个模块.就这么简单. 内部有自己的局部作用域以及程序,外部可以通过模块暴露的接口进行调用.执行模块内的程序 为什么要模块 我们从另一个角度出发,如果没有模块,会怎么样? 污染全局作用域 script 标签自己插入自己手动排好顺序 .... 总之就是,难以复用.难以维护! 所以很明显,我们需要模块化. 但是不同的环境是有不同的模块话机制的

  • Svelte调试模式js级别差异和细化后的体积差异详解

    目录 js级别的差异 ecma ast差异 细化后的体积差异 调试模式 on:事件名 svelte:options setContext js级别的差异 主要来自两个方面:hook系统(不考虑类)和ecma-ast差异hook系统. 钩子系统的api更多地用于纯函数组件注入状态和生命周期.在这两个方面,Svelte提供的解决方案是不同的. 由于预运行编译,Svelte编译器扫描所有与UI相关的状态并注入黑魔法,使得状态的使用与变量声明和赋值一样简单. 基本上,开发人员不需要太在意所谓的副作用:因

  • Electron学习应用程序打包实例详解

    目录 引言 如何将应用程序打包(Win) 1.关于package.js文件详解 2.使用electron-packager打包 3.使用electron-builder打包 整体感受 效果 引言 人真的是会变得越来越懒的,也正是人的惰性吧,真的是很讽刺. 关于这个应用程序的开发,断更了很久,但是代码部分还算没落下吧,终于在周一.周二终把这个应用程序写完了. 开发完不是终点.而是打包后可以使用才真的算是结束吧. 如何将应用程序打包(Win) 1.关于package.js文件详解 完整实例如下: j

  • 从Vue转换看Webpack与Vite 代码转换机制差异详解

    目录 配置方式 Vue 文件编译的流程 Vite 的 Vue 转换流程 Webpack 的 Vue 转换流程 对比和总结 配置方式 我们知道,Webpack 是使用 loader 转换代码的,而 Vite/Rollup 则是使用插件转换代码,那这两种机制有什么差异呢?我们用 Vue 的转换来说明一下. Vite 使用插件转换代码,直接在 plugins 使用 @vitejs/plugin-vue 即可 // vite.config.js import vue from '@vitejs/plug

  • Python之py2exe打包工具详解

    下载Python对应版本的py2exe,使用这个工具可以将自己的程序打包成exe文件. 使用这个工具需要写一个用于打包的setup.py文件(名称可以自己定,不一定是setup.py),写好后在命令提示符界面cd到这个文件的目录,执行命令"python setup.py py2exe"即可打包完成. 下面是自己参考其他网友写的,可供参考: # _*_ coding: utf-8 _*_ import py2exe from distutils.core import setup inc

  • vue-router 前端路由之路由传值的方式详解

    路由传值 在前端的路由里面,我们在切换路由的时候,也相当于切换了页面,页面与页面之前有时候需要做到传值 ,这个时候就需要进行路由传值,在VueRouter里面,两个路由之间做跳转的时候,如何进行传值呢? 普通跨页面传值: 1.通过localStorage setItem() getItem() 2.通过search(地址栏 ? 后面的参数) VueRouter的路由传值 VueRouter的路由传值有两种方式 jquery传值. 类似get传值 传值的路由 this.$router.push({

  • 对Python2与Python3中__bool__方法的差异详解

    学习Python面向对象编程的时候,遇到了一个很有意思的小问题.Python的__bool__方法不起作用的问题. 我反复读了我手中的教程,确认了我写的代码应该管用.可是在测试的时候却一直不通过,后来发现我实现的__bool__方法似乎并不是Python本身的接口. 代码如下: class Demo(): def __init__(self,value = 0): self.value = value def __bool__(self): return bool(self.value > 5)

  • 基于python计算滚动方差(标准差)talib和pd.rolling函数差异详解

    我就废话不多说了,大家还是直接看代码吧! # -*- coding: utf-8 -*- """ Created on Thu Apr 12 11:23:46 2018 @author: henbile """ #计算滚动波动率可以使用专门做技术分析的talib包里面的函数,也可以使用pandas包里面的滚动函数. #但是两个函数对于分母的选择,就是使用N还是N-1作为分母这件事情上是有分歧的. #另一个差异在于:talib包计算基于numpy,

  • Docker 容器生命周期 架构 以及和VM之间的差异详解

    容器的生命周期 容器运行时的生命周期 容器是一组具有隔离特性的进程集合,在使用 docker run 的时候会选择一个镜像来提供独立的文件系统并指定相应的运行程序.这里指定的运行程序称之为 initial 进程,这个 initial 进程启动的时候,容器也会随之启动,当 initial 进程退出的时候,容器也会随之退出. 因此,可以认为容器的生命周期和 initial 进程的生命周期是一致的.当然,因为容器内不只有这样的一个 initial 进程,initial 进程本身也可以产生其他的子进程或

  • vue前端开发层次嵌套组件的通信详解

    目录 前言 示例 小结 前言 vue父子组件之间通过props很容易的将父组件的值传递给子组件,如果一个组件嵌套很多层,每一层之间度需要同props进行传值,很麻烦,且不易维护 示例 [示例]A组件中使用了B组件,B组件中使用了C组件,C组件需要使用A组件的数据text及使用A组件的方法getmethod.A组件代码如下: <template> <div> <P>这是A组件</P> <v-comb></v-comb> </div

随机推荐