概述

本文是我在查资料的时候学到的一些东西,记录下来,供以后开发时参考,相信对其他人也有用。

参考资料:

异步函数 - 提高 Promise 的易用性

深入 CommonJs 与 ES6 Module

聊聊 package.json 文件中的 module 字段

异步 map

我们知道,Array.map 能够遍历 Array 里面的每一个元素,然后组成一个新的数组,它的参数是一个函数。如果这个函数里面有异步方法会怎样呢?

const jsonPromises = urls.map(async url => {
const response = await fetch(url);
return response;
});

上面的例子中,在 Array.map 里面接了一个 async 函数,它不在乎我提供给它的是不是异步函数,只把它当作一个返回 Promise 的函数来看待。 也就是说:它不会等到第一个函数执行完毕就会调用第二个函数。

虽然上面的例子初看很惊艳,但是我没有找到实际的应用场景。。。

前端模块化

前端模块化发展这么久了,目前比较流行的模块化方案主要有下面三种:

  1. umd 模块(通用模块)
  2. CommonJs 模块(node模块)
  3. es6 module(浏览器模块)

umd 模块

使用 UMD 规范的 js 文件的后缀通常写成 .umd.js

UMD 模块是以前比较流行的模块化方案,它的主要代码如下所示:

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.libName = factory());
}(this, (function () { 'use strict';})));

这段代码判断运行环境,如果是 node 环境就使用 CommonJs 规范,如果不是则判断是否为 amd 环境,如果是则使用 AMD 规范,如果不是则导出为全局变量。所以 UMD 模块化是 amd + commonjs + 全局变量 这三种风格的结合。

因为 UMD 模块既能使用在浏览器环境,也能使用在 node 环境。所以现在需要在 html 中用 script 标签引入的包大多数都是用 UMD 模块。

CommonJs

使用 CommonJs 规范的 js 文件的后缀通常写成 .cjs.js

CommonJs 规范是 node 使用的模块体系,所有在 node 运行的包都是 CommonJs 规范。示例如下:

// foo.js
module.exports.foo = 2; // index.js
const foo = require('./foo');

CommonJs 规范打包之后就变成类似下面这个样子:

