Maison > interface Web > js tutoriel > le corps du texte

Explication détaillée du module webpack et des nouvelles fonctionnalités de webpack3

小云云
Libérer: 2018-02-09 13:30:29
original
1512 Les gens l'ont consulté

Cet article commence par un exemple simple et analyse les trois questions suivantes à partir du fichier packagé : À quoi ressemble le fichier packagé du webpack ? Comment atteindre la compatibilité avec les principales solutions modulaires ? Quelles sont les nouveautés apportées par webpack3 ? Webpack est un puissant outil d'empaquetage de modules qui est excellent dans la gestion des dépendances et des modules. Cet article part de l'analyse des fichiers bundle.js pour explorer les mécanismes de chargement de différentes solutions de modules, pour comprendre initialement webpack et développer les fonctionnalités de webpack3. .

Un exemple simple

Configuration du webpack

 // webpack.config.js
module.exports = {
 entry: './src/index.js',
 output: {
 filename: 'bundle.js',
 path: path.resolve(__dirname, 'dist')
 },
};
Copier après la connexion

Fichier js simple

 // src/index.js
 console.log('hello world');
Copier après la connexion

Code packagé du Webpack

Quand vous regardez là-dessus, penserez-vous, je n'ai qu'une seule ligne de code, et vous en emballez tellement pour moi ? ? ? (Point d'interrogation noir)

// dist/bundle.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, {
/******/     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) {
console.log('hello world');
/***/ })
/******/ ]);
Copier après la connexion

Analysons cette partie du code et simplifions-la d'abord. En fait, le tout est une fonction auto-exécutable, puis passons dans un tableau de modules

<.>
 (function(modules) { 
  //...
 })([function(module, exports) {
  //..
 }])
Copier après la connexion
D'accord, que fait-on en passant dans le tableau de modules (en fait les commentaires sont très évidents, je viens de le traduire grossièrement)

 /******/ (function(modules) { // webpackBootstrap
/******/  // The module cache 缓存已经load过的模块
/******/  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, //模块id
/******/    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 为ES6 exports定义getter
/******/  __webpack_require__.d = function(exports, name, getter) {
/******/   if(!__webpack_require__.o(exports, name)) { // 假如exports本身不含有name这个属性
/******/    Object.defineProperty(exports, name, {
/******/     configurable: false,
/******/     enumerable: true,
/******/     get: getter
/******/    });
/******/   }
/******/  };
/******/
/******/  // getDefaultExport function for compatibility with non-harmony modules 解决ES module和Common js module的冲突,ES则返回module['default']
/******/  __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配置下的公共路径
/******/  __webpack_require__.p = "";
/******/
/******/  // Load entry module and return exports 最后执行entry模块并且返回它的暴露内容
/******/  return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
console.log('hello world');
/***/ })
/******/ ]);
Copier après la connexion
Quel est le processus global ?

  • Réussi Entrez le tableau de modules

  • Appelez __webpack_require__(__webpack_require__.s = 0)

pour construire l'objet module et mettez-le dans le cache

Appelez le module, en passant les paramètres correspondants modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); fonction)

marque que l'objet module a été chargé

Renvoie le contenu exposé par le module (notez que module.exports est transmis à la fonction ci-dessus et que la référence peut être modifiée)

  • La fonction du module est transmise dans le module, module exports, __webpack_require__

  • Pendant le processus d'exécution, l'exposition et la référence des variables sont complétées en modifiant le. références des trois ci-dessus

Quel est le mécanisme du module webpack

Nous pouvons aller sur le site officiel pour jeter un œil au module webpack

doc.webpack-china.org/concepts/mo…

