Webpack is taking 30 seconds to compile - javascript

I'm using a webpack on the development, I'm not sure what is wrong with my webpack configuration as it is taking too much of time even if I make a single line of change in my code. When I start the app it takes 30 seconds to start and it continues to take the same time in all my subsequent changes.
Here is my webpack file
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
login: './js/login.js',
progress_page: './js/react_progress_bar.js',
home: './js/home.js',
new_design_landing: './js/design_landing.js',
onboarding_preview: './js/preview.js',
popup_message: './js/message.js'
},
output: {
filename: '[name].js',
//chunkFilename: 'modern_theme_[name].[hash].chunk.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'http://localhost:5050/'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
//modules: true,
modules: {
// CSS name which we want to keep we can also
// change it to something like this [name]-[local]--[hash:base64:5]
localIdentName: '[name]',
},
url: false
}
}
]
},
{
test: /\.scss$/,
use: [{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
//modules: true,
modules: {
// CSS name which we want to keep we can also
// change it to something like this [name]-[local]--[hash:base64:5]
localIdentName: '[name]-[local]',
},
url: false
}
},
{
loader: 'sass-loader'
},
{
loader: 'sass-resources-loader',
options: {
resources: './scss/abstracts/variables.scss'
}
}
]
},
]
},
plugins: [
new webpack.DefinePlugin({
TRACKING_ID: "x"
NODE_ENV: JSON.stringify('production'),
SERVER_ADDRESS: JSON.stringify('http://localhost:5050/'),
WT_SITE: JSON.stringify('http://localhost:5050')
}),
new webpack.EnvironmentPlugin({
ASSETS_PATH: "http://localhost:5050/",
SERVER_ADDRESS: "http://localhost:5050/",
AUTO_LOGOUT_TIMER: 7180000,
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
watch: true,
watchOptions: {
poll: 500
},
optimization: {
minimize: false
},
mode: 'development',
devtool: false
};
Can you please help me point out what is wrong in this that it is taking 30 seconds for any change I make in the code.
React version used 16.8.6
webpack version 4.23.1
Here is how my package.json looks like

Try ignoring node_modules in your watchOptions:
watchOptions: {
ignored: /node_modules/
}
Also, polling is generally underperformant. Why do you need it ? Are you developing inside vagrant/docker or using a networked file system ?
Unrelated tangent: You may not want to set NODE_ENV: production for development, as it will suppress helpful warnings in many libraries like react, react-redux etc.

Related

Webpack url() path resolution with css-loader

I am developing a site and using webpack for obvious reasons. The problem I am having is with path resolution for images which are imported into my project via my SCSS files. The issue is that css-loader isn't resolving the correct path. What seems to be happening is the following:
If I allow css-loader to handle the url() imports (leaving the url option to true) it rewrites the file path relative to the output directory specified in ExtractCSSChunksPlugin(), for example:
url('../img/an-image.jpg') should be rewritten to url('http://localhost:3000/assets/img/an-image.jpg'), however, what is actually being outputted is url('http://localhost:3000/assets/css/assets/img/an-image.jpg').
If I change it to false the correct path is resolved but the file-loader isn't able to find the images and then emit them.
I know that the images are being outputted when the css-loader is handling url resolution as I can see the emitted message when the bundle is compiled -- it does not fail.
I can also get the images to display if I manually add import calls to them in the JS entry point, set in the entry: field, and then call the absolute path in SCSS. But this is not desirable as it becomes tedious with the growing project.
I have tried to use resolve-url-loader and changing multiple settings but I just can't seem to get this to work.
I have also tried using the resolve: { alias: { Images: path.resolve(__dirname, 'src/assets/img/' } } option provided by webpack and then calling url('~Images/an-image.jpg') in my SCSS but it just reproduces the same results.
So, overall, my issue is that I need to be able to use relative paths in my SCSS and then have them rewritten to the correct path by one of my loaders.
My current webpack config (outputting the files with file loader but prepending assets/css/ to the start of the url) is as follows:
"use strict";
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common');
const ExtractCSSChunksPlugin = require('extract-css-chunks-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
}
}
},
{
test: /\.scss$/,
use: [
{
loader: ExtractCSSChunksPlugin.loader,
options: {
hot: true,
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
}
}
]
},
{
test: /\.html$/,
use:['html-loader']
},
{
test:/\.(svg|jpg|png|gif)$/,
use: [{
loader:'file-loader',
options: {
publicPath: 'assets/img',
outputPath: 'assets/img',
name: '[name].[ext]',
esModule: false
}
}],
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ExtractCSSChunksPlugin({
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[id].css',
}),
]
});
Thank you in advance.
Ok, so it seems I have fixed the issue by resolving the publicPath set in the file loader config field: publicPath: path.resolve(__dirname, '/assets/img').
My config is now:
"use strict";
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const ExtractCSSChunksPlugin = require('extract-css-chunks-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
}
}
},
{
test: /\.scss$/,
use: [
{
loader: ExtractCSSChunksPlugin.loader,
options: {
hot: true,
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
}
}
]
},
{
test: /\.html$/,
use:['html-loader']
},
{
test:/\.(svg|jpg|png|gif)$/,
use: [{
loader:'file-loader',
options: {
publicPath: path.resolve(__dirname, '/assets/img'),
outputPath: 'assets/img',
name: '[name].[ext]',
esModule: false
}
}],
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ExtractCSSChunksPlugin({
filename: 'assets/css/[name].css',
chunkFilename: 'assets/css/[id].css',
}),
]
});
I think adding url loader in the webpack configuration would help.
{
test: /\.(jpg|png)$/,
use: {
loader: "url-loader",
options: {
limit: 25000,
},
},
},

