浏览器使用Commonjs加载UMD
参考,一个简单的UMD实现,包含externals
(function(root, factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
console.log('是commonjs模块规范,nodejs环境')
var depModule = require('./umd-module-depended')
module.exports = factory(depModule);
} else if (typeof define === 'function' && define.amd) {
console.log('是AMD模块规范,如require.js')
define(['depModule'], factory)
} else if (typeof define === 'function' && define.cmd) {
console.log('是CMD模块规范,如sea.js')
define(function(require, exports, module) {
var depModule = require('depModule')
module.exports = factory(depModule)
})
} else {
console.log('没有模块环境,直接挂载在全局对象上')
root.umdModule = factory(root.depModule);
}
}(this, function(depModule) {
console.log('我调用了依赖模块', depModule)
return {
name: '我自己是一个umd模块'
}
}))
开始
// 假设已经通过fetch拿到了js源代码
const jsStr = 'xxx';
// 构造 cmd default,babel在编译es6的时候会把模块挂在default下,所以要加一个default
const exports = {default: undefined};
// 构造module
const module = {exports};
// 构造reqire
const ModuleMapper = {
react: 'React',
'react-dom': 'ReactDOM',
axios: 'Axios',
redux: 'Redux',
};
const require = str => (window[ModuleMapper(str)]);
new Function('exports', 'require', 'module', jsStr)(exports, require, module);
// 拿到了module
module.exports.default
require函数是啥意思
require函数看起来很简单,首先把map如react的字符串,然后从window中取出并返回React Module;
假定react由CDN直接加载,那么它将可以通过window.React访问(实际上react也是由umd导出的)
webpack是这么处理externals依赖的:
function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"), require("react-dom"));
else if(typeof define === 'function' && define.amd)
define("demo", ["react", "react-dom"], factory);
else if(typeof exports === 'object')
exports["demo"] = factory(require("react"), require("react-dom"));
else
root["demo"] = factory(root["React"], root["ReactDOM"]);
}
由于前面new Function传入了module,原本会走到
root["demo"] = factory(root["React"], root["ReactDOM"]);
但是现在会走到:
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"), require("react-dom"));
所以这里需要将require("react")转换成root["React"],root在浏览器环境即window