Webpack - Создание нескольких выходных файлов из шаблона так же, как Grunt - PullRequest
4 голосов
/ 20 марта 2020

Я уже некоторое время использую Grunt, но теперь я перешел к веб-пакету, так как начинаю модульную обработку и модернизацию некоторых JS.

Это не очень большой проект и кажется, что и кряк, и веб-пакет кажутся излишним. Я понимаю, что webpack не является заменой grunt, может быть, есть какой-то разумный способ использовать оба, или, может быть, я недостаточно опытен в webpack, чтобы выполнять все задачи таким образом. Я хотел бы использовать только один, но если я не в состоянии, то мне придется оставить их обоих.

Итак, дело в том, что в Grunt (используя grunt-replace) я могу из файла «шаблона» замените некоторые переменные в конфигурации grunt на множество выходных файлов, как это взято из следующего фрагмента моего файла gruntfile.

       app1: {
        options: {
          patterns: [
            {
              match: 'FOO',
              replacement: '<%= grunt.config.get("foo_1") %>'
            },
            {
              match: 'BAR',
              replacement: '<%= grunt.config.get("bar_1") %>'
            }
          ]
        },
        src: '/myTemplate.js',
        dest: '/sw-1.js'
      },
      app2: {
        options: {
          patterns: [
            {
              match: 'FOO',
              replacement: '<%= grunt.config.get("foo_2") %>'
            },
            {
              match: 'BAR',
              replacement: '<%= grunt.config.get("bar_2") %>'
            }
          ]
        },
        src: '/myTemplate.js',
        dest: '/sw-2.js'
      },

Здесь «myTemplate. js» содержит некоторые заполнители, которые заменяются из значений конфигурации "foo_x", "bar_x" также основаны на среде.

В веб-пакете я смог использовать DefinePlugin и DotEnv для установки некоторых значений в соответствии с environement (ie, URL-адреса API, которые отличаются в зависимости от dev или производство). Я хотел бы вывести некоторые файлы на основе того же принципа, который описан здесь.

РЕДАКТИРОВАТЬ: Графически,

myTemplate.js 
    |
    |
 Webpack
    |
(outputs)
    |-------> sw-1.js (FOO is replaced in this file and this environment with "foo_1", the same happens with BAR).
    |
    |
    |-------> sw-1.js (FOO is replaced here in this file/environment with "foo_2".)

Таким образом, из одного файла шаблона, два вывода создаются как grunt -replace плагин делает в размещенном фрагменте.

Итак, возможно ли это сделать с помощью веб-пакета, или я должен продолжать выполнять ту часть рабочего процесса с той же рабочей конфигурацией, что и сейчас?

Спасибо!

PS: я включаю webpack.config для более подробного объяснения того, как я это делаю.

webpack.common. js

const path = require('path');
    const dotenv = require('dotenv');
    const fs = require('fs');
    const webpack = require('webpack');
    const {CleanWebpackPlugin} = require('clean-webpack-plugin');

module.exports = (env) => {
  const currentPath = path.join(__dirname);
  const basePath = currentPath + '/.env';
  const envPath = basePath + '.' + env.ENVIRONMENT;
  const finalPath = fs.existsSync(envPath) ? envPath : basePath;
  const fileEnv = dotenv.config({ path: finalPath }).parsed;

  // reduce it to a nice object, the same as before
  const envKeys = Object.keys(fileEnv).reduce((prev, next) => {
    prev[`process.env.${next}`] = JSON.stringify(fileEnv[next]);
    return prev;
  }, {});

  return {
    mode: 'development',
    entry: {
      //index: './src/index.js',
      titanpush: './src/titanpush.js',
    },
    devtool: 'inline-source-map',
    plugins: [
      new CleanWebpackPlugin(),
      new webpack.DefinePlugin(envKeys),
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
  };
};

webpack.dev. js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');


module.exports = (env) => {
  return merge(common(env), {
    mode: 'development',
    devtool: 'inline-source-map',
    /*devServer: {
      contentBase: './dist',
    },*/
  });
};

И в пакете . json в сценариях у меня есть:

"build": "webpack --config webpack.dev.js --env.ENVIRONMENT=development"

1 Ответ

2 голосов
/ 25 марта 2020

Сразу же существует несколько способов:

  1. Иметь несколько конфигов Webpack, каждый для одного набора определений замен. Это, безусловно, более управляемый способ сделать то, что вы хотите, в зависимости от того, сколько целевых файлов (т.е. определить сопоставления) требует ваша конфигурация.

  2. Аналогично 1, используйте скрипт для вызова API компилятора webpack, а не нескольких вызовов командной строки. (пример показан ниже)

  3. Используйте более полноценную систему шаблонов. Если ваши отображения достаточно велики и сложны, возможно, более целесообразно инвестировать в более тщательную систему шаблонов + веб-сервер. Или даже генератор сайтов stati c, такой как jekyll / Hugo / gatsby, в зависимости от того, разрешают ли они такие генерации файлов на основе таблиц.


Использование сценария для запускать webpack несколько раз

Webpack можно использовать в JavaScript напрямую без CLI. Таким образом, вы можете написать сценарий, который получит и объединит сопоставления любым удобным для вас способом. Например, что-то вроде этого может занять список определений сопоставлений плагинов и выполнить этап компиляции веб-пакета несколько раз:

const webpack = require("webpack");
// base config without define plugin mappings, and entry setting
const yourConfig = require("./webpack.config.js");

let promises = [];

for (env in envs) {
    // update the config for every run
    const config = clone(yourConfig);
    config.plugins.push(new DefinePlugin(/* get mappings from env */));
    config.output.filename = env.outputfile;

    const compiler = webpack(config);
    let promise = new Promise((resolve, reject) => {
        compiler.run(err => {
            if (err) return reject(err);

            resolve();
        });
    });

    promises.push(promise);
}

// you'd have to add error handling here
Promise.all(promises).then(_ => {
    console.log("done");
});

// webpack.config.js
module.exports = {
    entry: "template.js",
    output: {
        filename: null,
        path: __dirname + "/dist"
    }
};
...