Webpack: ignore references to svg/ttf files in css

I'm using webpack to export a css file. I'm using file-loader for svg/ttf files but it seems to copy them to the dist folder. Is there a way I can get webpack to just ignore referneces to svg/ttf in my css and leave as is? I've tried ignore-loader but it just replaces the file paths with [Object object].
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
performance: { hints: false },
mode: 'development',
devtool: 'source-map',
entry: ['babel-polyfill', './js/react-components/src/index.js'],
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'js/react-components/dist')
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: 'output.css',
chunkFilename: 'chunk[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.(png|svg|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9-]+)?$/,
loader: 'file-loader'
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
resolve: {
extensions: [".js", ".jsx"]
},
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [
{ loader: MiniCssExtractPlugin.loader,
options: {},
},
"css-loader"
]
}
]
}
};
I had a similar use case
Use esModule: false to fix the [Object object] in paths.
Also put all the assets in a /static/ folder (source is destination).
{
test: /\.(svg|png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
outputPath: '../static',
name: '[name].[ext]',
esModule: false
},
},
EDIT: Well that created a loop with npm run watch
I gave up and let the files be copied put the outputPath: './'
I also had to add an exception to CleanWebpackPlugin, or else they
plugins: [
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['!*.svg']
}), ...

Objects called in browser after webpack bundle show undefined

I am new to webpack and I want to debug using console.log in my browser and by calling functions to see what works, but whenever I try to do this after my js files are bundled everything shows up as undefined. Webpack must be changing the names somehow when the files get bundled together so even if I make a simple let x = 'hello', I can't console.log it and I can't even call any functions I made without them being undefined when I use them in the console.
How can I fix this so that I can call the objects that I made in the console? Here is my simple webpack config-
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-source-map',
mode: 'development',
entry: {
app:'./src/js/index.js',
test:'./src/js/test2.js',
create: './src/js/create.js'
},
devtool: 'source-map ',
devServer: {
contentBase: './dist',
compress: true,
port: 8080,
},
plugins: [
new HtmlWebpackPlugin({
title: 'Menu',
template: './src/views/index.ejs',
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.jsnpm$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['#babel/preset-env', {
'debug':true
}]
}
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
]
},
};
https://webpack.js.org/contribute/debugging/
This would be helpful for getting in depth of debugging webpacks! good documentation for debugging webpacks.
In case you want to use browser for debugging, this may be helpful:
Configure webpack to allow browser debugging
Hope this helps!

Webpack: include specific file instead of package.json specified?

I have a webpack configuration:
var path = require("path");
module.exports = {
entry: {
app: [
'./src/index.js'
]
},
output: {
path: path.resolve(__dirname + '/dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.(css|scss)$/,
use: [
'style-loader',
'css-loader',
]
},
{
test: /\.js$/,
exclude: /node_modules/,
},
{
test: /\.html$/,
exclude: /node_modules/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: /\.elm$/,
exclude: [/elm-stuff/, /node_modules/],
loader: 'elm-webpack-loader?verbose=true&warn=true',
options: {debug: true, warn: true},
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff',
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
},
],
noParse: /\.elm$/,
},
devServer: {
inline: true,
stats: { colors: true },
},
};
I have a few questions:
According to me the above config says that it should not be looking
for js files in node_modules. However it is still bundling
./node_modules/dexie/dist/dexie.es.js when I call require ("dexie"). (I am just doing this to experiment and understand webpack).
I would rather like to call dexie.js instead of dexie.es.js. How do
I make this happen. I know I can set the mainFields property.
However how do I do this on a prelibrary basis instead of globally.
Not sure if I understand your requirement fully, but an option is to set up aliases in the webpack resolve
module.exports = {
entry: {
...
},
output: {
...
},
module: {
rules: [
...
],
noParse: /\.elm$/,
},
resolve: {
alias: {
dixie: 'node_modules/dexie/dist/dexie.js'
}
},
devServer: {
...
},
};
To your first question please see here. It has already been answered.
No matter what you exclude in your loaders config, the file will be bundled unless you define it as external in your config.
To your second question, you can just require the other file with
require('dexie/dexie.js')
When you just write require('dexie'), webpack will look in your node_modules folder for a folder named 'dexie', read the package.json and resolve the file described by the module property. This is described here.
For more info, please read the webpack docs. They are excellent.

Moving from webpack v1 to v2

I'm trying to migrate my code from webpack v1 to v2 and add in the sass-loader, however I get the error
throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
I'm very confused as to what the final file is supposed to look like:
let webpack = require('webpack');
let path = require('path');
module.exports = {
devtool: 'eval-source-map',
entry: [
'./src/index'
],
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS
]
}],
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
resolve: {
extensions: ['.js'],
options: {
enforceExtension: false
}
},
output: {
path: path.join(__dirname, '/dist'),
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './dist',
hot: true,
historyApiFallback: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.LoaderOptionsPlugin({
debug: true,
options: {
context: __dirname
}
})
]
};
At the moment the code is a mix of the two versions. I am using webpack version 2.2.1. Thanks.
There are several things you need to change:
Your test: /\.js?$/ and the corresponding loader and exclude should be another object inside the rules array:
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS
]
},
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
resolve.options does not exist, it is just resolve.enforceExtension directly:
resolve: {
extensions: ['.js'],
enforceExtension: false
},
And finally, although it's not an error but just a warning, new webpack.NoErrorsPlugin() is deprecated and has been replaced with:
new webpack.NoEmitOnErrorsPlugin()
Also if you haven't yet, you should have a look at the migration guide from the official docs https://webpack.js.org/guides/migrating/.

Categories

Resources