Изучение модульной реализации webpack

Webpack ECMAScript 6

предисловие

Все мы знаем, что браузеры не могут распознавать модули спецификации commonjs и модули es6. Преобразование этих стандартизированных модулей в операторы, распознаваемые браузером, — это самое основное, что делает Webpack.Сам Webpack поддерживает модульную систему, которая совместима со всеми спецификациями модулей в рамках исторического процесса внешнего интерфейса, включая amd commonjs es6 и так далее. Конечно, у babel тоже есть возможность конвертировать es6-модули (посылку я не хочу упоминать), но поскольку у webpack есть функция tree-shaking, у него больше преимуществ, чем у babel. Поэтому модульная функция babel обычно запрещена в конфигурации babel. (["es2015", {"модули": ложь}]).

спецификация commonjs

Структура проекта:

  1. app.js (запись):
var c = require('./c')
console.log(c)
  1. c.js (запись):
let c1 = 'c1'
let c2 = 'c2'
module.exports = {
	c1,
	c2,
}

Результат упаковки:

(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["app"] = factory();
	else
		root["app"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return  (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, {
 				configurable: false,
 				enumerable: true,
 				get: getter
 			});
 		}
 	};

 	// 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 = 0);
 })
/************************************************************************/
 ([
/* 0 */
 (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__(1);


 }),
/* 1 */
 (function(module, exports, __webpack_require__) {

"use strict";

var c = __webpack_require__(2);
console.log(c);

module.exports = {
	a: '我是a'
};

 }),
/* 2 */
 (function(module, exports) {

var c1 = 'c1';
var c2 = 'c2';
module.exports = {
	c1: c1,
	c2: c2
};

 })
 ]);
});

Разобрать:

Сгенерированный пакет представляет собой функцию немедленного выполнения, которую можно упростить, написав

(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["app"] = factory();
	else
		root["app"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {解析完的模块部分})

Видно, что модульная часть передается в webpackUniversalModuleDefinition в качестве заводского параметра.Если обнаружено, что модуль module.exports определен, модуль назначается на module.exports, если обнаружено, что модульная система amd определена, он назначается системе модулей определения, наконец, если ни одна из вышеперечисленных систем модулей не обнаружена, назначьте ее глобальной переменной, определенной в webpack.output.library. Браузер может получить проанализированный модуль через window.app.

См. раздел анализа модуля ниже.

фабрика:

function(){
    return (function(modules){
        解析模块的方法
    })([function(){模块1},function(){模块1},...])
}

Последнее, что возвращает фабричный метод, — это значение, предоставляемое js:app.js записи веб-пакета.

Методы разбора модулей:

var installedModules = {};
function __webpack_require__(moduleId) {
	if(installedModules[moduleId]) {
		return installedModules[moduleId].exports;
	}
	var module = installedModules[moduleId] = {
		i: moduleId,
		l: false,
		exports: {}
	};
	modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
	module.l = true;
	return module.exports;
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.d = function(exports, name, getter) {
	if(!__webpack_require__.o(exports, name)) {
		Object.defineProperty(exports, name, {
			configurable: false,
			enumerable: true,
			get: getter
		});
	}
};
__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;
};
__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
__webpack_require__.p = "";
return __webpack_require__(__webpack_require__.s = 0);
  1. Определено InstalledModules, эта переменная используется для кэширования загруженных модулей.

  2. Функция __webpack_require__ определена, а параметром функции является идентификатор модуля. Эта функция используется для реализации требования модуля.

  3. webpack_requireФункция сначала проверяет, кэширован ли загруженный модуль, и если да, то напрямую возвращает экспорт кэшированного модуля.

  4. Если кеша нет, то есть он загружается в первый раз, модуль инициализируется первым, а модуль кешируется. Инициализировать ->

    {
    	i: moduleId,
    	l: false,
    	exports: {}
    }
    
  5. Затем вызовите функцию модуля, которая является функцией-оболочкой предыдущего веб-пакета для нашего модуля, передав в качестве параметров module, module.exports и __webpack_require__. Обратите внимание, что здесь выполняется динамическая привязка, а вызывающий объект функции модуля привязывается как module.exports, что гарантирует, что this в модуле указывает на текущий модуль.

  6. После завершения вызова модуль помечается как загруженный.

  7. Возвращает содержимое экспорта модуля.

  8. Используя определенную ранее функцию __webpack_require__, запросите 0-й модуль, который является входным модулем.

https://segmentfault.com/a/1190000010349749

Посмотрите еще раз на модуль с номером 0

function(module, exports, __webpack_require__) {
    module.exports = __webpack_require__(1);
}

прямо пусть expoprts =webpack_require(1), в это время

installedModules[0] = {i: 1, l: true, exports: __webpack_require__(1)}

Посмотрите еще раз на модуль №1

function(module, exports, __webpack_require__) {
    "use strict";
    var c = __webpack_require__(2);
    console.log(c);
    module.exports = {
    	a: '我是a'
    }
}

Пусть module.exports = {a: 'I am a'} напрямую, в это время:

installedModules[1] = {i: 1, l: true, exports: {a:'我是a'}}

Посмотрите еще раз на модуль №2

function(module, exports) {
    var c1 = 'c1';
    var c2 = 'c2';
    module.exports = {
    	c1: c1,
    	c2: c2
    };
}

Пусть module.exports = {c1: 'c1', c2: 'c2'} напрямую, потому что модуль 2 не требует других модулей, поэтому __webpack_require__ не получен. В настоящее время:

installedModules[2] = {i: 2, l: true, exports: {c1: 'c1',c2: 'c2'}}

Конец, результат установленныхModules сейчас

{
    0: {i: 0, l: true, exports: {a:'我是a'}}
    1: {i: 1, l: true, exports: {a:'我是a'}}
    2: {i: 2, l: true, exports: {c1: 'c1',c2: 'c2'}}
}

Заводская функция для возвратаreturn __webpack_require__(__webpack_require__.s = 0);

Таким образом, модуль ввода: app.js возвращает {a: 'Я'}, а window.app = {a: 'Я'}

Вывод: webpack использует пользовательскую функцию __webpack_require__ для реализации функции commonjs require и использует переменную createdModules для сохранения вывода модуля из module.exports. Завершена конвертация модуля commonjs.

Принцип модуляризации webpack-commonjs

es6 module

Структура проекта:

  1. app.js (запись):
import c,{c1,c2} from './c';

console.log(c,c1,c2)

export default '我是a';
export let a = '我是aa';
  1. с.js:
import b from './b'
console.log(b)

export let c1 = '我是c111'
export let c2 = '我是c222'

export default '我是c';
  1. b.js:
export default 'bbb';

Результат упаковки:

В основном то же самое, что и часть commonjs, только часть модуля анализируется по-другому.

Модуль 0 такой же, как и выше. Давайте посмотрим на модуль под номером 1 (app.js)

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
    __webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });
    var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);

    console.log(__WEBPACK_IMPORTED_MODULE_0__c__["c" /* default */], __WEBPACK_IMPORTED_MODULE_0__c__["a" /* c1 */], __WEBPACK_IMPORTED_MODULE_0__c__["b" /* c2 */]);

    __webpack_exports__["default"] = ('我是a');
    var aaaa = '我是aaaa';

В заключение:

  1. Поскольку app.js является модулем es6, webpack добавляет к этому модулю атрибут __esModule (true).

  2. Поскольку модуль es6 имеет функцию экспорта по умолчанию, webpack назначает атрибут по умолчанию, предоставляемый этим модулем, атрибуту по умолчанию module.exports.

  3. Примечание. Только если модуль является модулем ввода и модулем es6, значение по умолчанию для экспорта модуля будет преобразовано в свойство по умолчанию для module.exports.

  4. Переменные, отображаемые при экспорте, преобразуются в__webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });, можно обнаружить, что имя переменной aaaa, отображаемое при экспорте, изначально выводится.

  5. Оператор импорта превращается вvar __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);, видно, что веб-пакет оператора import c,{c1,c2} не обрабатывает, а напрямую получает объект экспорта модуля c через новую переменную __WEBPACK_IMPORTED_MODULE_0__c__. Все места, где используются c, c1 и c2, взяты из __WEBPACK_IMPORTED_MODULE_0__c__.

В настоящее время:

installedModules[1] = {
    i: 1,
    l: true,
    exports: {
        default:'我是a',
        aaaa:"我是aaaa",
        __esModule:true
    }
}

Посмотрите еще раз на модуль 2 (c.js):

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_require__.d(__webpack_exports__, "a", function() { return c1; });
    __webpack_require__.d(__webpack_exports__, "b", function() { return c2; });
    var __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(3);

    console.log(__WEBPACK_IMPORTED_MODULE_0__b__["a" /* default */]);

    var c1 = '我是c111';
    var c2 = '我是c222';

    __webpack_exports__["c"] = ('我是c');
}

