Предварительно скомпилируйте шаблоны pug и сохраните доступ к htmlWebpackPlugin.options - PullRequest
0 голосов
/ 12 июня 2019

Я решил перейти с ejs на pug как шаблонизатор в моих проектах веб-пакетов.И что мне нужно, это предварительно скомпилированный статический вывод (либо в dev, либо в режиме prod).Кроме того, мне нужно передать данные в шаблоны в процессе компиляции, и я использую для этого пользовательские параметры htmlWebpackPlugin.Структура проекта выглядит следующим образом:

root
|--package.json
|--webpack.configs // .dev.js, build.js
|--data.json
|--layout.pug
|--app
|--|--index.js
|--|--views
|--|--|--index.pug
|--|--|--includes
|--|--|--|--nav.pug
|--|--|--|--footer.pug
|--assets
|--|--(styles, images...)

Первый способ, который я нашел и попробовал, - передать данные в точку входа (скомпилировать локальные данные в index.js и вставить их на страницу через innerHTML =).Этот способ абсолютно не подходит для меня, так как мне нужен 100% предварительно скомпилированный статический вывод без вставки HTML во время выполнения.И тут начинается самое интересное ...

Например, мне нужно создать навигацию.У меня есть схема навигации следующим образом:

module.exports.nav = [
        {
          text: 'Home',
          href: '/'
        },
        {
          text: 'Offers',
          href: '/offers.html'
        },
        {
          text: 'Subnav Parent Test',
          isSubnavTrigger: true
        },
        {
          text: 'Subnav Item',
          href: '/test.html',
          isSubnavItem: true,
          subnavParent: 'Subnav Parent Test'
        }
      ]

и частичный pug для этого app/views/includes/nav.pug:

nav.navbar(role="navigation", ariaLabel="navigation")
  .container
    .navbar-brand
      a.navbar-item(href="/")
        img(src="/assets/images/logo.png", alt=title)
    .navbar-menu(id="navbar-menu")
      .navbar-start
      .navbar-end
        for link, index in nav
          //- TODO: isActive
          if !link.isSubnavTrigger && !link.isSubnavItem
            a(href=link.href, class="navbar-item")= link.text
          else if link.isSubnavTrigger
            .navbar-item.has-dropdown.is-hoverable
              a.navbar-link= link.text
              .navbar-dropdown
                - var parent = link.text
                - var dd = nav.filter(_item => _item.subnavParent === 
parent)
                each dd_link in dd
                  a.navbar-item(href=dd_link.href)= dd_link.text

, который частичный включен в общий макет layout.pug:

- var { title, nav } = htmlWebpackPlugin.options;
<!DOCTYPE html>
html(lang="en")
  head
    title= title + 'Pug Webpack Test'
    block metas
  body
    header
      include ./app/views/includes/nav.pug

    main
      block content

    footer  
      include ./app/views/includes/footer.pug

с надеждой, что app/views/includes/nav.pug будет интерполировать переменную nav.

Итак, я обнаружил 2 случая: используйте module -> rules -> loader и встроенный загрузчик в HTMLWebpackPlugin.

1-й.webpack.config.js настройки:

module.exports = {
  module: {
    rules: [
      //...
      {
        test: /\.pug$/,
        use: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
      }
      //...
    ],
  },
  plugins: [
    //...
    new HtmlWebpackPlugin({
      template: './layout.pug',
      filename: 'index.html',
      title: 'siteTitle',
      nav: nav  // required somewhere at the top of the file
    })
  ]
}

В этом случае мне не удается передать параметры из htmlWebpackPlugin в шаблоны.Как упоминалось в layout.pug, я пытаюсь уничтожить поля title и nav из опций и получаю ошибку компиляции: Cannot read property 'options' of undefined.

2-й случай.webpack.config.js:

module.exports = {
  module: {
    rules: [
      //...
      // Removed PUG loaders
      //...
    ],
  },
  plugins: [
    //...
    new HtmlWebpackPlugin({
      template: '!!pug-loader!./layout.pug', // <- inlined loader
      filename: 'index.html',
      title: 'siteTitle',
      nav: nav  // required somewhere at the top of the file
    })
  ]
}
// by the way, in case of EJS I've been using exactly this approach
// and it worked out pretty well with partials

Этот подход прекрасно компилирует layout.pug с параметрами, взятыми из htmlWebpackPlugin, , пока он не содержит включенные партиалы .И мне нужно передать мой nav в соответствующий партиал и оттуда вывести nav.И частичное начало сбрасывать ошибки в компиляцию, как будто она не понимает pug и нуждается в загрузчике:

  ERROR in ./app/views/includes/nav.pug 13:12
    Module parse failed: Unexpected token (13:12)
    You may need an appropriate loader to handle this file type.
    |       .navbar-start
    |       .navbar-end
    >         for link, index in nav
    |           //- TODO: isActive
    |           if !link.isSubnavTrigger && !link.isSubnavItem
     @ ./app/views/index.pug (c:/_npmg/node_modules/pug-loader!./app/views/index.pug) 4:514-543

Я в полном беспорядке.Я не хочу отступать к ejs, но если я не найду ответ, похоже, мне придется.

Спасибо, вперед.

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Я хочу уведомить ОП о его решении, но не могу комментировать.

HtmlWebpackPlugin и pug-loader могут хорошо работать вместе.Вместо использования:

// webpack.config file
new HtmlWebpackPlugin({
      template: './layout.pug',
      filename: 'index.html',
      myContent: 'loremp ipsum'
    })

// app/views/partials/nav.pug
- var { myContent } = htmlWebpackPlugin.options
p= myContent

вы можете использовать следующий синтаксис:

// webpack.config file
new HtmlWebpackPlugin({
   template: './layout.pug',
   filename: 'index.html',
   templateParameters: {
       myContent: 'loremp ipsum'   
   }
})

// app/views/partials/nav.pug
p= myContent

Он работает со всеми функциями движка мопса, и мы получаем более читаемые шаблоны.

1 голос
/ 12 июня 2019

решено.

Ответ состоит из 2 выводов:

  1. Используйте соответствующий загрузчик.

    Единственный загрузчик, который соответствует моим потребностям, это pug-loader (не pug-html-loader и не цепочка из нескольких загрузчиков).Ссылка здесь , но в двух словах:

    pug-loader: возвращает функцию

    pug-html-loader: возвращает строку, поэтому она статическая и нетпараметры могут быть переданы через

    Итак, окончательные настройки webpack.config.js относительно этого:

module.exports = {
  module: {
    rules: [
      //...
      test: /\.pug$/,
      use: [
        {loader: 'pug-loader'}
      ]
      //...
    ],
  },
  plugins: [
    //...
    new HtmlWebpackPlugin({
      template: './layout.pug', // <- NOT inlined loader
      filename: 'index.html',
      title: 'siteTitle',
      nav: nav  // required somewhere at the top of the file
    })
  ]
}

Частицы не наследуют переменные от макета, от которого требовалось частичное.

Итак, поскольку я хочу использовать данные из htmlWebpackPlugin.options, я должен объявить переменнуюдля этих данных не в общем файле макета, , но частично:

// app/views/partials/nav.pug
- var { nav } = htmlWebpackPlugin.options

nav.navbar(... and the other code you've seen above)

В случае, если кто-то сталкивается с этой проблемой, этоэто 100% рабочий подход.

...