UNPKG

@batch/craft-webpack

Version:

Batch's Webpack setup made for the Craft Starter.

286 lines (272 loc) 7.29 kB
// webpack.prod.js - production builds const LEGACY_CONFIG = "legacy"; const MODERN_CONFIG = "modern"; // node modules const glob = require("glob-all"); const path = require("path"); const fs = require('fs'); const { merge } = require('webpack-merge'); const webpack = require("webpack"); // webpack plugins const rimraf = require("rimraf"); const CompressionPlugin = require("compression-webpack-plugin"); const ImageminWebpWebpackPlugin = require("imagemin-webp-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const TerserPlugin = require("terser-webpack-plugin"); const zopfli = require("@gfx/zopfli"); // config files const common = require("./webpack.common.js"); let settings = require("./webpack.settings.js"); if (fs.existsSync(path.resolve(process.cwd(), './webpack.settings.js'))) { let projectSettings = require(path.resolve(process.cwd(), './webpack.settings.js')); settings = merge(settings, projectSettings); } let projectConfig = {}; if (fs.existsSync(path.resolve(process.cwd(), 'webpack.config.js'))) { projectConfig = require(path.resolve(process.cwd(), 'webpack.config.js')); } // Clean build assets before continuing rimraf(path.resolve(settings.paths.working, settings.paths.dist.base), {}, () => console.log("\n\nRemoved all previous build assets.\n") ); // Configure Compression webpack plugin const configureCompression = () => { return { filename: "[path].gz[query]", test: /\.(js|css|html|svg)$/, threshold: 10240, minRatio: 0.8, deleteOriginalAssets: false, compressionOptions: { numiterations: 15, level: 9, }, algorithm(input, compressionOptions, callback) { return zopfli.gzip(input, compressionOptions, callback); }, }; }; // Configure Image loader const configureImageLoader = (buildType) => { if (buildType === LEGACY_CONFIG) { return { test: /\.(png|jpe?g|gif|webp)$/i, use: [ { loader: require.resolve("file-loader"), options: { name: "img/[name].[hash].[ext]", }, }, ], }; } if (buildType === MODERN_CONFIG) { return { test: /\.(png|jpe?g|gif|webp)$/i, use: [ { loader: require.resolve("file-loader"), options: { name: "img/[name].[hash].[ext]", }, }, { loader: require.resolve("img-loader"), options: { plugins: [ require("imagemin-gifsicle")({ interlaced: true, }), require("imagemin-mozjpeg")({ progressive: true, arithmetic: false, }), require("imagemin-optipng")({ optimizationLevel: 5, }), require("imagemin-svgo")({ plugins: [{ convertPathData: false }], }), ], }, }, ], }; } }; // Configure SVG loader const configureSvgLoader = (buildType) => { if (buildType === LEGACY_CONFIG) { return { test: /\.svg$/, oneOf: [ { loader: require.resolve("vue-svg-loader"), }, { resourceQuery: /external/, loader: require.resolve("file-loader"), query: { name: "img/[name].[hash].[ext]", }, }, ], }; } if (buildType === MODERN_CONFIG) { return { test: /\.svg$/, oneOf: [ { loader: require.resolve("vue-svg-loader"), }, { resourceQuery: /external/, use: [ { loader: require.resolve("file-loader"), query: { name: "img/[name].[hash].[ext]", }, }, { loader: require.resolve("img-loader"), options: { plugins: [ require("imagemin-svgo")({ plugins: [{ convertPathData: false }], }), ], }, }, ], }, ], }; } }; // Configure optimization const configureOptimization = (buildType) => { if (buildType === LEGACY_CONFIG) { return { splitChunks: { cacheGroups: { default: false, common: false, styles: { name: settings.vars.cssName, test: /\.(pcss|css|vue)$/, chunks: "all", enforce: true, }, }, }, minimizer: [ new TerserPlugin(configureTerser()), new OptimizeCSSAssetsPlugin({ cssProcessorOptions: { map: { inline: false, annotation: true, }, safe: true, discardComments: true, }, }), ], }; } if (buildType === MODERN_CONFIG) { return { minimizer: [new TerserPlugin(configureTerser())], }; } }; // Configure Postcss loader const configurePostcssLoader = (buildType) => { if (buildType === LEGACY_CONFIG) { return { test: /\.(css)$/, use: [ MiniCssExtractPlugin.loader, { loader: require.resolve("css-loader"), options: { importLoaders: 2, sourceMap: true, }, }, { loader: require.resolve("resolve-url-loader"), }, { loader: require.resolve("postcss-loader"), options: { sourceMap: true, }, }, ], }; } // Don't generate CSS for the modern config in production if (buildType === MODERN_CONFIG) { return { test: /\.(pcss|css)$/, loader: require.resolve("ignore-loader"), }; } }; // Configure terser const configureTerser = () => { return { cache: true, parallel: true, sourceMap: true, }; }; // Production module exports module.exports = [ merge(common.legacyConfig, { output: { filename: path.join("./js", "[name]-legacy.[chunkhash].js"), }, mode: "production", devtool: "source-map", optimization: configureOptimization(LEGACY_CONFIG), module: { rules: [ configurePostcssLoader(LEGACY_CONFIG), configureImageLoader(LEGACY_CONFIG), configureSvgLoader(LEGACY_CONFIG), ], }, plugins: [ new MiniCssExtractPlugin({ path: path.resolve(settings.paths.working, settings.paths.dist.base), filename: path.join("./css", "[name].[chunkhash].css"), }), new CompressionPlugin(configureCompression()), ], }, projectConfig), merge(common.modernConfig, { output: { filename: path.join("./js", "[name].[chunkhash].js"), }, mode: "production", devtool: "source-map", optimization: configureOptimization(MODERN_CONFIG), module: { rules: [ configurePostcssLoader(MODERN_CONFIG), configureImageLoader(MODERN_CONFIG), configureSvgLoader(LEGACY_CONFIG), ], }, plugins: [ new ImageminWebpWebpackPlugin(), new CompressionPlugin(configureCompression()), ], }, projectConfig), ];