最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

webpack - Parse an HTML template as you require it in JavaScript - Stack Overflow

programmeradmin2浏览0评论

I spent hours on a basic webpack configuration but I'm still not able to make it work. My aim is to perform the parsing of a html template as you import it in a JavaScript file. It looks like a mon use-case, but there should be something odd in my webpack configuration or in my understanding.

I looked for configurations of html-loader, html-webpack-plugin, posthtml as well as pug and I've read all of their documentations, but none of them worked.

According to 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.

So, since it was the most promising, I report my attempt with posthtml:

   rules: [
      {
        test: /.html$/,
        use: [
          {
            loader: "html-loader",
            options: {
              minimize: true,
              interpolation: false
            }
          },
          {
            loader: "posthtml-loader"
          }
        ]
      }
    ]

It doesn't return any error but it looks like is totally ignoring the posthtml-loader, since executing import template from 'src/test.html' I get the template as string (how is supposed to do html-loader alone).

In my understanding, loaders are supposed to pile/transform files with different formats and make them available to JavaScript, and since html is the most mon type in a front-end project I supposed it was easy, but I'm not finding anything on the internet related to this question.

What I expect is to have a DOM tree object or, anyway, something that can be used by JavaScript.

Is anyone able to help me?

EDIT: My question is about getting a webpack configuration up and working. I know many solution for parsing HTML strings, but they're not applicable here

I spent hours on a basic webpack configuration but I'm still not able to make it work. My aim is to perform the parsing of a html template as you import it in a JavaScript file. It looks like a mon use-case, but there should be something odd in my webpack configuration or in my understanding.

I looked for configurations of html-loader, html-webpack-plugin, posthtml as well as pug and I've read all of their documentations, but none of them worked.

According to 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.

So, since it was the most promising, I report my attempt with posthtml:

   rules: [
      {
        test: /.html$/,
        use: [
          {
            loader: "html-loader",
            options: {
              minimize: true,
              interpolation: false
            }
          },
          {
            loader: "posthtml-loader"
          }
        ]
      }
    ]

It doesn't return any error but it looks like is totally ignoring the posthtml-loader, since executing import template from 'src/test.html' I get the template as string (how is supposed to do html-loader alone).

In my understanding, loaders are supposed to pile/transform files with different formats and make them available to JavaScript, and since html is the most mon type in a front-end project I supposed it was easy, but I'm not finding anything on the internet related to this question.

What I expect is to have a DOM tree object or, anyway, something that can be used by JavaScript.

Is anyone able to help me?

EDIT: My question is about getting a webpack configuration up and working. I know many solution for parsing HTML strings, but they're not applicable here

Share Improve this question edited May 31, 2019 at 9:23 Christian Vincenzo Traina asked May 29, 2019 at 8:11 Christian Vincenzo TrainaChristian Vincenzo Traina 10.5k4 gold badges45 silver badges78 bronze badges 5
  • First line in the html-loader doc : Exports HTML as string, can you put a link to what posthml-loader is/does? – HRK44 Commented May 31, 2019 at 8:28
  • Did you add the plugin part from their docs on webpack? – HRK44 Commented May 31, 2019 at 8:46
  • Try ssr and react, in my folder all ready for work. it's easy github./Da99er/react-server-start-kit – Vadim Hulevich Commented May 31, 2019 at 8:53
  • @HRK44 Yes I did, here is my full webpack.config.js – Christian Vincenzo Traina Commented May 31, 2019 at 8:58
  • @VadimHulevich this is not what I want, I can't use any framework (otherwise I wasn't getting crazy with webpack :D) and, in the end, everything I want is just executing a innerHTML. So any framework - also small - would be an overkill – Christian Vincenzo Traina Commented May 31, 2019 at 8:59
Add a ment  | 

3 Answers 3

Reset to default 2

Well, transforming a string to html is easy. So if you get a string reposonse back for your template you can transform it to a DOM structure like below.

/** 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>

You can then do transformation on the 'children' as well, just as you would with a normal DOM tree object.

Believe it or not this is not a mon use case, importing html files into JavaScript and displaying them sounds like a workaround or a mid-port hack. JavaScript libraries are used to generate dynamic html on the the fly in the browser in response to user input. If this is what you want you should be using React, Vue, Angular, jQuery or similar.

As others have mentioned, the solution to your problem is not to look for a loader that converts HTML into a DOM node, it's for you to do it yourself. The DOM is not present till code is executed in the browser, It's not a pile time transformation. It's a run-time transformation.

import template from 'src/test.html'

const html = document.createElement('div')
html.innerHTML = template

A loader simply cannot do what you ask for. The browser is responsible for parsing HTML and building the DOM tree based on it's platform and vendor specific implementation. querySelector or createElement are API methods for us to access this browser functionality. But we do not own DOM nodes in our code. They are created for us by the platform. Our JavaScript is merely consuming it.

There are some solutions such as DOMParser and jsDOM that can do this on the server. But they are inplete implementations of the browser DOM and they should not be brought into front-end code meant to be shipped to the browser. They are meant to be used for things such as headless testing, web crawling and other forms of machine consumption of web pages.

If you can present a specific scenario where you cannot have a HTML string parsed in the browser along with the rest of the code and just before it is consumed by JavaScript, by all means show us and we will present a solution. But It is highly likely that you have misunderstood the roles of JavaScript, Webpack, and HTML and the relationship between them.

TLDR: HTML is a string that gets sent to the browser via HTTP and the browser decides how to build a DOM tree based on it's vendor specific implemenation. In front end code there is no alternative except to get the browser to build a DOM tree for you with a string you provide and then consume it with the DOM Api.

To me it seems like the posthtml-loader is primarily a tool that helps to "prepare" your HTML during the build. Its parser options allow you to break in to the string -> PostHTML AST Tree step, and its plugin options allow you to modify the tree. Then, it stringifies back to HTML.

I couldn't find an option in the webpack plugin to return the interim tree format.


You could write a small custom loader to parse HTML strings to DOM objects:

// 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; 
  }())`;
};

Then, in your webpack.config.js, you can tell webpack to make .html files pass this loader:

// 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' ]
      }
    ]
  }
};

Now, whenever you type something like const template = require('./template.html'); you'll get an HTMLCollection instance rather than just a string.


Note that this loader adds a dependency to DOMParser, which is only available in the browser. You could replace it by something like jsdom if you want to run in non-browser environments.

发布评论

评论列表(0)

  1. 暂无评论