В заключение:

  1. Переменные, отображаемые при экспорте, преобразуются в__webpack_require__.d(__webpack_exports__, "a", function() { return c1; });, можно обнаружить, что отличие от модуля es6 записи состоит в том, что имена переменных, отображаемые при экспорте, были изменены случайным образом. по умолчанию преобразуется в c, c1 преобразуется в a, c2 преобразуется в b. Поэтому, когда модуль входа (app.js) импортирует этот модуль и использует атрибуты по умолчанию, c1, c2, соответствующие изменяются на c, a, b вебпаком (см. где вызывается модуль 1)

  2. В отличие от модуля ввода, экспорт по умолчанию этого модуля преобразуется в__webpack_exports__["c"] = ('我是c');, не преобразуется в атрибут по умолчанию, но также преобразуется в случайное имя атрибута.

В настоящее время:

installedModules[2] = {
    i: 2,
    l: true,
    exports: {
        a:"我是c111",
        b:"我是c222",
        c: "我是c"
    }
}

Посмотрите на модуль 3 еще раз

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_exports__["a"] = ('bbb');
}

В заключение:

Экспорт по умолчанию модуля 3 преобразуется в __webpack_exports__["a"] = ('bbb'); значение по умолчанию изменяется случайным образом на a, а затем значение ['a'] также используется там, где оно вызывается.

Таким образом, установленные модули:

{
    0: {i: 0, l: true, exports: {a:'我是a',_esModule:true}}
    1: {i: 1, l: true, exports: {a:'我是a',_esModule:true}}
    2: {i: 2, l: true, exports: {a:"我是c111", b:"我是c222",c: "我是c"}}
    3: {i: 3, l: true, exports: {a:"bbb"}}
}

В заключение:

  1. Если входной модуль является модулем es6, будет добавлен __esModule со значением true, указывающим, что это модуль es. И другие модули es6, на которые ссылается импортированный модуль es6, не будут добавлены с атрибутом __esModule.

  2. Когда модуль es6 используется в качестве модуля ввода, атрибут по умолчанию и другие имена атрибутов, которые экспортируются, будут сохранены как есть. Атрибут по умолчанию передается__webpack_exports__["default"] = ...способ экспорта, другие свойства через__webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });способ экспорта.

  3. Когда модуль es6 не является модулем входа, но на него ссылаются другие модули es6, атрибуту по умолчанию и другим экспортируемым именам атрибутов будут случайным образом назначены новые имена атрибутов, напримерexport default '我是c';повернулся к__webpack_exports__["c"] = ('我是c');. Атрибут по умолчанию также проходит__webpack_exports__["c"] = ...способ экспорта, другие свойства также передаются через__webpack_require__.d(__webpack_exports__, "b", function() { return c2; });способ экспорта.

  4. Синтаксис импорта модулей es6 преобразуется вvar __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(3);.

модули commonjs, смешанные с модулями es6

Сценарий 1: es6 ссылается на commonjs

Структура проекта:

  1. app.js (запись):
import c,{c1,c2} from './c';
console.log(c,c1,c2)

export default '我是a';
export let aaaa = '我是aaaa';
  1. с.js:
let c1 = 'c1'
let c2 = 'c2'
module.exports = {
	c1,
	c2,
}

Результат упаковки:

(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["app"] = factory();
	else
		root["app"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return  (function(modules) { // webpackBootstrap
 	var installedModules = {};
 	function __webpack_require__(moduleId) {
 		if(installedModules[moduleId]) {
 			return installedModules[moduleId].exports;
 		}
 		var module = installedModules[moduleId] = {
 			i: moduleId,
 			l: false,
 			exports: {}
 		};
 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
 		module.l = true;
 		return module.exports;
 	}
 	__webpack_require__.m = modules;
 	__webpack_require__.c = installedModules;
 	__webpack_require__.d = function(exports, name, getter) {
 		if(!__webpack_require__.o(exports, name)) {
 			Object.defineProperty(exports, name, {
 				configurable: false,
 				enumerable: true,
 				get: getter
 			});
 		}
 	};
 	__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;
 	};
 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
 	__webpack_require__.p = "";
 	return __webpack_require__(__webpack_require__.s = 0);
 })
/************************************************************************/
 ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__(1);


/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__c___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__c__);



console.log(__WEBPACK_IMPORTED_MODULE_0__c___default.a, __WEBPACK_IMPORTED_MODULE_0__c__["c1"], __WEBPACK_IMPORTED_MODULE_0__c__["c2"]);

/* harmony default export */ __webpack_exports__["default"] = ('我是a');
var aaaa = '我是aaaa';

/***/ }),
/* 2 */
/***/ (function(module, exports) {

var c1 = 'c1';
var c2 = 'c2';
module.exports = {
	c1: c1,
	c2: c2
};

/***/ })
/******/ ]);
});

Модуль ввода (app.js) — это модуль es6, а модуль, на который ссылаются (c.js), — это модуль commonjs.

Модуль 0 остается без изменений, см. упаковку модуля 1 (app.js)

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
    __webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });
    var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);
    var __WEBPACK_IMPORTED_MODULE_0__c___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__c__);

    console.log(__WEBPACK_IMPORTED_MODULE_0__c___default.a, __WEBPACK_IMPORTED_MODULE_0__c__["c1"], __WEBPACK_IMPORTED_MODULE_0__c__["c2"]);

    __webpack_exports__["default"] = ('我是a');
    var aaaa = '我是aaaa';
}

Можно обнаружить, что модуль 1 будет изменен на модуль COMMONJS.

var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);
// 与import es6模块相比增加了以下部分
var __WEBPACK_IMPORTED_MODULE_0__c___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__c__);

Когда ссылка на модуль найден модуль Commonjs, после вызова __WebPack_require __ (), __Webpack_require __. N также будет вызван,

__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;
};

Функция этого метода такова: если входящий модуль является модулем commonjs, преобразованным из модуля es6, то есть __esModule=true, то возвращается значение атрибута модуля по умолчанию.Если входящий модуль изначально является модулем commonjs , возвращается сам модуль. , и пусть свойство модуля = сам модуль. В результате создаются две переменные __WEBPACK_IMPORTED_MODULE_0__c__ и __WEBPACK_IMPORTED_MODULE_0__c___default.

__WEBPACK_IMPORTED_MODULE_0__c__={
	c1,
	c2,
}
__WEBPACK_IMPORTED_MODULE_0__c___default = function getModuleExports(){return module}
__WEBPACK_IMPORTED_MODULE_0__c___default.a = module

В заключение:

  1. Когда модуль es6 ссылается на модуль commonjs, поскольку имя импорта из «..» хочет получить атрибут модуля по умолчанию, а модуль commonjs не предоставляет метод по умолчанию, веб-пакет выводит весь модуль как значение атрибут по умолчанию.

Посмотрите еще раз на модуль 2:

function(module, __webpack_exports__) {
    "use strict";
    var c1 = 'c1';
    var c2 = 'c2';
    module.exports = {
    	c1: c1,
    	c2: c2
    };
}

вывод как есть

В итоге:

  1. es6 вызывает модуль commonjs, а случай импорта значения по умолчанию будет обработан специально

  2. Ссылочные модули commonjs выводятся как есть.

Сценарий 2: commonjs вызывает модуль es6

Структура проекта:

  1. app.js (запись):
var b = require('./b')
var c = require('./c')
console.log(b.default)
console.log(c)
module.exports = {
	a:'我是a'
}
  1. с.js:
import b from './b'
console.log(b)
export let c1 = '我是c111'
export let c2 = '我是c222'

export default '我是c';

Результат упаковки:

(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["app"] = factory();
	else
		root["app"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return  (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, {
 				configurable: false,
 				enumerable: true,
 				get: getter
 			});
 		}
 	};

 	// 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 = 0);
 })
/************************************************************************/
 ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(1);

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var b = __webpack_require__(2);
var c = __webpack_require__(3);
console.log(b.default);
console.log(c);
module.exports = {
	a: '我是a'
};

/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
__webpack_exports__["default"] = ('bbb');

/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
 __webpack_require__.d(__webpack_exports__, "c1", function() { return c1; });
 __webpack_require__.d(__webpack_exports__, "c2", function() { return c2; });

var __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(0);
console.log(__WEBPACK_IMPORTED_MODULE_0__b__["default"]);

var c1 = '我是c111';
var c2 = '我是c222';
/***/ })
/******/ ]);
});

Входной модуль (app.js) — это модуль commonjs, а упомянутые модули (b.js, c.js) — это модули es6.

Модуль 0 остается без изменений, см. упаковку модуля 1 (app.js)

function(module, exports, __webpack_require__) {
    "use strict";
    var b = __webpack_require__(2);
    var c = __webpack_require__(3);
    console.log(b.default);
    console.log(c);
    module.exports = {
    	a: '我是a'
    }
}

Просто используйте метод __webpack_require__, чтобы заменить исходный метод require

Посмотрите еще раз на модуль 2 (b.js) и модуль 3 (c.js).

b.js

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
    __webpack_exports__["default"] = ('bbb');
}

c.js

function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
    __webpack_require__.d(__webpack_exports__, "c1", function() { return c1; });
    __webpack_require__.d(__webpack_exports__, "c2", function() { return c2; });
    var c1 = '我是c111';
    var c2 = '我是c222';
    __webpack_exports__["default"] = ('我是c');
}

