Skip to content

Runtime

Webpack Runtime 是一个 Webpack 的运行时环境,它包含了一些函数和变量,这些函数和变量可以在模块中使用,用于加载模块、导出模块、异步加载模块、组织模块等等,保证了模块的正常运行。

webpack_require

根据模块 id 导入模块

js
function __webpack_require__(moduleId) {
  if (__webpack_modules__[moduleId])
    return __webpack_module_cache__[moduleId].exports

  const module = __webpack_module_cache__[moduleId] = {
    exports: {}
  }
  __webpack_modules__[moduleId](module, module.exports, __webpack_require__)
  return module.exports
}

webpack_require.m

所有模块。每个模块是一个数组,数组的第一项是模块的代码,第二项是模块的导出,第三项是模块的 promise。

js
__webpack_require__.m = __webpack_modules__

webpack_require.c

模块缓存

js
__webpack_require__.c = __webpack_module_cache__

webpack_require.n

获取 default 导出

js
__webpack_require__.n = (module) => {
  const getter = module && module.__esModule
    ? () => module.default
    : () => module
  __webpack_require__.d(getter, { a: getter })
  return getter
}

webpack_require.d

给对象定义属性

js
__webpack_require__.d = (exports, definition) => {
  for (const key in definition) {
    if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key))
      Object.defineProperty(exports, key, { enumerable: true, get: definition[key] })
  }
}

webpack_require.o

判断对象是否有属性

js
__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)

webpack_require.f

异步加载模块

js
__webpack_require__.f = {}

webpack_require.e

执行 webpack_require.f 中的所有函数,返回处理后的得到的 promises,然后使用 Promise.all 等到所有的 promises 都执行完毕后再返回。

js
__webpack_require__.e = (chunkId) => {
  return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
    __webpack_require__.f[key](chunkId, promises)
    return promises
  }, []))
}

webpack_require.u

获取 chunk 文件名称

js
__webpack_require__.u = (chunkId) => {
  return `${chunkId}.js`
}

webpack_require.l

通过 script 标签加载 chunk 文件

js
__webpack_require__.l = (url, done, key, chunkId) => {
  if (__webpack_require__.o(__webpack_require__.m, key)) {
    done()
    return
  }
  const script = document.createElement('script')
  const onScriptComplete = () => {
    script.onerror = script.onload = null
    clearTimeout(timeout)
    const chunk = __webpack_require__.m[key]
    if (chunk !== 0) {
      if (chunk)
        chunk[1](new Error('Loading chunk failed'))
      __webpack_require__.m[key] = undefined
    }
  }
  let timeout = setTimeout(onScriptComplete, 120000)
  script.onerror = script.onload = onScriptComplete
  script.src = url
  document.head.appendChild(script)
}

webpack_require.r

给 exports 定义 __esModule 属性

js
__webpack_require__.r = (exports) => {
  if (typeof Symbol !== 'undefined' && Symbol.toStringTag)
    Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })

  Object.defineProperty(exports, '__esModule', { value: true })
}

webpack_require.p

公共路径

js
__webpack_require__.p = ''

webpack_require.f.j

异步加载模块的函数

js
// 0 表示加载完成,[resolve, reject, promise] 表示正在加载
const installedChunks = { app: 0 }
__webpack_require__.f.j = (chunkId, promises) => {
  let installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined
  if (installedChunkData !== 0) {
    if (installedChunkData) {
      promises.push(installedChunkData[2])
    }
    else {
      if (chunkId !== 'webpack_container_remote_mfe-c_Component2') {
        const promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]))
        promises.push(installedChunkData[2] = promise)

        const url = __webpack_require__.p + __webpack_require__.u(chunkId)

        const error = new Error()
        const loadingEnded = (event) => {
          if (__webpack_require__.o(installedChunks, chunkId)) {
            installedChunkData = installedChunks[chunkId]
            if (installedChunkData !== 0)
              installedChunks[chunkId] = undefined
            if (installedChunkData) {
              const errorType = event && (event.type === 'load' ? 'missing' : event.type)
              const 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
              installedChunkData[1](error)
            }
          }
        }
        __webpack_require__.l(url, loadingEnded, `chunk-${chunkId}`, chunkId)
      }
      else { installedChunks[chunkId] = 0 }
    }
  }
}

webpackJsonpCallback

异步加载模块的回调函数

js
function webpackJsonpCallback(parentChunkLoadingFunction, data) {
  const [chunkIds, moreModules, runtime] = data
  // add "moreModules" to the modules object,
  // then flag all "chunkIds" as loaded and fire callback
  let moduleId; let chunkId; let i = 0

  // 如果 chunkIds 中有一个 chunk 还没有加载完毕,就把 moreModules 添加到 __webpack_require__.m 中
  if (chunkIds.some(id => (installedChunks[id] !== 0))) {
    for (moduleId in moreModules) {
      if (__webpack_require__.o(moreModules, moduleId))
        __webpack_require__.m[moduleId] = moreModules[moduleId]
    }
    if (runtime)
      var result = runtime(__webpack_require__)
  }

  if (parentChunkLoadingFunction)
    parentChunkLoadingFunction(data)

  // 把 chunk 标记为已经加载完毕
  for (;i < chunkIds.length; i++) {
    chunkId = chunkIds[i]
    if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId])
      installedChunks[chunkId][0]()

    installedChunks[chunkId] = 0
  }
}

const chunkLoadingGlobal = self.webpackChunkmodule_federation_aaa = self.webpackChunkmodule_federation_aaa || []

// 对每一项执行 webpackJsonpCallback
chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0))
// 当 push 的时候执行 webpackJsonpCallback
chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal))