一文彻底弄懂 “CommonJs” 与 “EsModule” 区别 |
您所在的位置:网站首页 › 后缀s和es的区别 › 一文彻底弄懂 “CommonJs” 与 “EsModule” 区别 |
简介
文章中就不具体解释什么是 “CommonJs” 与 “EsModule” 了,我们先简单的描述一下 “CommonJs” 与 “EsModule” 的区别。 它们有三个重大差异。 CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。 CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。 CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。因为在 Webpack 中是支持这两种模块加载方式的,所以接下来我们就通过 Webpack 并结合 Demo 来具体解释一下这三个差异。 对 Webpack 不熟的童鞋可以看一下我的这篇文章:来和 webpack 谈场恋爱吧 准备工作 初始化我们先创建一个 module-demo 目录,然后执行 npm 的初始化: mkdir module-demo && cd module-demo && npm init -y 安装 Webpack在 module-demo 目录下执行以下命令: npm install webpack webpack-cli --registry=https://registry.npm.taobao.org 配置 Webpack在 module-demo 项目根目录下创建一个 webpack.config.js 文件: touch webpack.config.js然后将以下内容写入到 module-demo/webpack.config.js 文件: module.exports = { mode: "none", // 为了测试方便,直接改成 node 模式 output: { pathinfo: true, // 添加 module 的 path 信息 }, devtool: false, // 去掉 source-map 信息 }Webpack 的配置就不详细介绍了,感谢的小伙伴可以看一下我的这篇文章:来和 webpack 谈场恋爱吧 创建入口文件在 module-demo 项目根目录下创建一个 src 目录: mkdir src并在 module-demo/src 目录下创建一个 index.js 文件,用来作为我们 webpack 打包的入口文件: touch ./src/index.js 测试我们可以试着在 module-demo 项目根目录下执行以下命令进行 webpack 打包命令测试: npx webpack可以看到,在项目的 module-demo/dist 目录下生成了一个 main.js 文件,main.js 文件就是我们通过 webpack 打包出来的资源文件。 ok,到这我们的准备工作就结束啦! 差别(一)CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。 CommonJS 模块输出的是值的拷贝我们在 module-demo/src 目录下创建一个 commonjs 目录,用来存放 commonjs 模块: mkdir ./src/commonjs然后在 src/commonjs 目录下创建一个 lib.js 文件: touch ./src/commonjs/lib.js接着将以下内容写入到 src/commonjs/lib.js 文件: // lib.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, };上面代码输出内部变量counter和改写这个变量的内部方法incCounter。 然后我们在src/index.js里面加载这个模块: // main.js var mod = require('./commonjs/lib'); console.log(mod.counter); // 打印 counter 值 mod.incCounter(); console.log(mod.counter); // 打印 counter 值最后我们在 module-demo 根目录下执行 webpack 打包命令: npx webpack等打包完成后,我们运行一下 webpack 打包过后的 dist/main.js 文件: node ./dist/main.js可以看到,两次 console.log 打印的都是 3,我们调用了 incCounter 方法后,counter 并没有改变,这是为什么呢? 我们看一下打包过后的 dist/main.js 文件: /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ([ /* 0 */, /* 1 */ /*!*****************************!*\ !*** ./src/commonjs/lib.js ***! \*****************************/ /***/ ((module) => { // lib.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, }; /***/ }) /******/]); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = { }; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: { } /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ var __webpack_exports__ = { }; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { /*!**********************!*\ !*** ./src/index.js ***! \**********************/ // main.js var mod = __webpack_require__(/*! ./commonjs/lib */ 1); console.log(mod.counter); // 打印 counter 值 mod.incCounter(); console.log(mod.counter); // 打印 counter 值 })(); /******/ })() ;当我们执行 node ./dist/main.js 命令的时候,最先执行了这段代码: (() => { /*!**********************!*\ !*** ./src/index.js ***! \**********************/ // main.js var mod = __webpack_require__(/*! ./commonjs/lib */ 1); console.log(mod.counter); // 打印 counter 值 mod.incCounter(); console.log(mod.counter); // 打印 counter 值 })();也就是我们的入口文件 src/index.js 文件: // index.js var mod = require('./commonjs/lib'); console.log(mod.counter); // 打印 counter 值 mod.incCounter(); console.log(mod.counter); // 打印 counter 值当我们用 require 导入 ./commonjs/lib 模块的时候,webpack 最后会编译成这样: // index.js var mod = require('./commonjs/lib'); // 编译前 // dist/main.js var mod = __webpack_require__(/*! ./commonjs/lib */ 1); // 编译后ok,我们看一下dist/main.js 文件中的 __webpack_require__ 方法: function __webpack_require__(moduleId) { // 检查缓存中是否有该模块 var cachedModule = __webpack_module_cache__[moduleId]; // 缓存中有就直接返回 if (cachedModule !== undefined) { return cachedModule.exports; } // 创建一个新的模块,并把当前模块放入到缓存中 var module = __webpack_module_cache__[moduleId] = { exports: { } // 模块的返回值 }; // 执行该模块 __webpack_modules__[moduleId](module, module.exports, __webpack_require__); // 返回模块的结果 return module.exports; }可以看到,在 __webpack_require__ 方法中,首先是去缓存中找这个模块,如果缓存中没有该模块的话,就会新创建一个模块,然后执行这个模块,最后导出这个模块。 我们重点看一下执行该模块的代码: // 执行该模块 __webpack_modules__[moduleId](module, module.exports, __webpack_require__);__webpack_modules__ 其实就是一个模块数组,用来存放我们源文件中的所有模块信息: var __webpack_modules__ = ([ /* 0 */, /* 1 */ /*!*****************************!*\ !*** ./src/commonjs/lib.js ***! \*****************************/ /***/ ((module) => { // lib.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, }; /***/ }) /******/]);可以看到,我们当前 demo 中有两个模块 src/index.js 与 src/commonjs/lib.js,因为 src/index.js 没有导出任何模块信息,所以 __webpack_modules__ 数组的第一个子项为 undefined,当我们执行: __webpack_modules__[moduleId](module, module.exports, __webpack_require__);代码的时候,我们传递进来的是 1: // dist/main.js var mod = __webpack_require__(/*! ./commonjs/lib */ 1); // 编译后所以最后会执行 __webpack_modules__ 数组的第 1 项内容,也就是我们的 src/commonjs/lib.js 模块: var __webpack_modules__ = ([ /* 0 */, /* 1 */ /*!*****************************!*\ !*** ./src/commonjs/lib.js ***! \*****************************/ /***/ ((module) => { // lib.js var counter = 3; function incCounter() { |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |