Я не начинал писать несколько месяцев.В последнее время я исследую некоторые технические вещи с командой.Есть только часть фронтенд-модуля, которым я могу поделиться с вами.
Прежде чем мы перейдем к сути, давайте рассмотрим краткую историю создания интерфейсных модулей с нуля.
Если у вас есть некоторый опыт работы и вы пережили эру jQuery, вы должны знать, что ранний интерфейсный модуль — это просто локальная переменная в окне.
В начале, чтобы поделиться собственным кодом, фронтенд инженеры часто устанавливали контакты через windows.Эта древняя практика до сих пор используется многими людьми из-за ее простоты.Например,когда мы пишем скрипт,мы обычно не думаем это модуль. , но мы привыкнем оборачивать этот скрипт как объект. Например
window.myModule = {
getName(name){
return `hello ${name}`
}
}
Когда кто-то другой загружает этот скрипт, он может легко вызвать метод getName через window.myModule.
Ранние сценарии JavaScript в основном использовались для разработки некоторых простых форм и интерактивных функций веб-страниц, в то время было очень мало фронтенд-инженеров, и не было больших проблем с реализацией модульности через окна.
До появления ajax веб постепенно продвигался до стадии богатого клиента.С появлением spa фронтенд-инженерам стало все труднее поддерживать использование оконного модульного кода.Есть две основные причины.
- Массивная загрузка модулей загрязняет окно, вызывая различные конфликты имен и случайные перезаписи, которые до сих пор трудно обнаружить.
- Взаимодействий между модулями становится все больше, и чтобы обеспечить порядок вызова, необходимо искусственно гарантировать порядок загрузки тегов скрипта.
Чтобы решить эту проблему, был создан загрузчик модулей, такой как require seajs, и с помощью загрузчика модулей две вышеупомянутые проблемы были значительно облегчены.
Однако скорость фронтенд-технологии и развитие Интернета далеко за пределами нашего воображения.Поскольку веб-страница все больше и больше становится похожей на реального клиента, это ставит перед инженерными возможностями фронтенда серьезную проблему. трудно уложиться в проект просто разработкой скрипта.Поэтому в поле нашего зрения стали входить строительные леса для управления фронтенд-инжинирингом типа gulp, но на данном этапе загрузчик модулей и поток фронтенд-инжиниринга не были органично комбинированный.
До появления nodejs у фронтенда был свой инструмент управления пакетами npm, на этой основе Webpack еще больше способствовал интеграции между фронтенд-инженерным потоком и модулями, а затем процесс модульности фронтенда начал стабилизироваться, и сохраняется по сей день.
Оглядываясь назад на эту историю, можно сказать, что весь процесс модульности внешнего интерфейса, включая стандарт es6 для модулей, всегда существовал вокруг этого основного предложения.
Либо require, либо Webpack по этому основному предложению и нет никакой разницы, то есть следовать интерфейсному модулю
Загрузить → вызвать → выполнить такую логическую взаимосвязь.Поскольку модули должны быть загружены, прежде чем их можно будет вызвать и выполнить, загрузчики модулей и инструменты сборки должны управлять и анализировать зависимости всех модулей в приложении, чтобы определить, какие модули можно разделить, а какие быть объединены. , и порядок, в котором загружаются модули.
Однако со временем интерфейсное приложение имеет все больше и больше модулей, а приложение становится все больше и больше. Наши локальные node_modules начинаются с нескольких сотен мегабайт. Хотя Webpack провел большую оптимизацию, время перестройки все еще очень долго перед масштабными приложениями.медленно.
В феврале этого года Webpack 5 выпустила свое решение для дизассемблирования модулей, объединение модулей, которое решает проблему невозможности повторного использования модулей, созданных Webpack, в нескольких проектах.
Более ранняя пряжа 2.0 использовала метод совместного использования node_moudles для решения проблемы производительности, вызванной большим количеством избыточных локальных модулей. В том числе автор nodejs отказался от npm в deno и перешел на способ сетевой загрузки модулей и т.д.
Видно, что сообщество осознало, что первый модульный механизм внешнего интерфейса снова сталкивается с узким местом, и есть много проблем с точки зрения производительности и затрат на обслуживание, и каждая команда пытается найти способ открыть новый. направление.
Тем не менее, эти усилия по-прежнему не выходят за рамки основного положения механизма упреждающей модульности, то есть модуль должен быть сначала загружен, а затем вызван и выполнен.
Пока это основное положение остается неизменным, проблема зависимости модулей остается неразрешимой, поэтому мы пытаемся предложить новую идею.
Почему нельзя сначала вызвать модуль, а затем загрузить и выполнить?
Если модуль A вызывает модуль B, но не требует, чтобы модуль B был готов немедленно, это означает, что загрузчик модуля может не заботиться о зависимостях модуля, а сосредоточиться только на решении проблем эффективности и производительности загрузки модуля.
В то же время для инструмента сборки, если выполнение модуля А не основано на том, что модуль Б сразу готов, то инструмент сборки может спокойно разделить модули А и Б на два файла. много модулей, вы можете использовать http2 Возможность параллельной загрузки значительно повышает производительность загрузки модуля.
В нашем видении новый метод загрузки модулей выглядит так
// remoteModule.js 这是一个发布到 cdn 的远程模块, 内部代码是这样
widnow.rdeco.create({
name:'remote-module',
exports:{
getName(name, next){
next(`hello ${name}`)
}
}
})
Давайте не будем сначала загружать этот модуль, а сразу выполним код на вызывающей стороне.Например, этот
window.rdeco можно понимать как существование, похожее на среду выполнения Webpack, но rdeco — это независимая библиотека, ее функции гораздо шире.
// localModule.js 这个是本地的模块
window.rdeco.inject('remote-module').getName('world').then(fullName=>{
console.log(fullName)
})
Затем мы сначала загружаем localModule.js, а затем загружаем remoteModule.js в html.
<scirpt src="localModule.js"></script>
<scirpt src="remoteModule.js"></script>
Это нормально понимать, что после загрузки localModule.js он попытается вызвать метод getName удаленного модуля, но удаленный модуль еще не загружен.Согласно предыдущему механизму модульности, этот вызов вызовет исключение. чтобы избежать этой проблемы
Инструмент построения модуля должен проанализировать код двух файлов, чтобы обнаружить, что localModule.js зависит от remoteModule.js, затем сохранить порядок зависимостей и уведомить загрузчик модуля, что для правильного выполнения кода remoteModule.js должен загружаться в первую очередь.
Но если модуль можно сначала вызвать, а потом загрузить, то этого сложного процесса можно вообще избежать.На данный момент мы реализовали этот механизм, вы можете посмотреть это демо:код sandbox.IO/is/tender-AR…
Вы можете попробовать нажать сначалаCall remote module's getName method
кнопка,
При этом копировать не меняется просто показывает привет, но код то не кидает, то жмешьLoad remote module
кнопку, начните загрузку remoteModule, дождитесь завершения загрузки, будет выполнено getName, и копия станет hello world
Приведенный выше пример представляет собой микрокосм нашего нового взгляда на модульность интерфейса и разделение кода.Мы приняли много схожих идей при разработке реальных приложений, и в настоящее время связанные функции инкапсулированы в rdeco:GitHub.com/kin op112365…В этом проекте, если вы заинтересованы в нашей работе, добро пожаловать, чтобы следовать за нами 👏🏻, и еще добро пожаловать, чтобы присоединиться к нам, просто оставьте сообщение ниже