Search code examples
wordpresswebpackworkflow

How to Configure WordPress with Webpack to have Seperate Build Folders for Css and JS


I am using Webpack from @wordpress/scripts in my WordPress Child theme. By default, the output files are generated inside the build folder. However, I would like to change the output path. I would like to separate my compiled js and CSS files into different subfolders inside the build folder, e.g. build/css and build/js. How can I do this? This is the Webpack configuration I am using:

webpack.config.js

/**
 * External Dependencies
 */
const path = require( 'path' );
const FixStyleOnlyEntriesPlugin = require( 'webpack-fix-style-only-entries' );
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );

/**
 * WordPress Dependencies
 */
const defaultConfig = require( '@wordpress/scripts/config/webpack.config.js' );

module.exports = {
    ...defaultConfig,
    ...{
        entry: {
            main: path.resolve( process.cwd(), 'src/scss', 'main.scss' ),
            app: path.resolve( process.cwd(), 'src/js', 'app.js' ),
        },
    },
    plugins: [ new FixStyleOnlyEntriesPlugin(), new MiniCssExtractPlugin() ],
};

Solution

  • Set multiple outputs in Webpack

    There are two ways you can achieve this:

    1. Using multi-compiler This example is from webpack repository from github: https://github.com/webpack/webpack/blob/main/examples/multi-compiler/webpack.config.js

    var path = require("path");
    var webpack = require("../../");
    
    module.exports = [
        {
            name: "mobile",
            // mode: "development || "production",
            entry: "./example",
            output: {
                path: path.join(__dirname, "dist"),
                filename: "mobile.js"
            },
            plugins: [
                new webpack.DefinePlugin({
                    ENV: JSON.stringify("mobile")
                })
            ]
        },
    
        {
            name: "desktop",
            // mode: "development || "production",
            entry: "./example",
            output: {
                path: path.join(__dirname, "dist"),
                filename: "desktop.js"
            },
            plugins: [
                new webpack.DefinePlugin({
                    ENV: JSON.stringify("desktop")
                })
            ]
        }
    ];
    

    2. Using entry-descriptor

    This the one is use and have tested. Below check out how your webconfig.js should be configured:

    /**
     * External Dependencies
     */
    const path = require( 'path' );
    const FixStyleOnlyEntriesPlugin = require( 'webpack-fix-style-only-entries' );
    const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
    
    /**
     * WordPress Dependencies
     */
    const defaultConfig = require( '@wordpress/scripts/config/webpack.config.js' );
    
    
    module.exports = {
      ...defaultConfig,
      ...{
        entry: {
          'css/main': path.resolve( process.cwd(), 'src/scss', 'main.scss' ),
          'js/app': path.resolve( process.cwd(), 'src/js', 'app.js' ),
        },
        output: {
          filename: '[name].js',
          path: path.resolve(__dirname, 'build')
        },
      }
      plugins: [
        ...defaultConfig.plugins,
        new FixStyleOnlyEntriesPlugin(),
        new MiniCssExtractPlugin() 
      ],
    }
    

    NB 1: When you use path: resolve( process.cwd(), 'build' ) in the output, the build folder becomes your root folder.

    NB 2: Also notice the way i have extended the plugins for your additional plugins.

    Kindly follow this thread for more explanations: How to create multiple output paths in Webpack config