I decided to give webpack a shot and am using a starter kit for a small project. I'm not sure where I am going wrong but I want to add a new directory of files and access them like any other build.In this case it is the folder "particles.js-master". When I add a directory I cannot seem to access anything in the folder. I'm assuming I have to add an output or the like to the webpack config? Any advice would be greatly appreciated, thanks :)
here is my project structure
webpack:
const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const CssUrlRelativePlugin = require('css-url-relative-plugin');
const glob = require('glob');
const IS_DEV = process.env.NODE_ENV === 'dev';
const config = {
mode: IS_DEV ? 'development' : 'production',
devtool: IS_DEV ? 'eval' : 'source-map',
entry: './src/js/index.js',
output: {
filename: 'js/[name].[hash].js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: IS_DEV,
},
},
'css-loader',
'sass-loader',
],
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: '[name].[ext]',
fallback: 'file-loader',
outputPath: 'public/images',
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65,
},
pngquant: {
quality: '65-90',
speed: 4,
},
gifsicle: {
interlaced: false,
},
webp: {
quality: 75,
},
},
},
],
},
],
},
plugins: [
new CleanWebpackPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'windows.jQuery': 'jquery',
}),
new CopyWebpackPlugin([
{
from: './src/public',
to: 'public',
},
]),
new MiniCssExtractPlugin({
filename: IS_DEV ? 'css/[name].css' : 'css/[name].[contenthash].css',
chunkFilename: 'css/[id].css',
}),
new webpack.HashedModuleIdsPlugin(),
new PreloadWebpackPlugin({
include: 'initial',
}),
new CssUrlRelativePlugin(),
],
devServer: {
contentBase: path.join(__dirname, 'src'),
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /node_modules/,
chunks: 'initial',
name: 'vendor',
priority: 10,
enforce: true,
},
},
},
minimizer: [],
},
};
if (!IS_DEV) {
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
config.optimization.minimizer.push(
new TerserPlugin(),
new OptimizeCSSAssetsPlugin({})
);
}
const files = glob.sync('./src/*.html');
files.forEach(file => {
config.plugins.push(
new HtmlWebPackPlugin({
filename: path.basename(file),
template: file,
favicon: path.resolve(__dirname, './src/public/icon.ico'),
minify: !IS_DEV,
})
);
});
module.exports = config;
Related
I'm creating a PWA react application in which I configure the manifest.json file and serviceWroker.js file.
In the development mode, it works fine but when I create production build using webpack, manifest.json file does not load in the Build folder.
Does anyone know what's the issue?
Here is my webpack.config.js file
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WebpackRTLPlugin = require('webpack-rtl-plugin');
const WebpackMessages = require('webpack-messages');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const del = require('del');
const webpack = require('webpack');
// theme name
const themeName = 'metronic';
// global variables
const rootPath = path.resolve(__dirname);
const distPath = rootPath + '/src';
const mainConfig = function() {
const isEnvDevelopment = false;
const isEnvProduction = true;
return {
mode: 'production',
stats: 'errors-only',
performance: {
hints: false
},
externals: [ 'jspdf', 'jspdf-autotable' ],
entry: './src/index.js',
output: {
// main output path in assets folder
path: path.resolve(__dirname, 'dist'),
// output path based on the entries' filename
// filename: '[name].js',
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
// TODO: remove this when upgrading to webpack 5
futureEmitAssets: true,
// There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction
? 'static/js/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'static/js/[name].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development.
publicPath: '/artbot/app/'
},
resolve: { extensions: [ '.scss', '.css','.mjs','.jsx', '.js', '.json' ] },
optimization: {
minimize: true,
namedChunks: true,
nodeEnv: 'production',
removeAvailableModules: true,
removeEmptyChunks: true,
mergeDuplicateChunks: true,
minimizer: [ new OptimizeCssAssetsPlugin(), new TerserPlugin({ cache: true }) ],
splitChunks: {
chunks: "all"
}
},
plugins: [
// webpack log message
new WebpackMessages({
name: themeName,
logger: (str) => console.log(`>> ${str}`)
}),
new BundleAnalyzerPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
new HtmlWebpackPlugin({
title: 'Custom Template',
template: 'public/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
}
}),
// create css file
new MiniCssExtractPlugin({
filename: 'static/css/[name].css'
}),
new WebpackRTLPlugin({
filename: 'static/css/[name].rtl.css',
minify: true
}),
{
apply: (compiler) => {
// hook name
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
(async () => {
await del.sync(distPath + '/sass/*.js', { force: true });
})();
});
}
}
],
module: {
rules: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
// exclude: /#babel(?:\/|\\{1,2})runtime/,
exclude: /node_modules/,
loader: require.resolve('babel-loader'),
options: {
babelrc: true,
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent: '#svgr/webpack?-svgo,+titleProp,+ref![path]'
}
}
}
]
]
}
},
{
test: /\.css$/,
loader: 'css-loader'
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'resolve-url-loader',
options: {
removeCR: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(png|jpg|svg)$/,
loader: 'file-loader',
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
esModule: false
}
//loader: 'url-loader?limit=8192'
},
{
test: /\.(woff2|eot|ttf|woff)$/,
loader: 'url-loader'
},
{
test: /\.json$/,
loader: 'file-loader',
type: 'javascript/auto',
exclude: /node_modules/,
options: {
name: 'static/json/[name].[hash:8].[ext]'
}
},
{
test: /\.html$/i,
loader: 'html-loader'
}
]
}
};
};
module.exports = function() {
return [ mainConfig() ];
};
Currently, my yarn build script generates 2 files, main.[hash].js and main.[hash].css. Is there any way that I can bundle even my css file to the main.[hash].js so that I only have one js file?
Here are my config files:
webpack.common.js
const webpack = require('webpack');
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js',
},
module: {
rules: [
{
test: /\.html$/,
use: ['html-loader'],
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'imgs',
},
},
},
{
enforce: 'pre',
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
cache: true,
emitWarning: true,
failOnError: true,
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.$': 'jquery',
'window.jQuery': 'jquery',
}),
],
};
webpack.dev.js
const path = require('path');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html',
}),
],
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
});
webpack.prod.js
const path = require('path');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'production',
output: {
filename: '[name].[contentHash].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
minimizer: [
new OptimizeCssAssetsPlugin(),
new TerserPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true,
removeComments: true,
},
}),
],
},
plugins: [
new MiniCssExtractPlugin({filename: '[name].[contentHash].css'}),
new CleanWebpackPlugin(),
],
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader, // 3. Extract css into files
'css-loader', // 2. Turns css into commonjs
'sass-loader', // 1. Turns sass into css
],
},
],
},
});
I have also tried adding some plugins to achieve this but had not had any luck so far.
If there is a plugin or some other way that you have, please help me with it.
Im trying to use url-loader to convert file URLs into inline data URLs for my CSS backgrounds. When I run the build command, it generates the CSS & JS files without any error but the background image URLs remain unchanged in the CSS output.
Here's my webpack config:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const ManifestPlugin = require('webpack-manifest-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = (env, argv) => ({
entry: {
app: ['./app/Resources/js/app.js', './app/Resources/scss/app.scss']
},
output: {
path: path.join(__dirname, "/web/build"),
filename: argv.mode === 'production' ? '[name].[hash].js' : '[name].js'
},
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false // set to true if you want JS source maps
}),
new OptimizeCSSAssetsPlugin({
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
})
]
},
devServer: {
contentBase: './web',
port: 9000,
disableHostCheck: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
},
resolve: {
extensions: ['.js']
}
},
{
test: /\.scss$/,
resolve: {
extensions: ['.scss']
},
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader"
},
{
loader: "sass-loader",
options: {
sassOptions: {
outputStyle: 'expanded',
includePaths: ['./node_modules/foundation-sites/scss']
}
}
}
]
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
},
}
],
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: argv.mode === 'production' ? '[name].[contenthash].css' : '[name].css'
}),
new ManifestPlugin(),
new CleanWebpackPlugin()
],
});
My CSS is just a standard SCSS file:
.icon { background:url('path/to/icon.svg'); }
In the final output, I'd expect path/to/icon.svg to be replaced by a data URL. What am I doing wrong?
My project is using 3 webpack files (one common, and two for dev/prod env) and .babelrc file for babel config
.babelrc
{
"presets": ["#babel/preset-env"],
"plugins": ["angularjs-annotate"]
}
webpack.common.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require("webpack");
const WebpackBar = require('webpackbar');
const pathPublic = "/public/path/";
const pathFonts = "/fonts/";
module.exports = {
devtool: "eval",
entry: {
app: "./src/js/app.index.js",
},
module: {
rules: [{
test: /\.(gif|png|jpe?g)$/i,
use: ["file-loader"],
}, {
test: /\.(woff|woff2|ttf|eot|svg|otf)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
publicPath: pathPublic + pathFonts,
name: "[name].[ext]",
outputPath: pathFonts,
chunks: true
}
}]
}, {
test: /\.css$/,
use: [
{loader: "style-loader"},
{loader: MiniCssExtractPlugin.loader},
{loader: "css-loader"}
]
}, {
test: /\.scss$/,
use: [
{loader: "style-loader"},
{loader: MiniCssExtractPlugin.loader},
{loader: "css-loader"},
{loader: "sass-loader"}
]
}, {
test: /\.less$/,
use: [
{loader: "style-loader"},
{loader: MiniCssExtractPlugin.loader, options: {publicPath: pathPublic}},
{loader: "css-loader"},
{loader: "less-loader"}
]
}]
},
plugins: [
new WebpackBar(),
new CleanWebpackPlugin(["frontend/dist", "static/"], {root: __dirname + "/.."}),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
collapseWhitespace: false,
template: path.join(__dirname, "src/assets/html/index.proto.html"),
title: 'SC app front page',
inject: "html",
hash: true
}),
new ScriptExtHtmlWebpackPlugin({defaultAttribute: "defer"}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
}),
new MiniCssExtractPlugin({
filename: "styles.min.css",
})
],
stats: {
children: false,
colors: true
},
};
webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const pathDist = path.resolve(__dirname, "dist");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(common, {
mode: "production",
output: {
filename: "[name].min.js",
publicPath: "/public/path/",
chunkFilename: "npm.[id].[chunkhash].min.js",
path: pathDist
},
optimization: {
runtimeChunk: "single",
minimizer: [
new UglifyJsPlugin({
sourceMap: false,
uglifyOptions: {
compress: true,
output: {comments: false},
}
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.(css|sass|scss|less)$/g,
cssProcessor: require("cssnano")({
safe: true,
normalizeWhitespaces: true,
discardDuplicates: true,
discardComments: {
removeAll: true,
}
})
})
],
splitChunks: {
chunks: "all",
maxInitialRequests: Infinity,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
maxSize: 249856, // 244 KiB Webpack recommended size
},
}
},
}
});
webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const pathDist = path.resolve(__dirname, "dist");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
output: {
filename: "[name].min.js",
publicPath: "/public/path/",
chunkFilename: "npm.[id].[chunkhash].min.js",
path: pathDist
},
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: true,
uglifyOptions: {
compress: true,
output: {comments: false}
}
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.(css|sass|scss|less)$/g,
cssProcessor: require("cssnano")({
safe: true,
normalizeWhitespaces: true,
discardDuplicates: true,
discardComments: {
removeAll: true,
},
})
})
]
},
devServer: {
contentBase: pathDist
}
});
the problem is that when i do dev build, es6 class names remains unchanged, but when i do prod build, es6 class names changes and this will crush angularjs DI process.
EXAMPLE:
Let's say there is 2 classes (one service and one controller)
/**
* build-dev: MyService.prototype.constructor.name = "MyService"
* build-prod: MyService.prototype.constructor.name = "MyService__MyService"
*/
class MyService {
serviceMethod() {
// DO STUFF
}
}
/**
* build-dev: MyCtrl.prototype.constructor.name = "MyCtrl"
* build-prod: MyCtrl.prototype.constructor.name = "MyCtrl__MyCtrl"
*/
class MyCtrl {
constructor(MyService) {
this.MyService = MyService;
}
ctrlMethod() {
this.MyService.serviceMethod()
}
}
and those classes are registered with angularjs DI this way
angular.module("MyApp")
.controller(MyCtrl.prototype.constructor.name, MyCtrl)
.service(MyService.prototype.constructor.name, MyService)
now pay attention at class annotations (build-dev, build-prod)
I've recently tried to add proper code splitting for the first time to one of my projects.
It's worked, however I think it's worked a little TOO well!
When I run bundle-analyser, my dist folder contains a bunch of other bundles that contain snapshots and test files and I can't find any information that would explain why this is happening!
here is my webpack.config.base.js
const path = require('path');
const postcssNested = require('postcss-nested');
const postcssSimpleVars = require('postcss-simple-vars');
const postcssPresetEnv = require('postcss-preset-env');
const postcssImport = require('postcss-import');
const postcssFor = require('postcss-for');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractCssPluginConfig = new ExtractTextPlugin({
filename: '[name].[hash].css',
disable: false,
});
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body',
});
module.exports = {
entry: {
main: './src/index.jsx',
},
output: {
path: path.resolve('_dist'),
chunkFilename: '[name].[hash].bundle.min.js',
filename: '[name].[hash].min.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.(js|jsx)?$/,
loader: 'babel-loader',
exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
},
{
test: /\.css$/,
loader: 'style-loader',
},
{
test: /\.css$/,
loader: 'css-loader',
query: {
modules: true,
importLoaders: 1,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]',
},
},
{
test: /\.css$/,
loader: 'postcss-loader',
options: {
plugins: () => [
postcssNested,
postcssImport,
postcssFor,
postcssPresetEnv({
browsers: '>1%',
autoprefixer: {
grid: true,
browsers: ['>1%'],
},
insertBefore: {
'all-property': postcssSimpleVars,
},
}),
],
},
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000,
name: 'images/[hash]-[name].[ext]',
},
}],
},
{
test: /\.(woff|woff2|ttf|eot|otf)$/,
use: 'file-loader?name=fonts/[name].[ext]',
},
{
test: /\.(pdf)$/,
use: [{
loader: 'url-loader',
options: { limit: 8000, name: 'documents/[hash]-[name].[ext]' },
}],
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.svg'],
modules: [path.resolve('./node_modules')],
alias: {
Pages: path.resolve(__dirname, 'src/pages/'),
Sections: path.resolve(__dirname, 'src/sections/'),
Components: path.resolve(__dirname, 'src/components/'),
Images: path.resolve(__dirname, 'src/images/'),
Downloads: path.resolve(__dirname, 'src/downloads/'),
Services: path.resolve(__dirname, 'src/services/'),
Enum: path.resolve(__dirname, 'src/enum/'),
Data: path.resolve(__dirname, 'src/data/'),
Utils: path.resolve(__dirname, 'src/utils/'),
Config: path.resolve(__dirname, 'src/config/'),
},
},
plugins: [
ExtractCssPluginConfig,
HtmlWebpackPluginConfig,
],
};
and here is my webpack.config.build.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const baseConfig = require('./webpack.config.base');
const WebpackCleanupPluginConfig = new WebpackCleanupPlugin({
exclude: ['webpack.stats.json'],
quiet: true,
});
const CopyWebpackPluginConfig = new CopyWebpackPlugin([
{ from: './src/documents', to: './documents' },
]);
module.exports = () => {
const DefinePluginConfig = new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'),
});
return (
merge(baseConfig, {
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'initial',
enforce: true,
},
},
},
noEmitOnErrors: true,
concatenateModules: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false,
}),
],
},
plugins: [
DefinePluginConfig,
WebpackCleanupPluginConfig,
CopyWebpackPluginConfig,
],
})
);
};
I've tried adding a regex that matches any files with .test.js/jsx and .snap to my module.rules object but that did nothing.
Any help would be greatly appreciated!
If your test files are in a different directory, you might want to consider adding exclude property within the modules rules for js files.
Refer the following document: https://webpack.js.org/configuration/module/?_sm_au_=iVVKrMW7ZsbHQPbq#rule-exclude
or the following example: https://webpack.js.org/configuration/?_sm_au_=iVVKrMW7ZsbHQPbq#options
Another solution would be to use the IgnorePlugin. Docs for IgnorePlugin here: https://webpack.js.org/plugins/ignore-plugin/?_sm_au_=iVVKrMW7ZsbHQPbq