Анализ файлов после упаковки webpack

Webpack

вебпак для компиляцииjavascriptмодуль, который может скомпилировать формат файла в желаемый статический формат файла, но процесс обработки не полностью определяетсяwebpackСовершенный в себе,webpackОн просто обеспечивает механизм упаковки, и для обработки упаковки различных файлов необходимо использовать соответствующий модуль предварительной обработки.loaderобращаться, как с механизмомwebpackпомогут различныеloaderОбеспечивает идентификацию входных каталогов, входных файлов, выходных каталогов и выходных файлов.

Сначала мы пытаемся упаковать пакет, который содержит толькоconsole.log('hello world')изjsдокумент.

Файлы инициализации и установкаwebpackокружающая обстановка

#  新建 demo 目录
mkdir webpack-demo cd webpack-demo

# 初始化目录
npm init -y

# 本地安装 webpack 工具
npm install webpack webpacl-cli  --save-dev

# webpack 默认的入口文件是 .src/index.js   创建 src 目录和 index.js 文件
mkdir src

echo “console.log('hello world')” > src/index.js

# 执行 webpack 命令  需要查看打包后文件, 这里使用 development 模式 
npx webpack --mode development

Упрощенные упакованные файлы

Поскольку упакованные файлы громоздки, здесь мы упрощаем упакованные файлы.

(function(modules) {
    var installedModules = {}
    function __webpack_require__(moduleIid) {

    }
    return __webpack_require__(__webpack_require__.s = "./src/index.js")
})({
    "./src/index.js": (function(module, exports) {
                            eval("console.log('test webpack entry')");
                    })
})

Упакованный файл содержит много комментариев иwebpackсами переменные, для удобства анализа эти аннотации и подобные__webpack_require__.sудалить все операторы копирования

Как видно из приведенного выше кода,

  1. проходить черезwebpackУпакованный код проходитIIFEСамовыполняющаяся функция, эта функция получает параметр объекта,keyэто каталог входного файла,valueэто функция, которая выполняет код в файле ввода
  2. этот объект как параметрmodulesПерейти кIIFEфункция
  3. IIFEВнутри функции объявлена ​​переменнаяinstalledModulesИспользуется для хранения кеша, функция__webpack_require__, используемый для преобразования кода в файле ввода
  4. IIFEнаконец положитьmodulesвнутриkeyПерейти к__webpack_require__функция и возврат.

мы смотрим дальше__webpack_require__что делает функция.

__webpack_require__анализировать

function (modules) {
    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
    }
}

  1. __webpack_require__функция получения./src/index.js
  2. Сначала проверьте кешinstalledModulesсодержит ли онkeyдля./src/index.jsобъект, если он существует, вернуть объект в этот объект напрямуюexports
  3. Когда модуль входа не существует в кеше, в кеше создается и помещается в кеш объект, который включает три значения:i l exports
  4. использоватьmodules[moduleId].callпередачаIIFEпараметрическийvalueфункцию и поставитьvalueВ соответствующей функцииthisуказатель, назначенныйmodule.exports, НазадcallПоследние три параметра методаvalueПараметры соответствующей функции
  5. наконец вернулсяmodule.exports, здесьmodule.exportsНа четвертом этапе он был назначен какIIFEв объекте параметраvalueсоответствующую функцию.

Так что это видно. функция__webpack_require__То, что на самом деле возвращается,IIFEв объекте параметраvalueСоответствующая функция, т.eval("\nconsole.log('test webpack entry')\n\n\n//# sourceURL=webpack:///./src/index.js?"),

когда мы бежимwebpackКогда упакованный файл выполняется, он выполняется"console.log('test webpack entry')"

Функция eval() оценивает строку и выполняет в ней код JavaScript.

Процесс упаковки, когда файл записи ссылается на другие модули

Никакие другие модули кода не упоминаются в файле записи процесса упаковки, упомянутом выше.webpackПроцесс упаковки также аналогичен описанному выше процессу.

существует./src/под новымmain.js

module.exports = () => {
    console.log('main module')
}

существует./src/index.jsвведен вmain.js

const main = reuiqre('./main.js')
console.log('webpack index entry')
main()

бегатьnpx webpackупакованный файл

IIFEизменение параметра

(function (mudoles) {

})({
    './src/index.js': (function(module,exports, __webpack_require__) {
        eval("const main = __webpack_require__(/*! ./main.js */ \"./src/main.js\")\r\nconsole.log('test webpack entry')\r\n\n\n//# sourceURL=webpack:///./src/index.js?");
    }), 
    './src/main.js': (function(module, exports) {
        eval("console.log('main module')\n\n//# sourceURL=webpack:///./src/main.js?");
    })
})

Если в файле записи есть ссылки на файлы из других модулей, эти модули будут добавлены вIIFEв объекте параметра ,keyпуть модуля,valueФункция, которая выполняет код этого модуля.

IIFEИзменения в логике выполнения функций

function (modules) {
    var installedModules = {}

    function __webpack_require__ (moduleId) {
        if (installedModules[moduleId]) {
            return installedMOdules[mudoleId].exports
        }

        var module = installedModuled[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        }
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)

        return module.exports
    }

    return __webpack_require__(__webpack_require__.s = "./src/index.js")
}

Приведенный выше код по-прежнему возвращает./src/index.jsфункция с параметрами. Но логика внутри функции изменилась.

  1. объявить одинinstalledModulesкеш хранения переменных
  2. Буду./src/index.jsвходящий__webpack_require__функция
  3. ./src/index.jsНет в кеше, спуститесь
  4. объявить одинmoduleи сохранить в кеше./src/index.jsдляkeyОбъект
  5. передачаmodules[moduleId]функции и указать область и параметры, которые
    function(module,exports, __webpack_require__) {
            eval("const main = __webpack_require__(/*! ./main.js */ \"./src/main.js\")\r\nconsole.log('test webpack entry')\r\n\n\n//# sourceURL=webpack:///./src/index.js?")}
    
  6. вернутьmodule.exports, так как пятый шаг вызываетmodules['./src/index.js']функция, уже поставилmodule.exportsкак функцияthisразмах, так что на этот разmodule.exportsфактическиmodules['./src/index.js']функция для выполнения.
  7. В приведенной выше функцииevalВ коде используется функция__webpack_require__, эта функция находится на пятом шагеmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__)последний параметр__webpack_require__, затем продолжайте звонить__webpack__require__функционировать и проходить в./src/main.js
  8. ./src/main.jsвходящий__webpack_require__, все еще не в кеше, снова объявить переменнуюmoduleи добавить новый в кешkeyдля./src/main.jsОбъект.
  9. modules[moduleId].callпозвони в это времяIIFEобъект параметраkeyдля./src/main.jsФункция:
         (function(module, exports) {
            eval("console.log('main module')\n\n//# sourceURL=webpack:///./src/main.js?");
        })
    
  10. вернутьmodule.export, аналогично шагу 6 в настоящее времяmodule.exportsто естьmodules[./src/main.js]соответствующую функцию.
  11. Окончательный возвращаемый результат (удаленevalи комментарии):
    const main = console.log('main module')
    console.log(test webpack entry)