Webpack: скомпилировать папку, но сохранить отдельные файлы?

#javascript #webpack #yarnpkg #nunjucks

#javascript #веб-пакет #yarnpkg #nunjucks #webpack

Вопрос:

У меня есть Webpack config, который компилирует файлы nunjuck в HTML-файлы. Однако мне приходится указывать ввод и вывод каждого отдельного файла вручную. Я не могу понять, как 1) прочитать все файлы в данной папке И 2) вывести отдельные скомпилированные файлы в другую папку, вот так:

 src/file1.njk -> dist/file1.html
src/file2.njk -> dist/file2.html
...
  

это мой конфигурационный файл:

 const path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var glob_entries = require("webpack-glob-folder-entries");

// Optional, but highly recommended. Create a returnEntries:
// Webpack doesn't support glob paths. For the nunjucks-html-loader
// we need each path to be specified for it to work (YES, even subdirectories!)

function returnEntries(globPath) {
  let entries = glob_entries(globPath, true);
  let folderList = new Array();
  for (let folder in entries) {
    folderList.push(path.join(__dirname, entries[folder]));
  }
  return folderList;
}

module.exports = {
  entry: "./src/app.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist")
  },
  plugins: [
    // HtmlWebpackPluginConfig
    new HtmlWebpackPlugin({
      filename: "index.html",
      inject: "body",
      template: "nunjucks-html-loader!./src/pages/index.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "1-categorize-devices.html",
      inject: "body",
      template: "nunjucks-html-loader!./src/pages/1-categorize-devices.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "2-split-to-triggers-vs-actors.html",
      inject: "body",
      template:
        "nunjucks-html-loader!./src/pages/2-split-to-triggers-vs-actors.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "3-generate-all-combinations.html",
      inject: "body",
      template:
        "nunjucks-html-loader!./src/pages/3-generate-all-combinations.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "4-rate-all-combinations.html",
      inject: "body",
      template: "nunjucks-html-loader!./src/pages/4-rate-all-combinations.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "5-cluster-useful-combinations.html",
      inject: "body",
      template:
        "nunjucks-html-loader!./src/pages/5-cluster-useful-combinations.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "6-scenes-for-given-packages.html",
      inject: "body",
      template:
        "nunjucks-html-loader!./src/pages/6-scenes-for-given-packages.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "7-design-templates.html",
      inject: "body",
      template: "nunjucks-html-loader!./src/pages/7-design-templates.njk"
    }),
    new HtmlWebpackPlugin({
      filename: "8-functional-prototype.html",
      inject: "body",
      template: "nunjucks-html-loader!./src/pages/8-functional-prototype.njk"
    })
  ],
  module: {
    rules: [
      {
        test: /.(scss)$/,
        use: [
          {
            // Adds CSS to the DOM by injecting a `<style>` tag
            loader: "style-loader"
          },
          {
            // Interprets `@import` and `url()` like `import/require()` and will resolve them
            loader: "css-loader"
          },
          {
            // Loader for webpack to process CSS with PostCSS
            loader: "postcss-loader",
            options: {
              plugins: function() {
                return [require("autoprefixer")];
              }
            }
          },
          {
            // Loads a SASS/SCSS file and compiles it to CSS
            loader: "sass-loader"
          }
        ]
      },
      {
        // HTML LOADER
        // Super important: We need to test for the html
        // as well as the nunjucks files
        test: /.html$|njk|nunjucks/,
        use: [
          "html-loader",
          {
            loader: "nunjucks-html-loader",
            options: {
              // Other super important. This will be the base
              // directory in which webpack is going to find
              // the layout and any other file index.njk is calling.
              //  searchPaths: [...returnEntries('./src/pages/**/')]
              // Use the one below if you want to use a single path.
              searchPaths: ["./src/pages"]
            }
          }
        ]
      }
    ]
  }
};
  

Как вы можете видеть, я продолжаю повторять new HtmlWebpackPlugin() и не могу понять, как автоматизировать операцию.

Большое вам спасибо.

Ответ №1:

Согласно HtmlWebpackPlugin документам, то, что вы делаете, на самом деле является рекомендуемым подходом (который, очевидно, отстой).

Но что вы можете сделать вместо того, чтобы перечислять их один за другим вручную, вот так, написать вспомогательную функцию, которая будет принимать список файлов для преобразования (скажем, с помощью подстановочного знака glob) и выводить массив HtmlWebpackPlugin инструкций, которые вы можете отправить непосредственно в webpack config.

Это всего лишь JS. Конфигурация Webpack — это просто скрипт NodeJS. Вы можете делать все, что вам нравится.

Ответ №2:

Что-то вроде этого должно сработать:

  const glob = require('glob');


 const pages = glob.sync('**/*.njk', {
    cwd: path.join(__dirname, 'src/pages/'),
    root: '/',
  }).map(page =>
    new HtmlWebpackPlugin({
      filename: page.replace('njk', 'html'),
      template: `src/pages/${page}.njk`,
    }));
  

Затем использовать его:

 plugins: [
  ...pages,