Я потратил часы на базовую конфигурацию веб-пакета, но до сих пор не могу заставить его работать. Моя цель - выполнить синтаксический анализ шаблона html, когда вы импортируете его в файл JavaScript. Это похоже на обычный вариант использования, но в моей конфигурации веб-пакета или в моем понимании должно быть что-то странное.
Я искал конфигурации html-loader
, html-webpack-plugin
, posthtml
, а также pug
, и я прочитал всю их документацию, но ни одна из них не сработала.
Согласно PostHTML Readme:
PostHTML is a tool for transforming HTML/XML with JS plugins. PostHTML itself is very small. It includes only a HTML parser, a HTML node tree API and a node tree stringifier.
Итак, поскольку это было наиболее многообещающе, я сообщаю о своей попытке с posthtml:
rules: [
{
test: /.html$/,
use: [
{
loader: "html-loader",
options: {
minimize: true,
interpolation: false
}
},
{
loader: "posthtml-loader"
}
]
}
]
Он не возвращает никакой ошибки, но похоже, что он полностью игнорирует posthtml-loader
, так как при выполнении import template from 'src/test.html'
я получаю шаблон в виде строки (как предполагается делать html-loader
отдельно).
Насколько я понимаю, загрузчики должны компилировать/преобразовывать файлы разных форматов и делать их доступными для JavaScript, а поскольку html
является наиболее распространенным типом во внешнем проекте, я полагал, что это было легко, но я ничего не нашел на интернет по этому вопросу.
Чего я ожидаю, так это иметь объект дерева DOM или, во всяком случае, что-то, что может использоваться JavaScript.
Кто-нибудь может мне помочь?
Обновлено: Мой вопрос касается настройки и работы веб-пакета. Я знаю много решений для разбора строк HTML, но здесь они не применимы.
Вы добавили часть plugin
из их документов в веб-пакете?
Попробуй ssr и отреагируй, в моей папке все готово к работе. это просто github.com/Da99er/реагировать-сервер-старт-кит
@HRK44 Да, здесь — это мой полный webpack.config.js
@VadimHulevich это не то, что я хочу, я не могу использовать никакой фреймворк (иначе я не сошел с ума от webpack :D) и, в конце концов, все, что я хочу, это просто выполнить innerHTML
. Так что любой фреймворк, даже маленький, будет излишним.
Что ж, преобразовать строку в html легко. Поэтому, если вы получите строковый ответ для своего шаблона, вы можете преобразовать его в структуру DOM, как показано ниже.
/** Create a NON attached DOM element. This floats in nothing. Hello Dave */
var dave = document.createElement("div");
/** Give dave a body with the HTML string we received from "somewhere" */
dave.innerHTML = "<div class='foo'><input type='text'></div>";
/**
* dave is now <div><div class='foo'><input type='text'></div></div>
*/
dave.querySelector('input').value = "I'm sorry Dave, I'm afraid I can't do that";
/** ======================================================================
* Now render we render Dave, this isn't really needed, but will do anyways.
* We don't need the "wrapping" floating div we created so we get all of Dave's children
* And let Dave be forgotten about in the abyss of eternity.
*/
var content = dave.children;
var main = document.getElementById('main');
for(var i = 0; i < content.length; i++) {
main.appendChild(content[i]);
}
.foo {
background-color: red;
}
.foo input {
background-color: black;
color: white;
}
<body id = "main">
</body>
Затем вы можете выполнить преобразование и для «детей», как и для обычного объекта дерева DOM.
Мне не нравится это решение, потому что мне нужно парсить html в нескольких файлах, и я не могу каждый раз вводить html в DOM только для того, чтобы понять, как устроен шаблон. Я мог бы создать поддельный документ, поскольку это позволяет JavaScript, а затем использовать его для анализа. Или я мог бы использовать отдельную библиотеку. Но я бы предпочел решение на основе веб-пакета: D, теоретически оно должно работать.
@ChristianTraìna Вам не нужно вводить в DOM. только последняя строка внедряется в DOM. остальное чисто виртуально. Вы создаете виртуальный неприкрепленный элемент с помощью x. Там вы вставляете текст. Это преобразовано в объект DOM. Вы можете сделать x.getElementById и т. д. Без вступления в силу визуализированного DOM
@CristianTraìna Я изменил ответ, добавив несколько комментариев, чтобы объяснить, что происходит.
Мне кажется, что posthtml-loader
— это в первую очередь инструмент, который помогает «подготовить» ваш HTML во время сборки. Параметры его парсера позволяют перейти к шагу string -> PostHTML AST Tree
, а параметры плагина позволяют изменять дерево. Затем он преобразуется обратно в HTML.
Я не смог найти в плагине веб-пакета возможность вернуть промежуточный формат дерева.
Вы можете написать небольшой пользовательский загрузчик для разбора строк HTML в объекты DOM:
// custom-loader.js
module.exports = function(content) {
return `module.exports = (function() {
const parser = new DOMParser();
const doc = parser.parseFromString("${content}", "text/html");
return doc.body.children;
}())`;
};
Затем в своем webpack.config.js
вы можете указать веб-пакету, чтобы .html
файлы передавали этот загрузчик:
// webpack.config.js
module.exports = {
mode: 'development',
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.bundle.js'
},
devtool: "eval-source-map",
module: {
rules: [
{
test: /\.html$/,
use: [ './custom-loader' ]
}
]
}
};
Теперь всякий раз, когда вы вводите что-то вроде const template = require('./template.html');
, вы получите экземпляр HTMLCollection
, а не просто строку.
Обратите внимание, что этот загрузчик добавляет зависимость к DOMParser
, которая доступна только в браузере. Вы можете заменить его чем-то вроде jsdom
, если хотите работать в небраузерной среде.
Вы не только объяснили, почему PostHTML не работает, но и предложили рабочее решение. Так что большое спасибо, это, безусловно, лучший ответ. Вы бы посоветовали этому решению реализовать структуру модель-представление-контроллер (без фреймворка) или вы думаете, что есть лучшие решения?
Я думаю, что это отличная идея — импортировать ваши HTML-шаблоны с помощью webpack. Я использую тот же подход при работе с Knockout.js в MVVM, например, в моде. Удобно, когда модели (просмотра), шаблоны и даже стили хорошо разделены. Тем не менее, автоматический анализ элементов DOM я мог бы с таким же успехом рассматривать как часть вашего кода на стороне клиента. Типа, new UserProfile( apiUser, Template.fromString(require("./UserProfile.html") ) )
.
Хотите верьте, хотите нет, но это не самый распространенный вариант использования, но импорт html-файлов в JavaScript и их отображение звучит как обходной путь или взлом среднего порта. Библиотеки JavaScript используются для генерации динамического html "на лету" в браузере в ответ на вводимые пользователем данные. Если это то, что вы хотите, вы должны использовать React, Vue, Angular, jQuery или что-то подобное.
Как уже упоминалось, решение вашей проблемы состоит не в том, чтобы искать загрузчик, который преобразует HTML в узел DOM, а в том, чтобы вы сделали это самостоятельно. DOM отсутствует, пока код не будет выполнен в браузере,Это не преобразование времени компиляции. Это преобразование во время выполнения.
import template from 'src/test.html'
const html = document.createElement('div')
html.innerHTML = template
Загрузчик просто не может сделать то, что вы просите. Браузер отвечает за синтаксический анализ HTML и построение дерева DOM на основе своей платформы и конкретной реализации поставщика. querySelector
или createElement
— это методы API для доступа к этой функции браузера. Но у нас нет узлов DOM в нашем коде. Они созданы для нас платформой. Наш JavaScript просто потребляет его.
Есть некоторые решения, такие как DOMParser
и jsDOM
, которые могут сделать это на сервере. Но они являются неполными реализациями DOM браузера, и их не следует вносить во внешний код, предназначенный для отправки в браузер. Они предназначены для таких вещей, как безголовое тестирование, веб-сканирование и другие формы машинного использования веб-страниц.
Если вы можете представить конкретный сценарий, в котором вы не можете проанализировать строку HTML в браузере вместе с остальным кодом и непосредственно перед тем, как она будет использована JavaScript, во что бы то ни стало покажите нам, и мы предложим решение. Но весьма вероятно, что вы неправильно поняли роли JavaScript, Webpack и HTML и взаимосвязь между ними.
TLDR: HTML — это строка, которая отправляется в браузер через HTTP, и браузер решает, как построить дерево DOM на основе его конкретной реализации поставщика. Во внешнем коде нет альтернативы, кроме как заставить браузер построить для вас дерево DOM с предоставленной вами строкой, а затем использовать его с помощью DOM Api.
Спасибо за ваш ответ. Я думал, что есть что-то доступное для анализа HTML, например, фреймворк, поскольку Angular, React, Vue и так далее основаны на веб-пакете, и я думал, что все они используются для анализа и составления шаблонов. Вместо этого, вероятно, каждый из них использует свой собственный парсер
Они используют свои собственные компиляторы для создания своих собственных представлений объектов, таких как React.createElement('div', childElements)
и т. д.... Ни одна из платформ фактически не создает DOM до тех пор, пока код не будет выполнен в браузере.
Первая строка в документе html-loader:
Exports HTML as string
, можете ли вы дать ссылку на то, чтоposthml-loader
есть/делает?