time: 2018.9.11
update: 2020.7.7
update: 2021-06-10 19:24:58
author: heyunjiang
目录
背景
使用 vue, react 组件化开发很久了,一直都是按照指定的模式开发,虽然说没有啥问题,但是也不知道个中缘由。
在项目日常开发中,有遇到如下问题:
Vue
对象,然后修改 Vue.prototype 属性,会影响到我们全局的 new Vue
对象吗?会,因为 import 模块在编译时就打包在了一起, new Vue 是在模块引入之后才执行的;如果是动态加载的模块,则不会收到影响es6 模块化实现,是浏览器自身实现的 api,在执行代码时,发现需要 import 组件,会发起 http 请求,如果之前已经请求过的会被缓存。
而 commonjs 模块化,主要是 nodejs 的应用,通过 require 关键字加载模块,运行时引入模块并缓存起来。
问题:
import 输入属性要点
// a.js
import Hello from 'b.js';
var foo = '234';
// b.js
let world = 12;
export default world;
上述代码的执行流程
import 本质是连接2个模块的变量
输出格式要求
export const hello = 1
export {ad as default}
,即输出一个名为 default
的变量。只能有一个 export default
总结:export 输出必须为一个接口,输出的是模块属性引用关系,不能输出一个值;而 export {} 、export default 属于特殊的输出引用关系方式,也是常用的输出格式。
export 和 import 不能用在块级作用域中,只能位于顶层
同 import 直接加载模块不同,import() 方法用于异步加载模块,返回 promise 对象。在浏览器和 nodejs 中都有实现。
传统浏览器加载方式
<script type="application/javascript" src="path/to/myModule.js"></script>
<script type="application/javascript" src="path/to/myModule.js" defer></script> // 页面渲染完再按顺序执行
<script type="application/javascript" src="path/to/myModule.js" async></script> // 加载完就执行,暂停渲染
es6 模块加载
<script type="module" src="./foo.js"></script> // 默认带有 defer 属性,异步加载,不需要再设置 defer 属性
commonjs 方式
var mod = require('./lib');
moduel.exports = {}
es modules 方式
.mjs
或者 package.json type = module
main
字段,则会直接去加载 main 指定路径文件。也可以指定 exports 字段,优先级 exports > main问:我们在日常业务开发中,通常都是使用 nodejs 环境,让 webpack 处理一下 import export。我们平时写的 import export,都是 es module,但是 webpack 打包结果不一样,是啥原因呢。
答:是为了兼容不支持 esm 的浏览器
umd 表示同时兼容 amd, cjs, 全局变量的写法,通常包含如下头部
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["jquery", "underscore"], factory);
} else if (typeof exports === "object") {
module.exports = factory(require("jquery"), require("underscore"));
} else {
root.Requester = factory(root.$, root._);
}
}(this, function ($, _) {
// this is where I defined my module implementation
var Requester = { // ... };
return Requester;
}));
特点如下
.js
:es6 之前支持的 js 文件格式.mjs
:浏览器支持的标准 es module 格式,使用 import, export 实现.jsm
:js module,非标准(2020.10.26)不同于 esmodule,js code module 是独立的 js 代码块,没有特殊的导出对象
使用方式如下
// 定义 jsm,文件格式为 jsm
var bar = {
name : "bar",
size : 3
};
// 使用 jsm,这个URL必须是在磁盘上的一个文件
Components.utils.import("resource://app/my_module.jsm");
// 卸载 jsm
Components.utils.unload()
特性
cjs 作为 nodejs 早期模块化的实现方式,在 12.22 和 14.17 版本就稳定支持了 esm; esm 在浏览器支持 es6 之后就支持了
esm 较于 cjs 的优势