задний план
Webpack — это самый популярный интерфейсный инструмент для модульного управления и упаковки ресурсов. Он может упаковывать множество свободных модулей во внешние ресурсы, которые соответствуют развертыванию в производственной среде в соответствии с зависимостями и правилами. Вы также можете кодировать отдельные модули, загружаемые по требованию, и загружать их асинхронно, когда они действительно необходимы. Webpack такой мощный, каков его внутренний механизм, давайте выясним сегодня.
Готов к работе
Создайте новый каталог и выполните npm init -y, чтобы инициализировать файл package.json.
Создайте index.js в src в качестве файла записи и export.js в качестве зависимого модуля.
Создайте новый файл webpack.config.js и напишите его здесь в соответствии с базовой конфигурацией webpack4.
Создайте новый bundle.js в качестве записи для создания веб-пакета Создайте webpack.js в lib
Чтение входного файла в соответствии с конфигурацией
bundle.js:
//读取到webpackd 的配置文件
const options = require("./webpack.config.js")
const Webpack = require("./lib/webpack.js")
new Webpack(options).run()
webpack.js Здесь написан класс Webpack, bundle.js создает экземпляр этого класса, передает параметры (содержимое импортированной базовой конфигурации) и выполняет метод запуска
module.exports = class Webpack {
constructor(options){
console.log(options)
}
run(){
console.log("hello")
}
}
Выполните node bundle.js в этот момент:
Входной модуль уже может быть прочитан в соответствии с базовой конфигурациейПроанализированные зависимые модули
index.js, который я написал здесь, выглядит так:
import { sayHi } from './export.js'
sayHi("hfj")
console.log("hello webpack index")
На этом этапе вам нужно использовать основной модуль узла -- файловую систему для чтения содержимого.
const conts = fs.readFileSync(entryFile,'utf-8')
Затем абстрагируйте содержимое в синтаксическое дерево с помощью @babel/parser (не забудьте установить и импортировать его самостоятельно..)
const ast = parser.parse(conts, {
sourceType: "module"
});
печать ast.program.body
Глядя на тип, где зависимый модуль и где выражение, это уже очевидно.Далее используйте @babel/traverse для извлечения зависимого модуля:const dependencies = {}
traverse(ast,{
ImportDeclaration({node}){
const newPath = "./" + path.join(
path.dirname(entryFile),
node.source.value
)
dependencies[node.source.value] = newPath
console.log(dependencies)
}
})
Обратите внимание, что здесь выполняется процесс, и зависимые модули помещаются в зависимости в виде объектов.
Компиляция контента
Затем обработайте ast в контент через @babel/core.
const {code} = transformFromAst(ast,null,{
presets: ["@babel/preset-env"]
})
console.log(code)
Распечатанный код выглядит следующим образом:
Контент успешно получен!Модули, зависимые от хода
Выше приведена компиляция входного файла.Далее нам нужно посмотреть зависимые модули входного модуля, проанализировать содержимое по методу только что и, наконец, сделать сводку (в зависимости от того, есть ли зависимые модули) :
run(){
const info = this.analysis(this.entry)
this.modulesArr.push(info)
for(let i=0;i<this.modulesArr.length;i++) {
const item = this.modulesArr[i]
const { dependencies } = item;
if(dependencies) {
for(let j in dependencies){
this.modulesArr.push(this.analysis(dependencies[j]))
}
}
}
// console.log(this.modules)
//数组结构转换
const obj = {}
this.modulesArr.forEach((item) => {
obj[item.entryFile] = {
dependencies:item.dependencies,
code:item.code
}
})
}
В итоге modulesArr преобразуется в объект, удобный для последующей обработки.
Вывод исполняемого js-кода браузера
Сосредоточьтесь здесь!Наконец, Webpack упаковывает модульные js в чанк, и упакованные js отправляются в dist (выходной набор в базовой конфигурации webpack).
Сначала используйте fs.writeFileSync для записи сгенерированного пакета в filePath (filePath был сохранен в this.output ранее), а затем обработайте obj (агрегированный модуль на предыдущем шаге):
Суть в том, чтобы использовать eval() для выполнения кода в obj.В то же время ему нужно обработать requrie и export require и export передаются через формальные параметры, а затем выполнять reqire и export require, которые вы написали для обработки путь к модулю.Exports - это объект, см. исходный код--
const bundle = `(function(graph){
function require(moduleId){
function localRequire(relativePath){
return require(graph[moduleId].dependencies[relativePath])
}
var exports = {};
(function(require,exports,code){
eval(code)
})(localRequire,exports,graph[moduleId].code)
return exports;
}
require('${this.entry}')
})(${newCode})`
Выполните node bundle.js и выведите следующие js в папку dist:
(function(graph){
function require(moduleId){
function localRequire(relativePath){
return require(graph[moduleId].dependencies[relativePath])
}
var exports = {};
(function(require,exports,code){
eval(code)
})(localRequire,exports,graph[moduleId].code)
return exports;
}
require('./src/index.js')
})({"./src/index.js":{"dependencies":{"./export.js":"./src\\export.js"},"code":"\"use strict\";\n\nvar _export = require(\"./export.js\");\n\n(0, _export.sayHi)(\"hfj\");\nconsole.log(\"hello webpack index\");"},"./src\\export.js":{"dependencies":{},"code":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.sayHi = void 0;\n\nvar sayHi = function sayHi(params) {\n console.log(\"hello ~\" + params);\n};\n\nexports.sayHi = sayHi;"}})
Выполнить в браузере: вывод:
сделано~
Суммировать
webpack слой за слоем просматривает зависимости модуля через входной файл, выполняет анализ кода, преобразование кода и, наконец, генерирует упакованный код, который можно запустить в браузере.
По сути, webpack — это сборщик статических модулей для современных приложений JavaScript. Когда webpack обрабатывает приложение, он рекурсивно строит граф зависимостей, содержащий каждый модуль, необходимый приложению, а затем объединяет все эти модули в один или несколько пакетов.
Вышеприведенное реализует упрощенную версию веб-пакета.
Далее: Анализ принципа Webpack (2) загрузчик и механизм плагина
Если вы заинтересованы, добро пожаловать на дальнейшее обсуждение~
Прикрепите адрес гитхаба:GitHub.com/brute-force-fairy…
Ссылаться на:Официальный сайт вебпака