I can't figure out how to configure Image Minimizer Webpack Plugin so that images are converted to webp format if I use them in html.
This is not work using in html
img.image(src="./images/image.jpg?as=webp")
If I use images in css, then everything works.
div {
background: url("./file.jpg?as=webp");
}
This works.
I did everything according to the Documentation. I definitely missed something or didn't understand. Help me figure it out
Webpack config
const path = require("path");
const fs = require("fs");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const SVGSpritemapPlugin = require("svg-spritemap-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlBeautifyPlugin = require("#sumotto/beautify-html-webpack-plugin");
const miniSVGDataURI = require("mini-svg-data-uri");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
// Variables
const PATHS = {
src: path.join(__dirname, "../src"),
dist: path.join(__dirname, "../dist"),
assets: "assets"
}
const PAGES_DIR = `${PATHS.src}/views/pages/`
const PAGES = fs.readdirSync(PAGES_DIR).filter(fileName => fileName.endsWith(".pug"))
// Main config
module.exports = {
mode: "production",
devtool: false,
output: {
filename: "js/bundle.min.js",
path: PATHS.dist,
publicPath: "",
clean: true
},
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin(),
new ImageMinimizerPlugin({
generator: [
{
filter: (source, sourcePath) => {
// The `source` argument is a `Buffer` of source file
// The `sourcePath` argument is an absolute path to source
if (source.byteLength < 8192) {
return false;
}
return true;
},
// You can apply generator using `?as=webp`, you can use any name and provide more options
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: ["imagemin-webp"],
},
},
],
minimizer: {
implementation: ImageMinimizerPlugin.imageminMinify,
options: {
plugins: [
"imagemin-gifsicle",
"imagemin-mozjpeg",
"imagemin-pngquant",
"imagemin-svgo",
]
}
},
}),
]},
module: {
rules: [
{
test: /\.pug$/,
loader: "pug-loader",
options: {
pretty: true
}
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
}
},
"css-loader",
"postcss-loader",
"sass-loader"
],
},
{
test: /\.(png|jpeg|jpg|gif|svg|webp)$/i,
type: "asset/resource",
generator: {
filename: 'images/[name][ext]'
}
},
{
test: /\.svg$/,
type: "asset",
generator: {
dataUrl(content) {
content = content.toString();
return miniSVGDataURI(content);
}
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
generator: {
filename: "fonts/[name][ext]"
}
}
]
},
resolve: {
alias: {
"~": PATHS.src,
"~modules": `${PATHS.src}/views/modules`,
}
},
plugins: [
new SVGSpritemapPlugin(`${PATHS.src}/images/sprites/*.svg`,
{
output: {
filename: `/images/sprites.svg`,
svg: {
sizes: true
}
},
sprite: {
prefix: false,
generate: {
title: false,
use: true,
symbol: true,
}
},
styles: {
filename: `${PATHS.src}/styles/base/_sprites.scss`,
variables: {
sprites: "sprite",
sizes: "size"
},
}
}),
new MiniCssExtractPlugin({
filename: "css/[name].min.css"
}),
new CopyWebpackPlugin({
patterns: [
{ from: `${PATHS.src}/static`, to: "" },
{
from: `${PATHS.src}/images`,
to: "images",
globOptions: {
ignore: [
"**/images/*.webp"
]
}
},
]
}),
// Automatic creation any html pages (Don"t forget to RERUN dev server)
...PAGES.map(page => new HtmlWebpackPlugin({
template: `${PAGES_DIR}/${page}`,
filename: `./${page.replace(/\.pug/, ".html")}`,
inject: "body"
})),
new HtmlBeautifyPlugin({
end_with_newline: true,
indent_size: 2,
indent_with_tabs: true,
indent_inner_html: true,
preserve_newlines: true,
unformatted: ["p", "i", "b", "span"]
}),
Related
**I have two single-spa projects (root-config, app-hello) and I need to create a build so that the file name is the same in both root-config and app-hello. The problem is that when I run the proteins separately in the build I get different dates in the file name and for this I am looking for a way to build them together **
Webpack app-hello
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const Dotenv = require('dotenv-webpack');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
const singleSpaDefaults = require('webpack-config-single-spa-react');
const override = require('./config-overrides.js');
module.exports = (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName: 'app',
projectName: 'hello',
webpackConfigEnv,
argv,
override,
});
return merge(defaultConfig, {
resolve: {
extensions: ['.ts', '.tsx', '.js'],
preferRelative: true,
alias: {
containers: path.resolve(__dirname, 'src/containers'),
components: path.resolve(__dirname, 'src/components'),
layouts: path.resolve(__dirname, 'src/layouts'),
stores: path.resolve(__dirname, 'src/stores'),
hooks: path.join(__dirname, 'src/hooks'),
context: path.join(__dirname, 'src/context'),
assets: path.join(__dirname, 'src/assets'),
helpers: path.join(__dirname, 'src/helpers'),
},
plugins: [new TsconfigPathsPlugin({ configFile: './tsconfig.json' })],
},
devServer: {
port: 8500,
},
plugins: [
new Dotenv({
path: './.env.development',
}),
new FilterWarningsPlugin({
exclude:
/There are multiple modules with names that only differ in casing/,
}),
new CleanWebpackPlugin(),
],
output: {
path: path.resolve(__dirname, 'build'),
filename: `app-chat-${Date.now()}.js`,
assetModuleFilename: 'assets/[name][ext]',
},
module: {
rules: [
{
test: /\.m?js/,
type: 'javascript/auto',
resolve: {
fullySpecified: false,
},
},
{
test: /\.js$|jsx/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.json$/,
use: 'json-loader',
},
{
test: /\.svg$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['preact', 'env'],
},
},
{
loader: '#svgr/webpack',
options: { babel: false },
},
],
},
],
},
});
};
webpack root-config
const { merge } = require("webpack-merge");
const singleSpaDefaults = require("webpack-config-single-spa-ts");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = (webpackConfigEnv, argv) => {
const orgName = "app";
const defaultConfig = singleSpaDefaults({
orgName,
projectName: "root-config",
webpackConfigEnv,
argv,
disableHtmlGeneration: true,
});
return merge(defaultConfig, {
plugins: [
new HtmlWebpackPlugin({
inject: false,
template: "src/index.ejs",
templateParameters: {
isLocal: webpackConfigEnv && webpackConfigEnv.isLocal,
orgName,
hash: Date.now(),
},
}),
],
});
};
index root-config
<script type="systemjs-importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/react#17.0.2/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom#17.0.2/umd/react-dom.production.min.js",
"single-spa": "https://cdn.jsdelivr.net/npm/single-spa#5.9.0/lib/system/single-spa.min.js",
"#app/root-config": "https://login-7mpuan0pw5.s3.amazonaws.com/app-root-config.js",
"#app/chat": "https://login-7mpuan0pw5.s3.amazonaws.com/app-chat-<%= hash %>.js",
"#app/switcher": "https://login-7mpuan0pw5.s3.amazonaws.com/switcher/app-switcher-<%= hash %>.js"
}
}
</script>
Webpack is not actually my strength, I bumped into a problem today where I'm completeley stuck on a gigantic project.
Basically I just ran the webpack analyzer and our bundle size is way too big because we have around 200 SVGs in our project build.
I wanted to come up with a simple solution to decrease the bundle size and compress the SVG using webpack since that's what we are using.
After many failures I figured it would be as simple as it is to include
test: /\.(gif|png|jpe?g|svg)$/i,
type: 'asset/resource',
},
I can now see that my bundle is significantly decreased, however ALL my SVG's are hidden when I load up the project.
What could be the reason? Also what are the alternatives to compress SVG's using Webpack 5???
here is the whole webpack config
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const hashSubstr = '.[contenthash:8]';
const svgoPlugins = [
{ cleanUpAttrs: true },
{ removeDoctype: true },
{ removeXMLProcInst: true },
{ removeComments: true },
{ removeMetadata: true },
{ removeDesc: true },
{ removeEditorsNSData: true },
{ removeEmptyAttrs: true },
{ removeHiddenElems: true },
{ removeEmptyText: true },
{ removeEmptyContainers: true },
{ cleanupNumericValues: true },
{ moveElemsAttrsToGroup: true },
{ convertColors: { shorthex: true } },
];
module.exports = (env) => ({
entry: ['./scripts/responsive/index.ts', './scripts/pwa/serviceworker.ts'],
output: {
filename: `[name]${!env.development ? hashSubstr : ''}.js`,
globalObject: 'this',
path: path.resolve(__dirname, './bundles/responsive'),
publicPath: '/',
assetModuleFilename: '[hash][ext][query]',
},
mode: !env.development ? 'production' : 'development',
devtool: 'inline-source-map',
optimization: {
minimize: true,
},
module: {
rules: [
// {
// test: /\.(gif|png|jpe?g|svg)$/i,
// type: 'asset/resource',
// },
{
test: /\.(jsx?|tsx?)$/,
loader: 'babel-loader',
options: {
presets: ['#babel/typescript', '#babel/env'],
},
},
{
test: /\.s[ac]ss$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\-colou?r\.svg$/,
type: 'asset/resource',
include: [path.resolve(__dirname, 'Content/responsive/svg')],
use: [
{
loader: 'svg-sprite-loader',
options: {
spriteFilename: 'sprite.svg',
esModule: false,
symbolId: (fileName) => {
return `r-icon-${path.basename(fileName, '.svg')}`;
},
},
},
{
loader: 'svgo-loader',
options: {
plugins: svgoPlugins,
},
},
],
},
{
test: /\.svg$/,
type: 'asset/resource',
exclude: /-colou?r\.svg$/,
include: [path.resolve(__dirname, 'Content/responsive/svg')],
use: [
{
loader: 'svg-sprite-loader',
options: {
spriteFilename: 'sprite.svg',
esModule: false,
symbolId: (fileName) => {
return `r-icon-${path.basename(fileName, '.svg')}`;
},
},
},
{
loader: 'svgo-loader',
options: {
plugins: [
{
removeAttrs: {
attrs: '(?!mask).*:(stroke|fill)',
},
},
...svgoPlugins,
],
},
},
],
},
],
},
//stats: 'verbose',
plugins: [
new ForkTsCheckerWebpackPlugin(),
new WebpackManifestPlugin({
fileName: 'asset-manifest.json',
generate: (seed, files) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
const entrypointFiles = files
.filter((x) => x.isInitial && !x.name.endsWith('.map'))
.map((x) => x.path);
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: `css/[name]${!env.development ? hashSubstr : ''}.css`,
chunkFilename: `css/[id]${!env.development ? hashSubstr : ''}.css`,
}),
new SpriteLoaderPlugin({
plainSprite: true,
}),
],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
Svg: path.resolve(__dirname, './Content/responsive/svg'),
},
},
});
In my case, it seems that when using type: 'asset/resource' the module is exported as commonjs and not default import of esmodule
I work with webpack 5. Pug works well - after autosave or cmd+S I get new version of page. And it doesn't work so with JS and SCSS: SCSS autosave works well but after cmd+S I get some old version of page(usually everytime the same). With JS both autosave and cmd+S return some old version of page. Can you help me to find a solution? Below I dropped webpack.config.js
const path = require("path");
const fs = require("fs");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const isDev = process.env.NODE_ENV === "development";
const isProd = !isDev;
const PATHS = {
src: path.join(__dirname, "./src"),
dist: path.join(__dirname, "./dist"),
};
const PAGES_DIR = `${PATHS.src}/`;
const PAGES = fs.readdirSync(PAGES_DIR).filter((fileName) => fileName.endsWith(".pug"));
const filename = (ext) => `[name].${ext}`;
const plugins = () => {
const basePlugins = [
...PAGES.map(
(page) =>
new HTMLWebpackPlugin({
template: `${PAGES_DIR}/${page}`,
filename: `./${page.replace(/\.pug/, ".html")}`,
})
),
new MiniCssExtractPlugin({
filename: `./css/${filename("css")}`,
}),
new CopyWebpackPlugin({
patterns: [
{ from: path.resolve(__dirname, "src/assets"), to: path.resolve(`${PATHS.dist}`) },
{ from: path.resolve(__dirname, "src/img"), to: path.resolve(`${PATHS.dist}/img/`) },
],
}),
];
return basePlugins;
};
module.exports = {
context: path.resolve(`${PATHS.src}`),
mode: "development",
entry: "./js/main.js",
output: {
filename: `./js/${filename("js")}`,
path: path.resolve(`${PATHS.dist}`),
publicPath: "",
clean: true,
},
devServer: {
historyApiFallback: true,
static: path.resolve(`${PATHS.dist}`),
open: true,
compress: true,
hot: true,
port: 3000,
},
optimization: {
splitChunks: {
chunks: "all",
},
},
plugins: plugins(),
devtool: isProd ? false : "source-map",
module: {
rules: [
{
test: /\.pug$/,
loader: "pug-loader",
},
{
test: /\.s[ac]ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: (resourcePath, context) => {
return path.relative(path.dirname(resourcePath), context) + "/";
},
},
},
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"],
},
},
},
"sass-loader",
],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.(?:|gif|png|jpg|jpeg|svg|webp)$/,
use: [
{
loader: "file-loader",
options: {
name: `./img/${filename("[ext]")}`,
},
},
],
},
{
test: /\.(?:|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: `./fonts/${filename("[ext]")}`,
},
},
],
},
],
},
};
I don't know what to write here. I described my problem above.
I found that some of the styles are not applied in Production website, but working in development env(localhost).
But Inspecting in Browser Inspector > Sources, I found that in Production sources(css/main.c938xxxxx.css), it missed #roadmap .slick-slide{padding:0 18px}}

Which exist in localhost

Not sure what’s wrong for the production webpack setting. I am using webpack 5
Webpack.base.js
const webpack = require("webpack");
const utils = require("./utils");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const chalk = require("chalk");
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap({
entry: "./src/index.jsx",
resolve: {
alias: {
"#": utils.resolve("src"),
},
extensions: ["*", ".js", ".jsx"],
fallback: {…},
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
},
}
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
},
{
loader: "sass-loader",
},
{
loader: "sass-resources-loader",
options: {
resources: ["./src/assets/scss/main.scss"],
},
},
],
},
{
test: /\.(png|jpg|gif|svg)$/i,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 8192
}
}
},
{
test: /\.(ico)$/,
exclude: /node_modules/,
use: ["file-loader?name=[name].[ext]"], // ?name=[name].[ext] is only necessary to preserve the original file name
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "public/index.html",
filename: "index.html",
favicon: "public/favicon.ico",
manifest: "public/manifest.json",
inject: true,
}),
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
}),
new webpack.ProvidePlugin({
process: "process/browser",
}),
new ProgressBarPlugin({
format: ` :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
}),
],
});
webpack.dev.js
const { merge } = require("webpack-merge");
const path = require("path");
const base = require("./webpack.base");
const utils = require("./utils");
const Dotenv = require("dotenv-webpack");
module.exports = merge(base, {
mode: "development",
devtool: "inline-source-map",
output: {
publicPath: '/',
assetModuleFilename: (pathData) => {
const filepath = path
.dirname(pathData.filename)
.split("/")
.slice(1)
.join("/");
return `${filepath}/[name].[hash][ext][query]`;
},
},
devServer: {
port: 3300,
static: [
{ directory: utils.resolve("dist") },
{ directory: utils.resolve("public") },
],
},
plugins: [new Dotenv({ path: "./.env.dev })],
});
webpack.uat.js
const { merge } = require("webpack-merge");
const base = require("./webpack.base");
const path = require("path");
const Dotenv = require("dotenv-webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = ["js", "css"];
module.exports = merge(base, {
mode: "production",
output: {
path: path.join(__dirname, "../dist"),
filename: "js/[name].[contenthash].js",
assetModuleFilename: (pathData) => {
const filepath = path
.dirname(pathData.filename)
.split("/")
.slice(1)
.join("/");
return `${filepath}/[name].[hash][ext][query]`;
},
},
optimization: {
minimizer: [`...`, new CssMinimizerPlugin()],
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
},
"sass-loader",
{
loader: "sass-resources-loader",
options: {
resources: ["./src/assets/scss/main.scss"],
},
},
],
},
],
},
plugins: [
new Dotenv({ path: "./.env.uat" }),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash].css",
}),
new CompressionPlugin({
filename: "[path][name].gz[query]",
algorithm: "gzip",
test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
threshold: 10240,
minRatio: 0.8,
})
],
});
utils.js
const path = require('path')
module.exports = {
resolve: function(dir) {
return path.join(__dirname, '..', dir)
}
}
Add "style-loader" in webpack.uat.js file.
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "style-loader",
},
{
loader: "css-loader",
},
"sass-loader",
{
loader: "sass-resources-loader",
options: {
resources: ["./src/assets/scss/main.scss"],
},
},
],
},
],
The Webpack Bulid runs pretty slow, project background is a community portal developed in Vue.js...
Can anybody tell if there is any potential for improvement and if so, what?
I wonder if the time for the build process of 37401ms can still be changed by changing the codebase?
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const glob = require('glob');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const autoprefixer = require('autoprefixer');
const statsSettings = {
all: false,
modules: true,
maxModules: 0,
errors: true,
warnings: false,
moduleTrace: true,
errorDetails: true,
timings: true,
performance: true,
builtAt: true,
};
const {
rootDir,
srcDir,
assetsDir,
stylesDir,
buildDir,
sitepackageDir,
publicPath,
} = require('./config');
const chunks = glob.sync(path.join(rootDir, srcDir, 'pages/**/index.js'))
.reduce((obj, file) => {
const name = path.basename(path.dirname(file));
return {
...obj,
[name]: file,
};
}, {});
module.exports = env => {
return {
mode: env.production ? 'production' : 'development',
context: path.join(rootDir, srcDir),
entry: chunks,
output: {
path: path.join(rootDir, buildDir),
filename: '[name].js',
publicPath: env.production ? publicPath : '',
},
devtool: env.production ? false : 'cheap-module-eval-source-map',
devServer: {
contentBase: path.join(rootDir, buildDir),
inline: true,
proxy: {
'/api/v0': 'http://localhost:4000',
},
},
watchOptions: {
ignored: env.watch ? 'node_modules' : '',
aggregateTimeout: 300,
},
stats: env.watch ? statsSettings : 'normal',
module: {
rules: [
{
test: /\.vue$/,
include: [
path.join(rootDir, srcDir),
require.resolve('bootstrap-vue'),
],
loader: 'vue-loader',
},
{
test: /\.js$/,
include: [
path.join(rootDir, srcDir),
require.resolve('bootstrap-vue'),
],
loader: 'babel-loader',
},
{
test: /\.(css|scss)$/,
use: [
env.production ? MiniCssExtractPlugin.loader : 'vue-style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
autoprefixer({
browsers: ['>1%', 'last 2 versions', 'not ie < 11'],
}),
],
},
},
{
loader: 'sass-loader',
options: {
includePaths: [
path.join(rootDir, srcDir, stylesDir),
],
},
},
],
},
{
test: /\.(jpg|jpeg|png|gif|webp|svg|eot|otf|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$/,
loader: 'file-loader',
options: {
name: `${assetsDir}/_processed_/[name].[hash:4].[ext]`,
},
},
],
},
optimization: {
runtimeChunk: {
name: '_runtime',
},
splitChunks: {
cacheGroups: {
// we need to figure out if it's worth having a common chunk
// or if each entry chunk should be somewhat self-contained
common: {
chunks: 'initial',
name: '_common',
minChunks: 2,
minSize: 0,
},
vendor: {
test: /node_modules/,
chunks: 'initial',
name: '_vendor',
enforce: true,
},
},
},
},
resolve: {
extensions: ['.js', '.json', '.vue'],
alias: {
'#app': path.join(rootDir, srcDir),
// although we're using single file components that can be pre-compiled,
// we want to dynamically mounting them in the DOM html.
// this is way we need to alias 'vue' to use the runtime + compiler build here.
// see: https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
vue$: 'vue/dist/vue.esm.js',
},
},
plugins: [
new webpack.DefinePlugin({
PAGES: JSON.stringify(Object.keys(chunks)),
}),
new VueLoaderPlugin(),
...plugHtmlTemplates(),
...plugExtractCss(env),
...plugCopyAssets(),
],
};
};
function plugHtmlTemplates () {
return glob.sync(path.join(rootDir, srcDir, 'pages/**/template.html'))
.map(template => {
const name = path.basename(path.dirname(template));
return {
template,
filename: `${name}.html`,
chunks: ['_runtime', '_vendor', '_styles', '_common', name],
};
})
.map(htmlConfig => new HtmlWebpackPlugin(htmlConfig));
}
function plugExtractCss (env) {
if (!env.production) return [];
return [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name].css',
}),
];
}
function plugCopyAssets () {
const assetsSrcPath = path.join(rootDir, srcDir, assetsDir);
if (!fs.existsSync(assetsSrcPath)) return [];
return [
new CopyWebpackPlugin([
{ from: assetsSrcPath, to: path.join(rootDir, buildDir, path.basename(assetsDir)) },
// this is required for the icons to be selectable in the backend
{ from: path.join(assetsSrcPath, 'icons/'), to: path.join(rootDir, sitepackageDir, 'Resources/Public/Icons/') },
// this is required for avatars to be available; we must not check them in in fileadmin since they would
// prevent having the dir linked by Deployer during a deployment
{ from: path.join(rootDir, '../packages/users/Resources/Private/Images/Avatars/'), to: path.join(rootDir, buildDir, 'static/avatars/') },
]),
];
}
The question is whether you can improve the performance by using different plugins or summarizing steps...
I have a similar configuration. My configuration built ~33 seconds. I added a cache-loader package and decrease build time to ~17 seconds.
npm install --save-dev cache-loader
config:
rules: [
//rules here
{
test: /\.vue$/,
use: [
{
loader: 'cache-loader',
options: {}
},
{
loader: 'vue-loader',
options: vueLoaderConfig
}
],
},
{
test: /\.js$/,
use: [
{
loader: 'cache-loader',
options: {}
},
{
loader: 'babel-loader'
}
],
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
}
]