0

我决定在我的 webpack 项目中从ejspug作为模板引擎。我需要的是预编译的静态输出(无论是在开发模式下还是在生产模式下)。另外,我需要通过编译过程将数据传递给模板,并且我使用了自定义选项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'
        }
      ]

和哈巴狗部分为此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变量。

所以我发现了两种情况:使用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,我尝试从选项中破坏titlenav字段并获得编译错误: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给相应的部分并从那里渲染导航。并且部分开始向编译中抛出错误,就好像它不理解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,但如果我找不到答案,似乎我将不得不这样做。

谢谢转发。

4

2 回答 2

3

解决了。

答案包括两个结论:

  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
    })
  ]
}
  1. 部分不会从需要部分的布局继承变量。

    因此,当我想使用来自 的数据时htmlWebpackPlugin.options,我必须为这些数据声明变量,而不是在通用布局文件中,而是在部分本身中:

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

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

如果有人遇到这个问题,这是 100% 的工作方法。

于 2019-06-12T12:19:15.987 回答
1

我想通知 OP 他的解决方案,但我不能发表评论。

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

它适用于所有哈巴狗引擎功能,我们获得了更具可读性的模板。

于 2019-07-09T21:20:56.400 回答