(function (exports, require, module, __filename, __dirname) { ...

es6 module

es6 module 规范又被称为 ESM 规范,使用这个规范的 js 文件的后缀通常写成 .esm.js

CommonJs 规范是 我们开发的时候 使用的模块体系。示例如下:

// foo.js
export default function () {} // index.js
import foo from './foo';

静态规范与 tree shaking

我们经常听到别人说,CommonJs 模块规范是动态的,所以在任何时刻都能使用 require 引入包;而 ESM 模块规范是静态的,所以只能在最开始使用 import 引入包,而且会在编译的时候确定导入和导出。

下面解释下为什么 CommonJs 模块规范是动态的而 ESM 模块规范是静态的?

因为在 node 端,当我们 require 一个包的时候,我们只需要从磁盘里面加载这个包的内容即可,非常迅速;但是如果在浏览器端引入一个包的时候,需要从网络上发送 http 请求加载这个包,耗时非常久,会导致浏览器阻塞,所以不能当代码执行一半的时候引入包,而需要在顶层一次性把包全部引入。(而且是异步引入)

由于,ESM 模块需要在编译的时候引入包,这个缺点却带来一个意想不到的好处,就是 tree shaking。说白了,就是可以在编译的时候确定哪些代码被实际引入了,哪些没有,然后那些没有被实际引用的代码就不会被打包!!!这样可以极大的减少打包体积。

pkg.module

但是我们在实际打包的时候,会忽略 node_modules 里面的内容,直接引入里面的包,而里面的包大多使用的是 UMD 规范,它在 node 端打包的时候是 CommonJs 规范,而 CommonJs 规范是动态的,编译的时候不知道哪些代码没有被使用,所以就不能 tree shaking

这样打包 node_modules 里面的包的时候岂不是会打包很多无用的代码???

这个时候 pkg.module 就应运而生了,pkg.module 指的是 package.json 文件中的 module 字段。我们知道 package.json 文件中 main 字段指向的就是打包后的代码,这个代码一般是 UMD 规范。而 module 字段指向的是 ESM 规范编写的代码!!!这样我们在引入 node_modules 的时候,如果引用的是 module 字段指向的代码,我们就可以对这个包进行 tree shaking 了!!!

异步 map 和模块打包的更多相关文章

  1. js模块化/js模块加载器/js模块打包器

    之前对这几个概念一直记得很模糊,也无法用自己的语言表达出来,今天看了大神的文章,尝试根据自己的理解总结一下,算是一篇读后感. 大神的文章:http://www.css88.com/archives/7 ...

  2. 一份关于webpack2和模块打包的新手指南(二)

    插件 我们已经看到一个内置的webpack插件的例子,在npm run build脚本中调用的webpack -p命令就是使用webpack附带的UglifyJsPlugin插件以生产模式压缩打包文件 ...

  3. 多模块打包后,扫描不到@controller和@service,实现 ADD DIRECTORY ENTRIES

    多模块打包后,扫描不到@controller和@service等Bean. 原因:打包时没有生成目录信息 解决办法: 1.在eclipse或者myeclipse 打包时 勾选 ADD DIRECTOR ...

  4. Webpack - CommonJs & AMD 模块打包器

    Webpack 是一个 CommonJs & AMD 模块打包器.可以把你的 JavaScript 代码分离为多个包,在需要的时候进行加载,支持预处理文件,例如 json, jade, cof ...

  5. Maven之多模块打包成一个jar包及assembly

    一.多模块打包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  6. 一份关于webpack2和模块打包的新手指南

    webpack已成为现代Web开发中最重要的工具之一.它是一个用于JavaScript的模块打包工具,但是它也可以转换所有的前端资源,例如HTML和CSS,甚至是图片.它可以让你更好地控制应用程序所产 ...

  7. 【spring cloud】【IDEA】【Maven】spring cloud多模块打包,打包的jar包只有几k,jar包无法运行,运行报错:no main manifest attribute, in /ms-eureka.jar

    ======================================================================================== 引申:maven打包多 ...

  8. Zepto自定义模块打包构建

    文章转自 http://www.chengxuyuans.com/web_technology/zeptojs-build.html zepto.js 是个好东西,遵循 jQuery API,但比 j ...

  9. python模块打包方法

    http://www.jb51.net/article/92789.htm 一 首先将模块的目录结构整理如下: VASPy/ ├── LICENSE ├── MANIFEST ├── MANIFEST ...

随机推荐

  1. 雪花算法生成ID

    前言我们的数据库在设计时一般有两个ID,自增的id为主键,还有一个业务ID使用UUID生成.自增id在需要分表的情况下做为业务主键不太理想,所以我们增加了uuid作为业务ID,有了业务id仍然还存在自 ...

  2. KVM安装配置笔记

    系统环境centos6.6 一.KVM安装前系统相关操作: (1)修改内核模式为兼容内核启动 # grep -v "#" /etc/grub.confdevice (hd0) HD ...

  3. 01.LNMP架构-Nginx源码包编译部署详细步骤

    操作系统:CentOS_Server_7.5_x64_1804.iso 部署组件:Pcre+Zlib+Openssl+Nginx 操作步骤: 一.创建目录 [root@localhost ~]# mk ...

  4. Activity安装与使用

    详细安装步骤:http://blog.csdn.net/oyzl68/article/details/16817963

  5. jquery preventDefault() 方法防止打开不是本站的链接URL

    将以下代码保存为test.html,用浏览器打开即可测试 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  6. Luogu P3170 [CQOI2015]标识设计 状态压缩,轮廓线,插头DP,动态规划

    看到题目显然是插头\(dp\),但是\(n\)和\(m\)的范围似乎不是很小.我们先不考虑复杂度设一下状态试试: 一共有三个连通分量,我们按照\(1,2,3\)的顺序来表示一下.轮廓线上\(0\)代表 ...

  7. java基础语法2-运算符与流程控制

    关键字-标识符-常量和变量-运算符-流程控制-方法-数组 5 运算符 算术运算符Arithmetic Operators 赋值运算符Assignment Operators 比较运算符Compare ...

  8. iOS自定义键盘的简单实现

    自定义键盘类VolumeInputKeyboardView: VolumeInputKeyboardView.h文件: #import <UIKit/UIKit.h> NS_ASSUME_ ...

  9. tf.expand_dims和tf.squeeze函数

    from http://blog.csdn.net/qq_31780525/article/details/72280284 tf.expand_dims() Function tf.expand_d ...

  10. 防火墙firewalld 案例1.内网请求转发到外网

    环境: 内网应用服务端口流量需要转发请求到外网端口 解决思路: firewalld 的富规则 d主机: 富规则 d主机对外dnat发布5423端口,然后dnat请求s的80端口: s主机snat返回8 ...