简体   繁体   English

将 JS/CSS/HTML 合并为单个 HTML

[英]Merging JS/CSS/HTML into single HTML

I have a small local web-application of 2 HTML files, 6 CSS files and 11 JS files.我有一个包含 2 个 HTML 文件、6 个 CSS 文件和 11 个 JS 文件的小型本地 Web 应用程序。

  1. Would the web-application still work if all of these files were (properly) copy-pasted in a single HTML file, eg putting the JS in <script> tags in the header, and putting the CSS in <style> tags?如果将所有这些文件(正确)复制粘贴到单个 HTML 文件中,例如将 JS 放在标头中的<script>标记中,并将 CSS 放在<style>标记中,Web 应用程序是否仍然可以工作?

  2. Does anyone know of a tool that could automatically and safely merge a collection of JS, CSS and HTML files into a single HTML?有谁知道可以自动、安全地将一组 JS、CSS 和 HTML 文件合并到一个 HTML 中的工具?

Searching online, I only found tools that can combine or minify files of one type at a time, but not create the merged HTML file (eg AIOM+ , HTMLcompressor . I did find this application called Inliner , but it seems it runs on Node.js, with which I'm not familiar and don't currently use.在网上搜索,我只发现可以一次合并或缩小一种类型文件的工具,但不能创建合并的 HTML 文件(例如AIOM+HTMLcompressor 。我确实找到了这个名为Inliner 的应用程序,但它似乎在 Node.js 上运行,我不熟悉,目前不使用。

In short, I'm looking for either a simple standalone tool that could read all the linked files in the HTML, and rewrite the HTML by appending those files' content.简而言之,我正在寻找一个简单的独立工具,它可以读取 HTML 中的所有链接文件,并通过附加这些文件的内容来重写 HTML。 If that's asking too much, then just a confirmation that manually doing the job would result in a working file, or any tips to think about when doing so.如果这要求太多,那么只需确认手动完成工作会产生工作文件,或者在这样做时要考虑的任何提示。 Thanks!谢谢!

I wrote a simple python script for it.我为它写了一个简单的python脚本。

This is my tree:这是我的树:

root-folder
├── index.html
├── build_dist.py
├── js
│   └── somescript.js
├── css
│   ├── styles1.css
│   └── styles2.css
└── dist

I run the script:我运行脚本:

cd root-folder
python build_dist.py

And a oneindex.html file is created in the dist folder.并且在 dist 文件夹中创建了一个 oneindex.html 文件。
This file contains all the js and css from the files specified with link and script tags in index.html.该文件包含 index.html 中使用linkscript标记指定的文件中的所有 js 和 css。
You can use this file anywhere.您可以在任何地方使用此文件。

Note:注意:

  1. The HTML file must be "index.html" in the root folder. HTML 文件必须是根文件夹中的“index.html”。
  2. It only works for a single HTML file.它仅适用于单个 HTML 文件。 I don't know what you want to do with multiple HTML files.我不知道你想用多个 HTML 文件做什么。

build_dist.py code: build_dist.py 代码:

# build_dist.py

from bs4 import BeautifulSoup
from pathlib import Path
import base64

original_html_text = Path('index.html').read_text(encoding="utf-8")
soup = BeautifulSoup(original_html_text)

# Find link tags. example: <link rel="stylesheet" href="css/somestyle.css">
for tag in soup.find_all('link', href=True):
    if tag.has_attr('href'):
        file_text = Path(tag['href']).read_text(encoding="utf-8")

        # remove the tag from soup
        tag.extract()

        # insert style element
        new_style = soup.new_tag('style')
        new_style.string = file_text
        soup.html.head.append(new_style)


# Find script tags. example: <script src="js/somescript.js"></script>
for tag in soup.find_all('script', src=True):
    if tag.has_attr('src'):
        file_text = Path(tag['src']).read_text()

        # remove the tag from soup
        tag.extract()

        # insert script element
        new_script = soup.new_tag('script')
        new_script.string = file_text
        soup.html.body.append(new_script)

# Find image tags.
for tag in soup.find_all('img', src=True):
    if tag.has_attr('src'):
        file_content = Path(tag['src']).read_bytes()

        # replace filename with base64 of the content of the file
        base64_file_content = base64.b64encode(file_content)
        tag['src'] = "data:image/png;base64, {}".format(base64_file_content.decode('ascii'))

# Save onefile
with open("dist/oneindex.html", "w", encoding="utf-8") as outfile:
    outfile.write(str(soup))

You could consider using webpack .您可以考虑使用webpack It is not easy to understand at first but this is a good tutorial to start with.一开始不容易理解,但这是一个很好的入门教程

1. 1.

Generally, yes一般来说,是的

2. 2.

I don't know of merging multiple html files, but我不知道合并多个 html 文件,但是
Here is a Python script (Github) for merging css/js/images into one single html file.这是一个 Python 脚本 (Github),用于将 css/js/images 合并到一个 html 文件中。 In addition to Noam Nol's answer..除了诺姆诺尔的回答..

  • ... it does not have external dependencies ...它没有外部依赖项
  • ... it will also handle non-png images properly. ...它还将正确处理非png图像。

Usage: python3 htmlmerger yourfile.html用法: python3 htmlmerger yourfile.html

Code from github: htmlmerger.py来自 github 的代码: htmlmerger.py

Below is the content from the file on Github.以下是 Github 上文件的内容。

from html.parser import HTMLParser
import os
import sys
import base64


gHelp = """
Merge JS/CSS/images/HTML into one single file
Version: 1.0

Usage:
  htmlmerger inputfile [optional: outputfile]

"""


def getFileContent (strFilepath):
  content = ""
  with open (strFilepath, "r") as file:
    content = file.read ()
  return content



def getFileContentBytes (strFilepath):
  content = b""
  with open (strFilepath, "rb") as file:
    content = file.read ()
  return content


class HtmlMerger(HTMLParser):
  """
    Call "run(htmlContent, basedir)"  to merge
    script/css/images referenced withing htmlContent
    into one single html file.
  """
  def __init__(self):
    super().__init__()
    self._result = ""
    self._additionalData = ""
    self._baseDir = ""
    self.messages = []



  def _addMessage_fileNotFound(self, file_asInHtmlFile, file_searchpath):
    self.messages.append ("Error: Line " + str (self.getpos ()[0]) +
                        ": Could not find file `" + str (file_asInHtmlFile) +
                        "`; searched in `" + str (file_searchpath) + "`." )



  def _getAttribute (self, attributes, attributeName):
    """Return attribute value or `None`, if not existend"""
    for attr in attributes:
      key = attr[0]
      if (key == attributeName):
        return attr[1]
    return None


  def _getFullFilepath (self, relPath):
    return os.path.join (self._baseDir, relPath)


  def handle_starttag(self, tag, attrs):

    # Style references are within `link` tags. So we have to
    #  convert the whole tag
    if (tag == "link"):
      href = self._getAttribute (attrs, "href")
      if (href):
        hrefFullPath = self._getFullFilepath (href)
        if (not os.path.isfile (hrefFullPath)):
          self._addMessage_fileNotFound (href, hrefFullPath)
          return
        styleContent = getFileContent (hrefFullPath)
        self._result += "<style>" + styleContent + "</style>"
        return

    self._result += "<" + tag + " "

    for attr in attrs:
      key = attr[0]
      value = attr[1]

      # main work: read source content and add it to the file
      if (tag == "script" and key == "src"):
        #self._result += "type='text/javascript'"
        strReferencedFile = self._getFullFilepath (value)
        if (not os.path.isfile (strReferencedFile)):
          self._addMessage_fileNotFound (value, strReferencedFile)
          continue
        referencedContent = getFileContent (strReferencedFile)
        self._additionalData += referencedContent

        # do not process this key
        continue

      if (tag == "img" and key == "src"):
        imgPathRel = value
        imgPathFull = self._getFullFilepath (imgPathRel)
        if (not os.path.isfile (imgPathFull)):
          self._addMessage_fileNotFound (imgPathRel, imgPathFull)
          continue

        imageExtension = os.path.splitext (imgPathRel)[1][1:]
        imageFormat = imageExtension

        # convert image data into browser-undertandable src value
        image_bytes = getFileContentBytes (imgPathFull)
        image_base64 = base64.b64encode (image_bytes)
        src_content = "data:image/{};base64, {}".format(imageFormat,image_base64.decode('ascii'))
        self._result += "src='" + src_content + "'"

        continue



      # choose the right quotes
      if ('"' in value):
        self._result += key + "='" + value + "' "
      else:
        self._result += key + '="' + value + '" '

    self._result +=  ">"

  def _writeAndResetAdditionalData(self):
    self._result += self._additionalData
    self._additionalData = ""

  def handle_endtag(self, tag):
    self._writeAndResetAdditionalData ()
    self._result += "</" + tag + ">"


  def handle_data(self, data):
    self._result += data

  def run(self, content, basedir):
    self._baseDir = basedir
    self.feed (content)
    return self._result



def merge(strInfile, strOutfile):

  if (not os.path.isfile (strInfile)):
    print ("FATAL ERROR: file `" + strInfile + "` could not be accessed.")
    return

  baseDir = os.path.split (os.path.abspath (strInfile))[0]

  #read file
  content = getFileContent (strInfile)

  parser = HtmlMerger()
  content_changed = parser.run (content, baseDir)

  # log errors
  if (len (parser.messages) > 0):
    print ("Problems occured")
    for msg in parser.messages:
      print ("  " + msg)
    print ("")

  # debug:
  if (False):
    print (content_changed)
    exit ()


  # write result
  with open (strOutfile, "w") as file:
    file.write (content_changed)



def main():
  args = sys.argv[1:] # cut away pythonfile
  if (len (args) < 1):
    print (gHelp)
    exit()

  inputFile = args[0]

  # get output file name
  outputFile = ""
  if (True):
    outputFile = os.path.splitext (inputFile)[0] + "_merged.html"

    if (len (args) > 1):
      outputFile = args[1]

    if (os.path.isfile (outputFile)):
      print ("FATAL ERROR: Output file " + outputFile + " does already exist")
      exit ()

  # run the actual merge
  merge (inputFile, outputFile)


main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM