为什么CommonJS和ES6可以混合使用?
1 node环境下运行
新建一个文件夹testImport,创建webpack.config.js文件,创建src/index.js 内容为空。
执行npm init
安装第三方工具 npm install airspeed
目录结构如下:
index.js写入测试内容:
import isEmptyObject from 'airspeed/isEmptyObject';// const isEmptyObject = require('airspeed/isEmptyObject');const d = {name: 'maile'}console.log(isEmptyObject(d))module.exports = d;
node src/index.js
会提示错误信息:SyntaxError: Cannot use import statement outside a module。
这是因为用node去执行index.js文件的时候,该文件运行在node环境下,支持的是CommonJs规范,不支持ES6。
const isEmptyObject = require('airspeed/isEmptyObject');
换成上面的方式进行引入,可以正常执行。
2 webpack编译
如果想让index.js文件支持es6模块,需要经过webpack编译后再使用。来配置下webpack:
const path = require('path')
const config = {mode: 'development',entry: './src/index.js',output: {filename: `main.min.js`,path: path.resolve(__dirname, 'dist'),}
}module.exports = config;
安装:npm install webpack@4 webpack-cli -D
主意:目前还没有使用babel,仅仅使用了webpack来进行打包。
"scripts": {"build": "webpack","test": "echo \"Error: no test specified\" && exit 1"},
修改src/index.js
import isEmptyObject from 'airspeed/isEmptyObject';// const isEmptyObject = require('airspeed/isEmptyObject');const d = {name: 'maile'}console.log(isEmptyObject(d))export default d;
注意:引入和导出使用规范保持一致。
执行npm run build
运行 node .\dist\main.min.js
可以看到控制台打印出了false。
再看下"airspeed/isEmptyObject"的导出方式:
node_modules/airspeed/isEmptyObject.js
/*** * @desc 判断`obj`是否为空* @param {Object} obj * @returns {Boolean}*/function isEmptyObject(obj) {if(!obj || typeof obj !== 'object' || Array.isArray(obj)) {return false;}return !Object.keys(obj).length;
}
module.exports = isEmptyObject;
这个文件是用commonJs的规范导出的。后使用的过程中是用es6的规范引入的,经过webpack打包后,就支持了混合使用。
3 分析原因
先来看下webpack打包后的文件:
main.min.js
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ })
/************************************************************************/
/******/ ({/***/ "./node_modules/airspeed/isEmptyObject.js":
/*!************************************************!*\!*** ./node_modules/airspeed/isEmptyObject.js ***!\************************************************/
/*! no static exports found */
/***/ (function(module, exports) {eval("/**\r\n * \r\n * @desc 判断`obj`是否为空\r\n * @param {Object} obj \r\n * @returns {Boolean}\r\n */\r\n\r\nfunction isEmptyObject(obj) {\r\n if(!obj || typeof obj !== 'object' || Array.isArray(obj)) {\r\n return false;\r\n }\r\n return !Object.keys(obj).length;\r\n}\r\nmodule.exports = isEmptyObject;\n\n//# sourceURL=webpack:///./node_modules/airspeed/isEmptyObject.js?");/***/ }),/***/ "./src/index.js":
/*!**********************!*\!*** ./src/index.js ***!\**********************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! airspeed/isEmptyObject */ \"./node_modules/airspeed/isEmptyObject.js\");\n/* harmony import */ var airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n// const isEmptyObject = require('airspeed/isEmptyObject');\r\n\r\nconst d = {name: 'maile'}\r\n\r\nconsole.log(airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0___default()(d))\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (d);\n\n//# sourceURL=webpack:///./src/index.js?");/***/ })/******/ });
简化一下上面的代码如下:
(function(modules) { // webpackBootstrap// The require functionfunction __webpack_require__(moduleId) {// Create a new module (and put it into the cache)var module = {i: moduleId,l: false,exports: {}};// Execute the module functionmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);// Return the exports of the modulereturn module.exports;}// Load entry module and return exportsreturn __webpack_require__("./src/index.js");})({"./node_modules/airspeed/isEmptyObject.js":(function(module, exports) {// ./node_modules/airspeed/isEmptyObject.js的内容}),"./src/index.js":(function(module, __webpack_exports__, __webpack_require__) {"use strict";// ./src/index.js})});
这样看着就是不是清晰多了,一个自动执行的函数,入参是 modules
。modules
是一个对象,key为入口文件和所依赖文件的路径,value是一个函数,函数体内部是处理后的文件内容。
先来看自执行函数内部,定义了一个webpack_require函数,并且
returnwebpack_require("./src/index.js"),入参是入口文件。
这个webpack_require 函数内部定义了一个module对象,带有exports属性。调用的时候会传递module,和module.exports。
modules[moduleId].call(module.exports, module, module.exports, _webpack_require); 这里调用的就是自执行函数的入参,找到对应的路径key,调用对应的函数。
"./node_modules/airspeed/isEmptyObject.js":(function(module, exports) {eval("/**\r\n * \r\n * @desc 判断`obj`是否为空\r\n * @param {Object} obj \r\n * @returns {Boolean}\r\n */\r\n\r\nfunction isEmptyObject(obj) {\r\n if(!obj || typeof obj !== 'object' || Array.isArray(obj)) {\r\n return false;\r\n }\r\n return !Object.keys(obj).length;\r\n}\r\nmodule.exports = isEmptyObject;\n\n//# sourceURL=webpack:///./node_modules/airspeed/isEmptyObject.js?");}),
eval内部的module.exports = isEmptyObject,访问到的就是函数入参就是webpack_require函数中定义的module。
"./src/index.js":(function(module, __webpack_exports__, __webpack_require__) {"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! airspeed/isEmptyObject */ \"./node_modules/airspeed/isEmptyObject.js\");\n/* harmony import */ var airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n// const isEmptyObject = require('airspeed/isEmptyObject');\r\n\r\nconst d = {name: 'maile'}\r\n\r\nconsole.log(airspeed_isEmptyObject__WEBPACK_IMPORTED_MODULE_0___default()(d))\r\n\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (d);\n\n//# sourceURL=webpack:///./src/index.js?");})
上面函数入参webpack_exports就是webpack_require函数中定义的module.exports。而webpack_require就是webpack_require这个函数。
看到eval的第一句先执行了一个函数webpack_require.r(_webpack_exports),这个函数如下:
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
大概意思就是标记一个这个文件使用的是es6规范导出的。
src/index.js文件中第一行内容:
import isEmptyObject from 'airspeed/isEmptyObject';
输入为webpack_require(/*! airspeed/isEmptyObject */ \"./node_modules/airspeed/isEmptyObject.js\")。
可以看出无论是以es6规范导出还是以CommonJs规范导出,最终都会被挂在webpack_require函数中定义的module对象上。当然,引入也是如此。
所以如果你的项目使用了webpack进行打包,就放心了混合使用两种方式了。
为什么CommonJS和ES6可以混合使用?相关推荐
- AMD、CMD、CommonJS、ES6(import/export)
AMD.CMD.CommonJS.ES6(import/export) AMD.CMD.CommonJS是ES5模块化解决方案 AMD -- 异步模块 Asynchronous Module Defi ...
- 模块化(AMD、CMD、CommonJS、ES6)
1,CommonJS 服务器,同步加载模块,加载机制是:输出拷贝 模块导出:module.exports 导入模块:require 2,AMD(异步模块定义) 用于浏览器,防止js加载阻塞页面渲染,异 ...
- 模块打包之CommonJS与ES6模块比较初探
Time: 20190920 模块是具有特定功能的组成单元,不同模块负责不同的工作,然后会以某种方式联系到一起,形成完整的程序逻辑. CommonJS CommonJS是2009年社区提出的,包含模块 ...
- es6 混合commjs_前端模块化——CommonJS、ES6规范
什么叫模块化? 对于一个复杂的程序,将其按照一定的规范封装成几个文件块,每一块向外暴露一些接口,但是块的内部数据是私有的,块与块之间通过接口通信.这个过程称为模块化. 模块化的好处 CommonJS ...
- es6模块化机制及CommonJS与ES6模块化规范区别
模块化机制 CommonJS模块化规范 导入 1. let { firstName, lastName } = require('./1-module.js') 导出 1. module.export ...
- 03.06 随手记(AMD、CMD、CommonJS、ES6 Module的区别)
***当前阶段的笔记 *** 「面向实习生阶段」https://www.aliyundrive.com/s/VTME123M4T9 提取码: 8s6v 点击链接保存,或者复制本段内容,打开「阿里云盘」 ...
- commonjs、ES6的模块暴露和模块引入
一.commonjs commonjs是作用于服务端应用程序,让js程序具有模块化功能的一种语法规范,执行方式是同步且运行时加载. (一).module.exports 导出 定义一个匿名对象,将需要 ...
- Requirejs与r.js打包,AMD、CMD、UMD、CommonJS、ES6模块化
一:require.js 1.require.js是什么?为什么要用它? require.js是一个JavaScript模块载入框架,实现的是AMD规范.使用require.js有以下优点: ① 异步 ...
- 五、Vue模块化开发学习笔记——JavaScript原始功能、匿名函数的解决方案、使用模块作为出口、CommonJS、ES6 export和import的使用
一.JavaScript原始功能 -在网页开发的早期,js制作作为一种脚本语言,做一些简单的表单验证或动画实现等,那个时候代码还是很少的. 那个时候的代码是怎么写的呢? 直接将代码写在<scri ...
最新文章
- mvc:interceptor 不起作用的一个解决方法
- 报错Submitted credentials for token did not match the expected credentials
- 02_创建Git仓库,克隆仓库,git add,git commit,git push,git pull,同行冲突,不同行冲突的结局方案,git mergetool的使用
- python实现redis分布式锁
- mysql vb_vb连接mysql
- JavaScript:学习笔记(3)——正则表达式的应用
- 简易网络视频播放器android
- java创建项目出现怎么办_maven创建项目后main/java missing的解决方法
- java 人脸识别博客
- 全球最值得模仿的500个网站(扫描版pdf)
- VARCHAR2 与 NVARCHAR2 区别
- 6步解决win7局域网内传输慢的问题
- 郑州等保测评公司有哪些?在哪里?
- 搬家后计算机总重启,电脑无故重启是这一个月来的事了,我刚刚搬家电脑搬到新家那用了没几 爱问知识人...
- Arcgis地图切片专题(关于tpk的制作以及迁移切片包至服务器的相关流程)
- 在线购物系统 分析类或问题域类图
- 高数-数列极限与函数极限
- gem5下用se模式运行自己的测试程序
- 小车运料c语言编程,西门子PLC编程实例及技巧(运料小车控制系统)
- 电桥-20151208