Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenate JS files after webpack build process

I'm trying to concatenate two js files after the webpack build process. The goal is to provide a single js file with the ES6 modules and the legacy code in it.

Already tried plugins like webpack-concat-files-plugin without success. Which makes sense to me, because the output files are not there when the plugin gets executed.

Another thought would be a small script executed in the afterCompile hook, which handles the concatenation of the two files. Is this the common way to do something like this or are there other ways to achieve the goal?

Thanks for your help.


Basic example:

module.exports = {
  entry: {
    app: 'app.js',
    legacy: [
      'legacy-1.js',
      'legacy-2.js', 
      // ...
    ]
  },
  output: {
    filename: path.join('dist/js', '[name].js'),
  }
}
like image 581
Robin Avatar asked Oct 19 '25 11:10

Robin


2 Answers

Solved this as suggested:

FileMergeWebpackPlugin.js

const fs = require('fs');

class FileMergeWebpackPlugin {
  constructor({ files, destination, removeSourceFiles }) {
    this.files = files;
    this.destination = destination;
    this.removeSourceFiles = removeSourceFiles;
  }

  apply(compiler) {
    compiler.hooks.afterEmit.tap('FileMergeWebpackPlugin', () => {
      const fileBuffers = [];

      this.files
        .filter(file => fs.existsSync(file))
        .forEach(file => fileBuffers.push(fs.readFileSync(file)))

      fs.writeFileSync(this.destination, fileBuffers.concat(), { encoding: 'UTF-8' })

      if (this.removeSourceFiles) {
        this.files.forEach(file => fs.unlinkSync(file));
      }
    });
  }
}

module.exports = FileMergeWebpackPlugin;

webpack.config.js

const FileMergeWebpackPlugin = require('./FileMergeWebpackPlugin');

module.exports = {
  entry: {
    app: 'app.js',
    legacy: [
      'legacy-1.js',
      'legacy-2.js',
    ]
  },
  output: {
    filename: path.join('dist/js', '[name].js'),
  },
  plugins: [
    new FileMergeWebpackPlugin({
      destination: 'dist/js/bundle.js',
      removeSourceFiles: true,
      files: [
        'dist/js/app.js',
        'dist/js/legacy.js',
      ]
    })
  ]
}

Eventually i will release this as a npm package, will update the post when i do so

like image 106
Robin Avatar answered Oct 22 '25 02:10

Robin


Yes.

You can create your own Plugin that is activate in emit hook - the parameter for this hook is compilation. You can get the chunks you look to concat from this object and create a new chunk with the concated value (or just add one to the other)

like image 45
Raz Ronen Avatar answered Oct 22 '25 01:10

Raz Ronen