webpack 打包 CommonJs, ECMAScript

1. 首先配置一个简单的webpack项目

 1 const path = require('path')
 2 const htmlWebpackPlugin = require('html-webpack-plugin')
 3 
 4 module.exports = {
 5   entry: {
 6     app: './src/js/index.js'
 7   },
 8   output: {
 9     path: path.resolve(__dirname, '../dist'),
10     filename: 'js/[name].bundle.js'
11   },
12   module: {
13     rules: [
14       {
15         test: /\.js$/,
16         exclude: '/node_modules/',
17         loader: 'babel-loader'
18       }
19     ]
20   },
21   plugins: [
22     new htmlWebpackPlugin({
23       filename: 'index.html',
24       template: './src/index.html'
25     })
26   ]
27 }
View Code
/* index.js */
import * as ejs from './ejs'
import cjs from './cjs'
const requireCjs = require('./cjs')
const requireEjs = require('./ejs')

console.log('cjs: ', cjs)
console.log('ejs: ', ejs)
console.log('requireCjs: ', requireCjs)
console.log('requireEjs: ', requireEjs)

/* ejs.js ecmaScript */
const a = 12
const b = {
  a: 1,
  b: 2
}
function fn1 (a) {
  console.log('fn1 in ejs: ', a)
}

export default fn1
export {
  a, b
}

/* cjs.js -- commonjs */
const a = 1
const b = 2

function fn1 (a) {
  console.log('fn1 in cjs: ', a)
}

// module.exports = {
//   a, b, fn1
// }

exports.a = a
View Code

2. 通过package.json 里面配置webpack 命令打包,从生成的文件可以看到,webpack 打包之后生成的是一个立即执行函数:

/* 
    生成一个立即执行函数,函数的参数是一个对象 
        {
            key: 文件路径,
            value: 打包之后的函数,参数为module跟exports,类似 commonjs
        }
*/
(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__)
  // 将modules数组参数挂载在属性m上
    __webpack_require__.m = modules;
  // expose the module cache
  // 将缓存模块挂载在属性c上
    __webpack_require__.c = installedModules;
  // define getter function for harmony exports
  // 将js模块里面暴露的属性挂载在 module.exports 对象上,主要是给es模块用的
    __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
  // es模块定义 __esModule 属性,用来标志 es模块 还是 commonjs模块
    __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
  // 获取默认导出,es模块是根据 __webpack_require__.d 定义的属性 __esModule 判断,如果true 则返回 export.default 属性值
  // 如果 __esModule 不为true 则返回当前模块
    __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/js/index.js");
})
/************************************************************************/
({

/***/ "./src/js/cjs.js":
/*!***********************!*\
  !*** ./src/js/cjs.js ***!
  \***********************/
/*! no static exports found */
/***/ (function(module, exports) {

eval("const a = 1;\nconst b = 2;\n\nfunction fn1(a) {\n  console.log('fn1 in cjs: ', a);\n} // module.exports = {\n//   a, b, fn1\n// }\n\n\nexports.a = a;\n\n//# sourceURL=webpack:///./src/js/cjs.js?");

/***/ }),

/***/ "./src/js/ejs.js":
/*!***********************!*\
  !*** ./src/js/ejs.js ***!
  \***********************/
/*! exports provided: default, a, b */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return a; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return b; });\nconst a = 12;\nconst b = {\n  a: 1,\n  b: 2\n};\n\nfunction fn1(a) {\n  console.log('fn1 in ejs: ', a);\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (fn1);\n\n\n//# sourceURL=webpack:///./src/js/ejs.js?");

/***/ }),

/***/ "./src/js/index.js":
/*!*************************!*\
  !*** ./src/js/index.js ***!
  \*************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ejs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ejs */ \"./src/js/ejs.js\");\n/* harmony import */ var _cjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cjs */ \"./src/js/cjs.js\");\n/* harmony import */ var _cjs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cjs__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nconst requireCjs = __webpack_require__(/*! ./cjs */ \"./src/js/cjs.js\");\n\nconst requireEjs = __webpack_require__(/*! ./ejs */ \"./src/js/ejs.js\");\n\nconsole.log('cjs: ', _cjs__WEBPACK_IMPORTED_MODULE_1___default.a);\nconsole.log('ejs: ', _ejs__WEBPACK_IMPORTED_MODULE_0__);\nconsole.log('requireCjs: ', requireCjs);\nconsole.log('requireEjs: ', requireEjs);\n\n//# sourceURL=webpack:///./src/js/index.js?");

/***/ })

});
View Code

3. 仔细看下生成之后的 index.js:

/* 
  每个文件打包之后生成的模块,默认都会传入 module, module.exports, __webpack_require__ 这三个参数
  这三个参数是在 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__) 这里传递的
*/

/* 通过 __webpack_require__.r 标志该文件为 ECMAScript 模块*/
__webpack_require__.r(__webpack_exports__);

/* 通过 __webpack_require__ 引入模块对应的模块 */
/* harmony import */ var _ejs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ejs */ "./src/js/ejs.js");
/* harmony import */ var _cjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cjs */ "./src/js/cjs.js");

/* 获取模块的默认导出,根据 module.__esModule 兼容 ECMAScript 跟 CommonJs*/
/* harmony import */ var _cjs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cjs__WEBPACK_IMPORTED_MODULE_1__);



const requireCjs = __webpack_require__(/*! ./cjs */ "./src/js/cjs.js");

const requireEjs = __webpack_require__(/*! ./ejs */ "./src/js/ejs.js");

console.log('cjs: ', _cjs__WEBPACK_IMPORTED_MODULE_1__);
console.log('ejs: ', _ejs__WEBPACK_IMPORTED_MODULE_0__);
console.log('requireCjs: ', requireCjs);
console.log('requireEjs: ', requireEjs);
View Code

4. 以上可以看出,webpack 对于 CommonJS 跟 ECMAScript 打包是做了兼容的,对于模块暴露的属性,都是统一放在 module.exports 这个属性里面,如果是 ECMAScript 的 export default, 则会放在 module.exports['default'] 这个属性里面,其他的如 export 或者 CommonJs 的 exports, module.exports 都是放在 module.exports 对于对象里面

猜你喜欢

转载自www.cnblogs.com/l-c-blog/p/12089211.html