Les modules Webpack peuvent exprimer leurs dépendances de différentes manières, quelques exemples sont les suivants :

  • ES2015 instruction d'importation

  • Instruction CommonJS require()

  • AMD définit et requiert les instructions

  • @import instructions dans les fichiers css/sass/less.

  • Style (url(...)) ou lien image (url de l'image) dans un fichier HTML ()

Module webpack puissant C'est compatible avec diverses solutions modulaires et sans opinion

Nous pouvons écrire un autre exemple pour le découvrir

CommonJS

Modifier src/index.js

var cj = require('./cj.js');
console.log('hello world');
cj();
Copier après la connexion
Ajoutez src/cj.js et gardez tout le reste inchangé par rapport à l'exemple précédent

// src/cj.js
function a() {
 console.log("CommonJS");
}
module.exports = a;
Copier après la connexion
Exécutez à nouveau webpack

/******/ (function(modules) { // webpackBootstrap
 //... 省略代码
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
let cj = __webpack_require__(1);
console.log('hello world');
cj();
/***/ }),
/* 1 */
/***/ (function(module, exports) {
function a() {
 console.log("CommonJS");
}
module.exports = a;
/***/ })
/******/ ]);
Copier après la connexion
Nous pouvons voir le tableau de modules Il y a plus de fichiers importés, puis la fonction du module index.js a un paramètre supplémentaire __webpack_require__ pour référencer le fichier (__webpack_require__ a été introduit dans la section précédente. Dans l'ensemble, le module dépendant modifie module.exports, puis le module principal exécute Dépend du module et obtient les exportations).

Import ES2015

Ajouter src/es.js

// src/es.js
export default function b() {
 console.log('ES Modules');
}
Copier après la connexion
Modifier src/index.js

// src/index.js
import es from './es.js';
console.log('hello world');
es();
webpack.config.js不变,执行webpack
/******/ (function(modules) { // webpackBootstrap
// ... 省略代码
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__es_js__ = __webpack_require__(1);
console.log('hello world');
Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["a" /* default */])();
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = b;
function b() {
 console.log('ES Modules');
}
/***/ })
/******/ ]);
Copier après la connexion
On voit qu'ils ont tout devient mode strict. Les performances de

automatiquement adoptées par webpack sont en fait similaires à celles de CommonJS Il passe également en export puis le modifie dans le module principal,

. On voit ça

Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
Copier après la connexion
A quoi ça sert ? En fait, il s'agit de marquer les exports actuels comme un module es. Vous souvenez-vous encore du précédent __webpack_require__.n ? Retirons-le et jetons un coup d'œil

/******/  // getDefaultExport function for compatibility with non-harmony modules 解决ES module和Common js module的冲突,ES则返回module['default']
/******/  __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;
/******/  };
Copier après la connexion
afin d'éviter les conflits avec les non-. Des modules ES ? Où est le conflit ?

En fait, vous connaîtrez cette partie si vous voyez le code source de babel convertissant les modules ES. Afin d'être compatibles avec le module, les modules ES seront directement accrochés sur exports.default, puis sur __esModule. L'attribut sera ajouté, et il sera jugé une fois lors de son introduction. S'il s'agit d'un module de conversion, si c'est le cas, introduisez le module['default'], sinon, introduisez le module

Introduisons-en quelques autres. Modules ES pour voir l'effet

// src/es.js
export function es() {
 console.log('ES Modules');
}
export function esTwo() {
 console.log('ES Modules Two');
}
export function esThree() {
 console.log('ES Modules Three');
}
export function esFour() {
 console.log('ES Modules Four');
}
Copier après la connexion
Introduisons plus d'esTwo et d'esFour, mais sans utiliser esFour

// src/index.js
import { es, esTwo, esFour} from './es.js';
console.log('hello world');
es();
esTwo();
Copier après la connexion
, nous obtenons

/******/ (function(modules) { // webpackBootstrap
// ...
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__es_js__ = __webpack_require__(1);
console.log('hello world');
Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["a" /* es */])();
Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["b" /* esTwo */])();
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = es;
/* harmony export (immutable) */ __webpack_exports__["b"] = esTwo;
/* unused harmony export esThree */
/* unused harmony export esFour */
function es() {
 console.log('ES Modules');
}
function esTwo() {
 console.log('ES Modules Two');
}
function esThree() {
 console.log('ES Modules Three');
}
function esFour() {
 console.log('ES Modules Four');
}
/***/ })
/******/ ]);
Copier après la connexion
Eh bien, c'est en fait le même qu'avant. Quel est le point clé dans cet exemple ? Avez-vous remarqué dans les commentaires

/* unused harmony export esThree */
/* unused harmony export esFour */
Copier après la connexion
esThree est un module que nous n'avons pas présenté, esFour est un module que nous avons référencé mais non utilisé, et webpack les a marqués comme inutilisés. En fait, si vous utilisez le plug-in webpack uglify, via la marque, cela éliminera les deux codes inutilisés esThree et esFour (en fait, c'est un tremblement d'arbre)

