Как упаковать или импортировать HTML-шаблоны без HTML-импорта

Так как Html-импорт теперь не поддерживается в Chrome ( https://www.chromestatus.com/feature/5144752345317376) и будет удален, мне интересно, какие есть альтернативы.

В настоящее время я использую Html-Imports для импорта Html-шаблонов. Пока я вижу только две альтернативы:

  • Объединение всех HTML-файлов в один файл. Это также улучшит время загрузки, но уменьшит инкапсуляцию и модульность. Существует полимерный пакет, который будет выполнять эту работу путем обхода HTML-Import-Statements в отдельных HTML-файлах. Но это будет означать, что HTML-импорт остается в моем коде, даже если в будущем он не будет поддерживаться никакими браузерами.
  • Сборка какого-то загрузчика модулей с использованием XHttpRequests и объединение шаблонов в один HTML-файл во время выполнения. Это сохранит инкапсуляцию и модульность, но у меня будет неприятный запах, так как я в основном перестрою import-заявления самостоятельно.

Есть ли новый ванильный способ импорта HTML-шаблонов? (Под "ванилью" я подразумеваю путь без каких-либо дополнительных инструментов, таких как прекомпилятор или пакет)

2 ответа

Устаревание HTML Imports существенно изменило порядок загрузки ресурсов. Пользовательские элементы, по сути, стали в первую очередь сценариями, а не шаблонами. Если вашему элементу нужен шаблон, загрузите его из скрипта. Если нет, просто иди на работу. Честно говоря, в то время как я был устойчив к этому в течение первых нескольких недель, я полюбил это. И оказывается, что загрузка внешних ресурсов, таких как шаблоны, не так уж и плоха.

Вот простой код, который будет загружать шаблон HTML из внешнего файла:

используя async/await:

    async function getTemplate(filepath) {
        let response = await fetch(filepath);
        let txt = response.text();

        let html =  new DOMParser().parseFromString(txt, 'text/html');
        return html.querySelector('head > template');
    }

Обещают на основе:

    function getTemplate(filepath) {
        return fetch(filepath)
            .then(response => {
                let txt = response.text();
                let html = new DOMParser().parseFromString(txt, 'text/html');

                return html.querySelector('template');
            });
    }   

Оба могут быть вызваны с обоими из следующих:

асинхронная / ждут:

    let tpl = await getTemplate('path/to/template.html');

Обещания:

    getTemplate('path/to/template.html')
        .then(function doSomething(tpl) {
            // Put your code here...
        });

Полученный код достаточно прост, чтобы его можно было реализовать без особых усилий различными способами. На самом деле, у меня есть небольшой суперкласс, который обрабатывает его для меня, и все мои пользовательские элементы наследуются от него. Вместо этого вы можете использовать миксин, что я и делал в прошлом.

Тяжелая работа - это просто изменение порядка, и даже это не очень сложно, если вы не используете тысячи компонентов. Вероятно, это может быть автоматизировано с очень небольшим количеством работы.

index.html:

      <script type="module">
  import { CustomHTMLElement } from './CustomHTMLElement.js'

  customElements.define('custom-html-element', CustomHTMLElement)
</script>

<custom-html-element></custom-html-element>

CustomHTMLElement.js:

      import { createTemplate } from './createTemplate.js'

const template = createTemplate(`
  <template>
    <style>
      .box {
        width: 2rem;
        height: 2rem;
        background-color: red;
      }  
    </style>
    <div class="box"></div>
  </template>
`)

export class CustomHTMLElement extends HTMLElement {
  constructor() {
    super()
    const templateContent = template.content
    const shadowRoot = this.attachShadow({mode: 'closed'})
    shadowRoot.appendChild(templateContent.cloneNode(true))
  }
}

createTemplate.js:

      import { createDOM } from './createDOM.js'

export function createTemplate(templateText) {
  const dom = createDOM(templateText)
  const template = dom.querySelector('template')
  return template
}

createDOM.js:

      export function createDOM(htmlText) {
  return new DOMParser().parseFromString(htmlText, 'text/html')
}

См. Https://github.com/SanjoSolutions/web-components для кода, лицензированного по безлицензионной лицензии.

Другие вопросы по тегам