В заключение:

  1. Можно обнаружить, что модуль commonjs ссылается на модуль es6, и указанный модуль es6 будет добавлен с атрибутом __esModule (true)

  2. Синтаксис экспорта был преобразован в__webpack_require__.d(__webpack_exports__, "c1", function() { return c1; });.

  3. Оператор экспорта по умолчанию был преобразован в__webpack_exports__["default"] = ('我是c');

  4. Используйте импорт b из './b' для вызова модуля es6. Если вам нужно вызвать значение b по умолчанию, вам нужно использовать__WEBPACK_IMPORTED_MODULE_0__b__["default"];

  5. Чтобы вызвать модуль commonjs с импортом b из './b', необходимы следующие методы:

    var __WEBPACK_IMPORTED_MODULE_0__b__ = __webpack_require__(0);
    var __WEBPACK_IMPORTED_MODULE_0__b___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__b__);
    console.log(__WEBPACK_IMPORTED_MODULE_0__b___default.a);
    

В итоге:

  1. Когда модуль commonjs упакован, требуемая часть будет заменена функцией __webpack_require__, а остальные части будут выведены как есть.

  2. Когда модуль commonjs импортируется, поскольку модуль commonjs не предоставляет функцию значения по умолчанию, синтаксис значения импорта по умолчанию будет преобразован в:

    // import c from './c'被解析成:
    var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);
    var __WEBPACK_IMPORTED_MODULE_0__c___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__c__);
    // 使用c时被解析成:
    console.log(__WEBPACK_IMPORTED_MODULE_0__c___default.a)
    
  3. Даже если ссылка require() используется в модуле es6, независимо от того, является ли требование модулем es6 или модулем commonjs, оно будет просто проанализировано вvar c = __webpack_require__(2);. Можно считать, что требование спецификации commonjs будет напрямую заменено на __webpack_require__.

  4. Когда требуется модуль es6 (независимо от того, появляется ли инструкция require в модуле commonjs или es6), модуль es6 будет добавлен с __esModule=true. При импорте модуля es6 атрибут __esModule не добавляется. Когда модуль es6 используется в качестве модуля входа, он также будет добавлен с __esModule=true.Можно считать, что судьба модуля входа заключается в том, что он будет упакован как модуль commonjs и выставлен. переменная необходима, чтобы определить, что я раньше был модулем es6. Он просто вынужден стать модулем commonjs. После того, как пакет будет завершен, функция встряхивания дерева не будет запускаться при повторном обращении к этому модулю.

  5. Когда модуль es6 импортируется напрямую, будет запущена функция встряхивания дерева веб-пакета.Можно считать, что веб-пакет может вызывать встряхивание дерева только после статического анализа модуля es6.

  6. Когда модуль es6 упакован, оператор экспорта анализируется в:

    __webpack_require__.d(__webpack_exports__, "a", function() { return c1; });
    

    Оператор экспорта по умолчанию анализируется в:

    __webpack_exports__["c"] = ('我是c');
    

    Конечно, всем именам атрибутов назначаются новые имена случайным образом, как правило, в порядке a,b,c,d... .

    Исключение: если модуль es6 используется в качестве модуля ввода, имена свойств, предоставляемые операторами экспорта и экспорта по умолчанию, сохраняются, например:

    __webpack_require__.d(__webpack_exports__, "aaaa", function() { return aaaa; });
    __webpack_exports__["default"] = ('我是a');
    
  7. Когда модуль es6 импортируется, оператор импорта анализируется в:

    var __WEBPACK_IMPORTED_MODULE_0__c__ = __webpack_require__(2);
    

    Использование __webpack_require__.n не отображается.

    На этом этапе все атрибуты, предоставляемые при вызове модуля es6, проходят через метод __WEBPACK_IMPORTED_MODULE_0__c__['случайное имя атрибута'], например:

    console.log(__WEBPACK_IMPORTED_MODULE_0__c__["c" /* default */])
    
  8. Когда требуются модули es6, все намного проще:

    var c = __webpack_require__(2);
    

    Вызов любого свойства вызывается непосредственно через c.

Краткое описание:

import->__webpack_require__ 和 __webpack_require__.n((引用commonjs模块时出现))
require->__webpack_require__ 
export->__webpack_require__.d
export default->__webpack_exports__[".."]
module.exports->不变

Принцип модульности вебпака - модуль ES Подробное объяснение смешанного использования import, require, export и module.exports.

код проекта

Согласно приведенным выше идеям, если файл загружается по пути, можно написать простой модульный инструмент.