AMD.

Voyons comment Webpack prend en charge AMD

Nouvel ajout src/amd.js

// src/amd.js
define([
],function(){
 return {
  amd:function(){
   console.log('AMD');
  }
 };
});
Copier après la connexion
Modifier index.js

// src/index.js
define([
 './amd.js'
],function(amdModule){
 amdModule.amd();
});
Copier après la connexion
pour obtenir

/******/ (function(modules) { // webpackBootstrap
// ... 省略代码
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
 __webpack_require__(1)
], __WEBPACK_AMD_DEFINE_RESULT__ = function(amdModule){
 amdModule.amd();
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
    __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
], __WEBPACK_AMD_DEFINE_RESULT__ = function(){
 return {
  amd:function(){
   console.log('AMD');
  }
 };
}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
    __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ })
/******/ ]);
Copier après la connexion
Regardez d'abord amd.js pour trier le code

function(module, exports, __webpack_require__) {
 var __WEBPACK_AMD_DEFINE_ARRAY__,
  __WEBPACK_AMD_DEFINE_RESULT__;
 !(
  __WEBPACK_AMD_DEFINE_ARRAY__ = [],
  __WEBPACK_AMD_DEFINE_RESULT__ = function() {
   return {
    amd: function() {
     console.log('AMD');
    }
   };
  }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  __WEBPACK_AMD_DEFINE_RESULT__ !== undefined &&
  (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)
 );
})
Copier après la connexion
Pour faire simple, collectez Define Array et mettez-le dans la fonction de retour, et obtenez le dépendances selon les paramètres

s'appliquent pour démonter le tableau en paramètres un par un

Regardez à nouveau la partie module index.js

function(module, exports, __webpack_require__) {
 var __WEBPACK_AMD_DEFINE_ARRAY__,
  __WEBPACK_AMD_DEFINE_RESULT__;
 !(
  __WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)],
  __WEBPACK_AMD_DEFINE_RESULT__ = function(amdModule) {
    amdModule.amd();
  }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && 
  (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)
 );
}
Copier après la connexion
En fait, il introduit {amd : [Fonction : amd]>

css/image exposé par amd.js ?

css et image peuvent également devenir un module webpack, c'est choquant, il ne peut pas être simplement appelé via un moyen ordinaire hack commonjs ou appel de fonction, c'est n'importe quoi pour JS, il doit utiliser le chargeur webpack pour réaliser

像css就是转换成一段js代码,通过处理,调用时就是可以用js将这段css插入到style中,image也类似,这部分就不详细阐述了,有兴趣的读者可以深入去研究

webpack3新特性

我们可以再顺便看下webpack3新特性的表现

具体可以看这里medium.com/webpack/web…

Scope Hoisting

我们可以发现模块数组是一个一个独立的函数然后闭包引用webpack主函数的相应内容,每个模块都是独立的,然后带来的结果是在浏览器中执行速度变慢,然后webpack3学习了Closure Compiler和RollupJS这两个工具,连接所有闭包到一个闭包里,放入一个函数,让执行速度更快,并且整体代码体积也会有所缩小

我们可以实际看一下效果(要注意的是这个特性只支持ES Modules,是不支持CommonJs和AMD的)

使用上面的例子,配置webpack.config.js,增加new webpack.optimize.ModuleConcatenationPlugin()

const path = require('path');
const webpack = require('webpack');
module.exports = {
 entry: './src/index.js',
 output: {
 filename: 'bundle.js',
 path: path.resolve(__dirname, 'dist')
 },
 module: {
 },
 plugins: [
 new webpack.optimize.ModuleConcatenationPlugin(),
 ]
};
Copier après la connexion

打包

/******/ (function(modules) { // webpackBootstrap
// ... 省略代码
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
// CONCATENATED MODULE: ./src/es.js
function es() {
 console.log('ES Modules');
}
function esTwo() {
 console.log('ES Modules Two');
}
function esThree() {
 console.log('ES Modules Three');
}
function esFour() {
 console.log('ES Modules Four');
}
// CONCATENATED MODULE: ./src/index.js
// src/index.js
console.log('hello world');
es();
/***/ })
/******/ ]);
Copier après la connexion

我们可以惊喜的发现没有什么require了,它们拼接成了一个函数,good!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal