What is the WebPack template code
After webPack wraps the project, we can see that our business code is wrapped in a piece of code. This piece of code is the Runtime code generated by WebPack, which I will refer to as webPack template code
Webpack does not generate files when code is cut
- Sample directory structure
.Heavy Exercises ── Heavy Exercises. Md heavy Exercises ─ distPackage the build file│ ├ ─ ─ 1. Js# src/chunk.js => 1.js│ ├ ─ ─ app. Js# src/index.js => app.js│ └ ─ ─ splitChunk. Js# src/splitChunk.js => splitChunk.js├── Package. json ├─ SRC │ ├─ chunk.js# Dynamically loaded chunk│ ├ ─ ─ index. Js# Non-code cutting entry file│ └ ─ ─ splitChunk. Js# code cut entry file├ ─ ─ webpack. Config. Js └ ─ ─ yarn. The lockCopy the code
- index.js
// index.js
console.log('app')
Copy the code
- File after build
; (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 && typeofvalue ! ='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 = 0))
})([
/* 0 */
function(module, exports) {
/* Here is the index.js package */
console.log('app')})Copy the code
- As you can see, the above code is mostly generated
__webpack_require__
Function related stuff,__webpack_require__
The webPack Runtime is the way to load internal modules - The generated code is the immediate execution function expression (IIFE). The immediate execution function’s call parameters are all the modules that WebPack processes, usually a file into a module. Modules can be an object or an array. The key value of the object is the module path or module ID, and the value is the specific code of the module. Is an array, the array subscript is the module ID
- You can see that the module is passed three arguments when it is loaded, namely
module
,exports
and__webpack_require__
The above code can be simplified as follows
; (function(modules) {
// Used to cache loaded modules
var installedModules = {}
// The method to load the module
function __webpack_require__(moduleId) {
// If the module exists in the cache, return it directly
if (installedModules[moduleId]) {
return installedModules[moduleId].exports
}
// Define a new module object and store it in the cache
var module = (installedModules[moduleId] = {
i: moduleId,
l: false.exports: {}})// Load the module
modules[moduleId].call(module.exports, module.module.exports, __webpack_require__)
// Module loading completion flag
module.l = true
// Returns the object exported by the module
return module.exports
}
// Load the entry module
return __webpack_require__(0)
})([
/* 0 */
function(module, exports) {
/* Here is the index.js package */
console.log('app')})Copy the code
Webpack has generated files when code is cut
- splitChunk.js
// splitChunk.js
import('./chunk').then(chunk= > {
chunk.default()
console.log('done')})Copy the code
- chunk.js
// chunk.js
export default() = > {console.log('I am chunk')}Copy the code
- After the build generated
splitChunk.js
file
; (function(modules) {
// webpackBootstrap
// install a JSONP callback for chunk loading
function webpackJsonpCallback(data) {
var chunkIds = data[0]
var moreModules = data[1]
// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId,
chunkId,
i = 0,
resolves = []
for (; i < chunkIds.length; i++) {
chunkId = chunkIds[i]
if (installedChunks[chunkId]) {
resolves.push(installedChunks[chunkId][0])
}
installedChunks[chunkId] = 0
}
for (moduleId in moreModules) {
if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId]
}
}
if (parentJsonpFunction) parentJsonpFunction(data)
while (resolves.length) {
resolves.shift()()
}
}
// The module cache
var installedModules = {}
// object to store loaded and loading chunks
// undefined = chunk not loaded, null = chunk preloaded/prefetched
// Promise = chunk loading, 0 = chunk loaded
var installedChunks = {
0: 0
}
// script path function
function jsonpScriptSrc(chunkId) {
return __webpack_require__.p + ' ' + ({}[chunkId] || chunkId) + '.js'
}
// 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
}
// This file contains only the entry chunk.
// The chunk loading function for additional chunks
__webpack_require__.e = function requireEnsure(chunkId) {
var promises = []
// JSONP chunk loading for javascript
var installedChunkData = installedChunks[chunkId]
if(installedChunkData ! = =0) {
// 0 means "already installed".
// a Promise means "currently loading".
if (installedChunkData) {
promises.push(installedChunkData[2])}else {
// setup Promise in chunk cache
var promise = new Promise(function(resolve, reject) {
installedChunkData = installedChunks[chunkId] = [resolve, reject]
})
promises.push((installedChunkData[2] = promise))
// start chunk loading
var script = document.createElement('script')
var onScriptComplete
script.charset = 'utf-8'
script.timeout = 120
if (__webpack_require__.nc) {
script.setAttribute('nonce', __webpack_require__.nc)
}
script.src = jsonpScriptSrc(chunkId)
// create error before stack unwound to get useful stacktrace later
var error = new Error()
onScriptComplete = function(event) {
// avoid mem leaks in IE.
script.onerror = script.onload = null
clearTimeout(timeout)
var chunk = installedChunks[chunkId]
if(chunk ! = =0) {
if (chunk) {
var errorType = event && (event.type === 'load' ? 'missing' : event.type)
var realSrc = event && event.target && event.target.src
error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ':' + realSrc + ') '
error.name = 'ChunkLoadError'
error.type = errorType
error.request = realSrc
chunk[1](error)
}
installedChunks[chunkId] = undefined}}var timeout = setTimeout(function() {
onScriptComplete({ type: 'timeout'.target: script })
}, 120000)
script.onerror = script.onload = onScriptComplete
document.head.appendChild(script)
}
}
return Promise.all(promises)
}
// 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 && typeofvalue ! ='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 = ' '
// on error function for async loading
__webpack_require__.oe = function(err) {
console.error(err)
throw err
}
var jsonpArray = (window['webpackJsonp'] = window['webpackJsonp'] | | [])var oldJsonpFunction = jsonpArray.push.bind(jsonpArray)
jsonpArray.push = webpackJsonpCallback
jsonpArray = jsonpArray.slice()
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i])
var parentJsonpFunction = oldJsonpFunction
// Load entry module and return exports
return __webpack_require__((__webpack_require__.s = 0))
})([
/* 0 */
function(module, exports, __webpack_require__) {
__webpack_require__
.e(1)
.then(__webpack_require__.bind(null.1))
.then(chunk= > {
chunk.default()
console.log('done')})})Copy the code
- With no previous code cut, the main is much more
webpackJsonpCallback
and__webpack_require__.e
function - The simplified code is as follows
; (function(modules) {
// the callback executes after the js is loaded
// A chunk clock can contain many modules
function webpackJsonpCallback(data) {}
// Chunk that has been loaded
// a chunk value of 0 indicates that the chunk has been loaded
var installedChunks = {
0: 0
}
/ / the require module
function __webpack_require__(moduleId) {}
// Load the js file and insert the script tag
__webpack_require__.e = function requireEnsure(chunkId) {}
// Read modules already in webpackJsonp for use in code
var jsonpArray = (window['webpackJsonp'] = window['webpackJsonp'] | | [])var oldJsonpFunction = jsonpArray.push.bind(jsonpArray)
// Change the push method to a callback for this module
jsonpArray.push = webpackJsonpCallback
jsonpArray = jsonpArray.slice()
for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i])
var parentJsonpFunction = oldJsonpFunction
return __webpack_require__((__webpack_require__.s = 0))
})([
/* 0 */
function(module, exports, __webpack_require__) {
__webpack_require__
.e(1) // Insert the asynchronous JS script tag
// The webPackJsonP.push method is automatically executed after the loaded JS is successfully loaded
// Register the module with modules
// Load the module
.then(__webpack_require__.bind(null.1))
.then(chunk= > {
chunk.default()
console.log('done')})})Copy the code
- After packaging
1.js
content
; (window['webpackJsonp'] = window['webpackJsonp'] || []).push([
[1], [,/* 0 */
/ * 1 * /
function(module, __webpack_exports__, __webpack_require__) {
'use strict'
__webpack_require__.r(__webpack_exports__)
__webpack_exports__['default'] = (a)= > {
console.log('I am chunk'}}]])Copy the code
- Code cut after different file sharing modules are implemented through global variables
webpackJsonp
To implement the - After the asynchronous JS file is loaded successfully, the execution code will be stopped, and the execution code is
window['webpackJsonp'].push
Method, the actual function executed issplitChunk.js
In thewebpackJsonpCallback
methods - The simple execution process is as follows
Extract the WebPack Runtime to a separate file
Set webpack configuration optimization. RuntimeChunk is true, then the webpack generated template files into a separate file, all other files will be in the form of separation for the json file
Implement a simple Webpack module loading function
The __webpack_require__ and window[‘webpackJsonp’].push methods are implemented in webpack-require
- index.js
; (function(modules) {
// Cache modules already required
const installedModules = {}
// Load the module
function __webpack_require__(id) {
if (installedModules[id]) {
return installedModules[id].exports
}
const module = (installedModules[id] = {
loaded: false.exports: {}
})
modules[id].call(module.exports, module.module.exports, __webpack_require__)
// Indicate that the module has been loaded
module.loaded = true
return module.exports
}
// Cache the chunk that has been loaded
const installedChunks = {}
// Callback executed after the js chunk file is successfully loaded
function webpackJsonpCallback(data) {
// Name of chunk that exists in the js file
const chunkIds = data[0]
// Module exported from chunk
const moreModules = data[1]
const resolves = []
// Let all chunks contained in a js file complete loading
// A single js file may contain multiple pre-packaged files
for (i = 0; i < chunkIds.length; i++) {
const chunkId = chunkIds[i]
if (installedChunks[chunkId]) {
resolves.push(installedChunks[chunkId][0])
}
installedChunks[chunkId] = 0
}
// Copy the modules in chunk
for (let moduleId in moreModules) {
if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId]
}
}
// let __webpack_require__.e execute the returned promise all resolve
while (resolves.length) {
resolves.shift()()
}
}
// Load modules that already exist in window.webPackjsonp
const jsonpArray = (window.webpackJsonp = window.webpackJsonp || [])
jsonpArray.push = webpackJsonpCallback
for (let i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i])
// Insert the script tag
__webpack_require__.e = function(chunkId) {
const promises = []
let installedChunkData = installedChunks[chunkId]
// If it has been cached, return it directly
if (installedChunkData === 0) return Promise.all(promises)
if (installedChunkData) {
// The loading condition
promises.push(installedChunkData[2])}else {
// New load
const promise = new Promise((resolve, reject) = > {
installedChunkData = installedChunks[chunkId] = [resolve, reject]
})
installedChunkData[2] = promise
promises.push(promise)
const script = document.createElement('script')
// Convert to url according to chunkId
const chunksSrc = {
'./chunk.js': './chunk.js'.'./chunks-1.js': './chunks.js'.'./chunks-2.js': './chunks.js'
}
script.src = chunksSrc[chunkId]
// js complete loading event
onScriptComplete = function(event) {
clearTimeout(timeout)
// Avoid IE memory leaks
script.onerror = script.onload = null
// The load failed when the chunk was not completed
const chunk = installedChunks[chunkId]
if(chunk ! = =0) {
if (chunk) {
chunk[1] (`${chunkId}Load failed ')
}
installedChunks[chunkId] = undefined
}
}
script.onerror = script.onload = onScriptComplete
// Set timeout
const timeout = setTimeout((a)= > onScriptComplete(), 120000)
document.head.appendChild(script)
}
return Promise.all(promises)
}
// Load the entry file
return __webpack_require__('./index.js') ({})'./index.js': function(module, exports, __webpack_require__) {
console.log('I am index.js')
/ / load. / the chunk. Js
__webpack_require__
.e('./chunk.js')
.then((a)= > __webpack_require__('./chunk.js'))
.then(data= > {
data.default()
})
/ / load. / chunks - 1. Js
__webpack_require__
.e('./chunks-1.js')
.then((a)= > __webpack_require__('./chunks-1.js'))
.then(data= > {
data.default()
})
/ / load. / chunks - 2. Js
__webpack_require__
.e('./chunks-2.js')
.then((a)= > __webpack_require__('./chunks-2.js'))
.then(data= > {
data.default()
})
}
})
Copy the code
- chunk.js
; (window['webpackJsonp'] = window['webpackJsonp'] || []).push([
['./chunk.js'] and {'./chunk.js': function(module, __webpack_exports__, __webpack_require__) {
'use strict'
__webpack_exports__['default'] = (a)= > {
console.log('I am chunk'}}}])Copy the code
- chunks.js
// A file contains multiple chunks; (window['webpackJsonp'] = window['webpackJsonp'] || []).push([
['./chunks-1.js'.'./chunks-2.js'] and {'./chunks-1.js': function(module, __webpack_exports__, __webpack_require__) {
'use strict'
__webpack_exports__['default'] = (a)= > {
console.log('I am chunks-1')}},'./chunks-2.js': function(module, __webpack_exports__, __webpack_require__) {
'use strict'
__webpack_exports__['default'] = (a)= > {
console.log('I am chunks-2'}}}])Copy the code
link
This article is simultaneously posted to Github, and the sample code is available on Github
- Webpack principles series of articles
- Webpack principles – Start with front-end modularity