0

这是我的 webpack 配置的相关部分:

plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      hash: false, // for testing purposes
      minify: false,
    }),    
  ]

尽管如此minify: false,如果mode: 'production'. 如果mode: 'development',那么它是多行。如果我更改hash: true,那么它会变成一行,其中包含用于缓存清除的查询字符串哈希,这证明它读取了此配置对象。

但为什么它会截断换行符?我试图指定一个对象和集合collapseWhitespace以及其他道具而不是minify: false,但它也没有效果,仍然使它成为一行。以下是 package.json 的版本列表:

"devDependencies": {
    "@babel/cli": "^7.14.5",
    "@babel/core": "^7.14.6",
    "@babel/preset-env": "^7.14.5",
    "babel-loader": "^8.2.2",
    "babel-plugin-angularjs-annotate": "^0.10.0",
    "css-loader": "^5.2.6",
    "css-minimizer-webpack-plugin": "3.0.1",
    "html-loader": "^2.1.2",
    "html-webpack-plugin": "5.3.1",
    "mini-css-extract-plugin": "1.6.0",
    "postcss": "^8.3.4",
    "style-loader": "^2.0.0",
    "webpack": "5.39.0",
    "webpack-cli": "4.7.2",
    "webpack-dev-server": "3.11.2",
    "webpack-merge": "^5.8.0"
  }

编辑:为了澄清,我指的是 webpack 插入的动态包含之间的换行符的截断,这是对捆绑的 JS 和 CSS 文件的引用。无论是生产版本还是开发版本,所有这些文件都恰好出现在一行中。似乎没有办法将它们逐行拆分,就好像它们是人类小心插入的一样。

为什么将每个动态包含在自己的行中很有用?例如,如果您想检查订单。目前唯一的选择是向左/向右滚动并尝试记住屏幕外出现的内容,这比从上到下阅读列表更具认知负荷,所有内容都适合一个屏幕而不滚动。

4

1 回答 1

1

我看到您正在使用html-loader。我的猜测是,自从您设置以来,在您的案例中进行缩小的不是HtmlWebpackPluginminify: false,而是html-loader

为了阻止html-loader缩小,我们可以这样设置:

test: /\.html$/,
use: {
  loader: "html-loader",
  options: {
    minimize: false,
  },
}

但是,由于您还希望将.js.css包含在生成的.html文件中的不同行中,因此我们遇到了问题。它们在同一行的原因是它们是由HtmlWebpackPlugin注入的,一开始没有任何换行符。据我所知,我们没有可以设置的选项。

解决方案 1

步骤1

我发现的最佳解决方案是使用EJS ( https://ejs.co/ ) 而不是纯 html 创建我们的模板文件。这使我们可以将 javascript 直接写入模板,并让我们完全控制包含的注入方式。看到这个答案。

首先将您的 html 模板文件重命名为 template.ejs 之类的文件</head>接下来在结束标签之前添加这个:

for (const tag of htmlWebpackPlugin.tags.headTags) { %>
  <%= tag %><%
} %>

确保不要启用自动格式,因为我们依靠此处的换行符来生成正确的输出格式。根据您使用的 HtmlWebpackPlugin 版本,除了headTags之外,您还可以使用bodyTags。在我看来,至少在最新版本中,他们选择将脚本包含在带有defer标志的头部以延迟执行,据我所知,这也是最高效的方法。

第2步

接下来,我们需要在HtmlWebpackPlugin选项中更改模板的路径,并禁用包含的自动注入,如下所示:

new HtmlWebpackPlugin({
  template: "./src/template.ejs",
  inject: false
}),

第 3 步

由于HtmlWebpackPlugin有一个内置的后备.ejs解析器,我们不需要为此安装任何额外的加载器。唯一的问题是,由于您使用的是html-loader我假设您的模板文件中有资产,例如图像等。如果您要创建一个新规则来测试.ejs文件并使用html-loader来处理它们确实可以将硬编码的src包含替换为动态的,因为这是加载程序的目的。但是,为.ejs文件指定加载器会阻止HtmlWebpackPlugin使用它的后备解析器,因此所有模板变量(其中的那些<% %>)都不会被解析。

然而,我们实际上根本不需要html-loader。相反,您可以做的是使用EJS在模板文件中要求您的资产,如下所示:

<img src="<%= require('./assets/myimage.jpg') %>" />

解决方案 2

如果由于某种原因您需要/更喜欢使用html-loader而不是另一种解决问题的方法。

由于HtmlWebpackPlugin在html-loader被激活时不会使用它的后备 EJS 解析器,我们需要使用另一个加载器来解析它,称为ejs-loader。不过有一个小问题:当html-loader解析模板文件时,它会生成javascript。由于ejs-loader不期望接收 javascript,我们需要先将其转换回 EJS 格式。这可以通过另一个名为extract-loader 的加载器来完成。

解决方案 1中的步骤 1开始。接下来我们需要安装两个新的加载器:

yarn add -D ejs-loader extract-loader

之后,我们将它们添加到webpack 配置中的模块规则中。确保将esModule也为html-loader设置为false ,因为 extract-loader 无法处理:

module: {
rules: [
  {
    test: /\.ejs$/,
    use: [
    {
      loader: "ejs-loader",
      options: {
        esModule: false
      }
      },
      'extract-loader',
      {
      loader: "html-loader",
      options: {
        esModule: false
      },
    }]
  },

  ...

此设置从html-loader开始,它会自动解析任何src包含并将其转换为require语句。它生成提取加载程序转换回EJS的javascript代码。最后ejs-loader解析模板变量,在这种情况下js / css的列表包括。

于 2021-11-22T14:37:16.103 回答