Does webpack make projects bigger? - javascript

I started using webpack with my existing project and the bundle it generates is much bigger in size than before webpack.
I am using all the optimisations I can think of and still it's around 60% bigger than before.
I don't know what I am doing wrong.
my config:
'use strict';
// Modules
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var HtmlWebpackPlugin = require('html-webpack-plugin');
//var jQueryPlugin = require('jquery');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
//var Promise = require('es6-promise-polyfill').Promise;
module.exports = function makeWebpackConfig (options) {
/**
* BUILD is for generating minified builds
*/
var BUILD = !!options.BUILD;
var config = {};
config.entry = {
app: './app.js',
iosCordova: ['./static/wrapper-resources/js/ios/cordova_all.js'],
androidCordova: ['./static/wrapper-resources/js/android/cordova_all.js']
};
/**
* Output
*/
config.output = {
// Absolute output directory
path: __dirname + '/public',
// Output path from the view of the page
// Uses webpack-dev-server in development
publicPath: 'http://localhost:8080/',
filename: '[name].bundle.js',
// non-entry
chunkFilename: '[name].bundle.js'
};
if (BUILD) {
config.devtool = 'source-map';
} else {
config.devtool = 'eval';
}
/**
* Loaders
*/
config.module = {
noParse: /node_modules\/html2canvas/,
preLoaders: [],
loaders: [
{
// JS LOADER
test: /\.js$/,
loader: 'babel?optional[]=runtime,cacheDirectory',
presets: ['es2015'],
plugins: ['transform-runtime'],
exclude: [/node_modules/,
/cordova_all/
]
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
loader: 'file?name=[name].[ext]'
//loader: 'url-loader'
}, {
test: /\.html$/,
loader: 'raw'
}]
};
var cssLoader = {
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', 'css?sourceMap!postcss', 'scss', 'sass')
};
config.module.loaders.push(cssLoader);
config.postcss = [
autoprefixer({
browsers: ['last 2 version']
})
];
/**
* Plugins
*/
config.plugins = [
// Extract css files
new ExtractTextPlugin('[name].css')
,
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
];
// build specific plugins
if (BUILD) {
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.optimize.DedupePlugin(),
// Minify all javascript, switch loaders to minimizing mode
new webpack.optimize.UglifyJsPlugin()
)
}
/**
* Dev server configuration
*/
config.devServer = {
contentBase: './public',
stats: {
modules: false,
cached: false,
colors: true,
chunk: false
}
};
return config;
};

I figured it out. When importing I didn't import the minified version of node modules. I guess webpack's minification and uglification just doesn't cut it.
Thanks for the helpers.

Related

Webpack throws TypeError: Super expression must either be null or a function, not undefined when importing LESS file

I have the following in a file initialize.js:
import App from './components/App';
import './styles/application.less';
document.addEventListener('DOMContentLoaded', () => {
const app = new App();
app.start();
});
In webpack.config.js I have:
'use strict';
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const ProvidePlugin = webpack.ProvidePlugin;
const ModuleConcatenationPlugin = webpack.optimize.ModuleConcatenationPlugin;
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const extractLess = new ExtractTextPlugin({
filename: 'app.css',
});
const webpackCommon = {
entry: {
app: ['./app/initialize']
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader?presets[]=es2015'
}]
}, {
test: /\.hbs$/,
use: {
loader: 'handlebars-loader'
}
}, {
test: /\.less$/,
exclude: /node_modules/,
use: extractLess.extract({
use: [{
loader: 'css-loader'
}, {
loader: 'less-loader'
}],
// use style-loader in development
fallback: 'style-loader'
}),
}]
},
output: {
filename: 'app.js',
path: path.join(__dirname, './public'),
publicPath: '/'
},
plugins: [
extractLess,
new CopyWebpackPlugin([{
from: './app/assets/index.html',
to: './index.html'
}]),
new ProvidePlugin({
$: 'jquery',
_: 'underscore'
}),
new ModuleConcatenationPlugin(),
],
};
module.exports = merge(webpackCommon, {
devtool: '#inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 9000
}
});
I tried removing the the plugins and the contents of application.less, but I keep getting this error:
ERROR in ./node_modules/css-loader!./node_modules/less-loader/dist/cjs.js!./app/styles/application.less
Module build failed: TypeError: Super expression must either be null or a function, not undefined
at ...
# ./app/styles/application.less 4:14-127
# ./app/initialize.js
If I replace that LESS file with a CSS one and update the config it works fine, so I guess the problem has to do with less-loader.
I'm using Webpack 3.4.1, Style Loader 0.18.2, LESS Loader 4.0.5, Extract Text Webpack Plugin 3.0.0 and CSS Loader css-loader.
My bad, I didn't notice I was using an old less version. That was the culprit. Just updated it to 2.7.2 and the problem is gone.

how to install reactjs npm package correctly

Hi I want to install this reactjs package called react-dropdown-input
https://github.com/RacingTadpole/react-dropdown-input/
I ran this command
$npm install react-dropdown-input --save
in my local folder in git bash. After that I checked my package.json, it says "react-dropdown-input": "^0.1.11" which means i have installed it correctly.
Then i tried to use it in my js file
import React from 'react'
import PropTypes from 'prop-types';
var DocumentTitle = require('react-document-title');
//var DropdownInput = require('react-dropdown-input');
When i added the fifth line, my page just could not load anymore (a blank page)
I dont know how to fix this.
Here's my webpack.config.js
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
const path = require('path');
const webpack = require('webpack');
const BaseFolder = 'static/'; //relative to html path
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractLess = new ExtractTextPlugin({
filename: '[name].[contenthash].css',
disable: process.env.NODE_ENV === 'development'
});
var loaders = ['babel-loader'];
var port = process.env.PORT || 3000;
var vendor = ['react', 'react-dom', 'react-router', 'whatwg-fetch', 'es6-promise'];
var outputDir = 'dist';
var entry = {
filename: path.resolve(__dirname, 'src/app.js'),
}
var plugins = [
new webpack.optimize.CommonsChunkPlugin({
name:'vendor',
minChunks: Infinity,
filename: BaseFolder + 'js/[name].js',
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, '/src/index.html'),
filename: 'index.html',
inject: 'body'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'BaseFolder': JSON.stringify(BaseFolder)
}),
//new webpack.optimize.LimitChunkCountPlugin({maxChunks: 1}),
extractLess,
new webpack.ProvidePlugin({
Promise: 'es6-promise',
fetch: 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch',
React: 'react',
jsSHA: 'jssha',
wx: 'weixin-js-sdk'
}),
new CopyWebpackPlugin([
{
from: 'src/images',
to: BaseFolder + 'images'
}
])
];
if (process.env.NODE_ENV === 'development') {
//devtool ='eval-source-map';
loaders = ['react-hot-loader'].concat(loaders);
plugins = plugins.concat([
new webpack.HotModuleReplacementPlugin()
]);
entry = Object.keys(entry).reduce(function (result, key) {
result[key] = [
'webpack-dev-server/client?http://0.0.0.0:' + port,
'webpack/hot/only-dev-server',
entry[key]
];
return result;
}, {});
}
entry.vendor = vendor;
module.exports = env => {
return {
entry: entry,
output: {
filename: BaseFolder+'js/bundle.js',
chunkFilename: BaseFolder+'js/[id].chunk.js',
path: path.resolve(__dirname, outputDir),
publicPath: '/'
},
externals: [
],
module: {
loaders: [
{
test: /.jsx?$/,
loader: loaders,
exclude: /node_modules/,
include: __dirname
},
{ test: /\.js$/, exclude: /node_modules/, loaders: loaders, include: __dirname},
{ test: /\.scss$/, exclude: /node_modules/, loader: 'style-loader!css-loader?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap&includePaths[]=node_modules/compass-mixins/lib'},
{ test: /\.css$/, loader: 'style-loader!css-loader', exclude: /\.useable\.css$/},
{
test: /\.useable\.css$/,
use: [
{
loader: 'style-loader/useable'
},
{ loader: 'css-loader' },
],
},
{ test: /\.(png|jpg|jpeg|gif)$/, loader: 'url-loader?limit=100000&name='+BaseFolder+'images/[name].[ext]' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?name='+BaseFolder+'fonts/[name].[ext]' },
{ test: /\.(woff|woff2)$/, loader:'url-loader?prefix=font/&limit=5000&name='+BaseFolder+'fonts/[name].[ext]' },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream&name='+BaseFolder+'fonts/[name].[ext]' },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml&name='+BaseFolder+'images/[name].[ext]' },
]
},
plugins: plugins
}
};
Yes this must be included in your node_modules, but the point is that you have include that in your compiled js file or not, i.e.
you must have used webpack or gulp to compile all your dependencies of js to give one file and you must have forget to include that dependency file in webpack file or gulpfile, Please check or provide sample of your webpack or gulpfile.
I think that DropdownInput is named export from react-dropdown-input since in index.js file in the repository its exported as
module.exports = DropdownInput;
So need to import it like
import {DropdownInput} from 'react-dropdown-input'

Vue.js / webpack: how do I clear out old bundle main-*.js files when hot-reload transpiles them?

I'm using Vue.js to make an SPA application with Django and I transpile, uglify, and bundle the code using webpack (specifically webpack-simple from vue-cli setup).
I use the following to "watch" and hot-reload the code:
$ ./node_modules/.bin/webpack --config webpack.config.js --watch
The problem is every time I change the code and it gets built it generates a new bundle .js file and updates webpack-stats.json to point to that one, but doesn't delete the old ones. How do I have it delete the old (useless) files?
webpack.config.js:
var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
context: __dirname,
// entry point of our app.
// assets/js/index.js should require other js modules and dependencies it needs
entry: './src/main',
output: {
path: path.resolve('./static/bundles/'),
filename: "[name]-[hash].js",
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
],
module: {
loaders: [
{ test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader'}, // to transform JSX into JS
{test: /\.vue$/, loader: 'vue-loader'}
],
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src')
}
},
}
webpack-stats.json:
{
"status":"done",
"chunks":{
"main":[
{
"name":"main-faa72a69b29c1decd182.js",
"path":"/Users/me/Code/projectname/static/bundles/main-faa72a69b29c1decd182.js"
}
]
}
}
Also what's a good way to add this to git/source control? Otherwise it changes everytime and I have to add it like so:
$ git add static/bundles/main-XXXXX.js -f
which gets annoying.
Any pointers? Thanks!
You need clean-webpack-plugin github link
First install it:
npm i clean-webpack-plugin --save-dev
Then in webpack.config.js add these lines(I have added comments the lines I added):
var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
const CleanWebpackPlugin = require('clean-webpack-plugin'); // require clean-webpack-plugin
function resolve (dir) {
return path.join(__dirname, dir)
}
// the path(s) that should be cleaned
let pathsToClean = [
path.resolve('./static/bundles/'), // same as output path
]
// the clean options to use
let cleanOptions = {
root: __dirname,
exclude: [], // add files you wanna exclude here
verbose: true,
dry: false
}
module.exports = {
context: __dirname,
// entry point of our app.
// assets/js/index.js should require other js modules and dependencies it needs
entry: './src/main',
output: {
path: path.resolve('./static/bundles/'),
filename: "[name]-[hash].js",
},
plugins: [
new CleanWebpackPlugin(pathsToClean, cleanOptions), // add clean-webpack to plugins
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
],
module: {
loaders: [
{ test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader'}, // to transform JSX into JS
{test: /\.vue$/, loader: 'vue-loader'}
],
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src')
}
},
}
And that's it, now every time you will run npm run build, the plugin will delete the static/bundles/ folder then build, so all your previous files will get removed, only new files will be there. It won't remove old files while watching with npm run watch
The current latest version does not need any options passed in for most cases. Consult the documentation for more specifics https://www.npmjs.com/package/clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpackConfig = {
plugins: [
/**
* All files inside webpack's output.path directory will be removed once, but the
* directory itself will not be. If using webpack 4+'s default configuration,
* everything under <PROJECT_DIR>/dist/ will be removed.
* Use cleanOnceBeforeBuildPatterns to override this behavior.
*
* During rebuilds, all webpack assets that are not used anymore
* will be removed automatically.
*
* See `Options and Defaults` for information
*/
new CleanWebpackPlugin(),
],
};
module.exports = webpackConfig;
You should adjust webpack so a new bundle is only being created when actually building for production.
From the webpack-simple vue-cli template, you'll see that uglifying and minifying only take place when it is set to a production env, not a dev env:
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}

Still getting 'Symbol' is undefined' error even after adding babel-polyfill in my webpack

https://babeljs.io/docs/usage/polyfill/#usage-in-browser
I did not understand the lines on the documentation page under:
Usage in Browser heading
can someone help me with what else is required:
Below are my code snippets:
I'm using storybook as a boilerplate:
webpack.config.js file:
entry: [
'babel-polyfill',
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs
]
index.js file:
import 'babel-polyfill';
import React from 'react';
Is there some other files also where I need to add babel-polyfill related code.
require('babel-polyfill');
var path = require('path');
var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
var getClientEnvironment = require('./env');
var paths = require('./paths');
var publicPath = '/';
var publicUrl = '';
var env = getClientEnvironment(publicUrl);
module.exports = {
devtool: 'cheap-module-source-map',
entry: ['babel-polyfill',
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
paths.appIndexJs
],
output: {
path: paths.appBuild,
pathinfo: true,
filename: 'static/js/bundle.js',
publicPath: publicPath
},
resolve: {
fallback: paths.nodePaths,
extensions: ['.js', '.json', '.jsx', ''],
alias: {
'react-native': 'react-native-web'
}
},
module: {
// First, run the linter.
// It's important to do this before Babel processes the JS.
preLoaders: [{
test: /\.(js|jsx)$/,
loader: 'eslint',
include: paths.appSrc,
}],
loaders: [{
exclude: [/\.html$/, /\.(js|jsx)$/, /\.css$/, /\.json$/],
loader: 'url',
query: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
},
// Process JS with Babel.
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: 'babel',
query: {
cacheDirectory: true
}
}, {
test: /\.css$/,
loader: 'style!css?importLoaders=1!postcss'
}, {
test: /\.json$/,
loader: 'json'
}
]
},
// We use PostCSS for autoprefixing only.
postcss: function() {
return [
autoprefixer({
browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway
]
}),
];
},
plugins: [
new InterpolateHtmlPlugin({
PUBLIC_URL: publicUrl
}),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),
new webpack.DefinePlugin(env),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules)
],
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
There are two ways to get this code into your browser.
1 - Include the babel-polyfill module in the webpack bundle
2 - Load it as an external script in your html
Webpack - adding bundle dependencies with entry arrays
Put an array as the entry point to make the babel-polyfill module available to your bundle as an export.
With webpack.config.js, add babel-polyfill to your entry array.
The webpack docs explain how an entry array is handled:
What happens when you pass an array to entry? Passing an array of file
paths to the entry property creates what is known as a "multi-main
entry". This is useful when you would like to inject multiple
dependent files together and graph their dependencies into one
"chunk".
Webpack.config.js
require("babel-polyfill");
var config = {
devtool: 'cheap-module-eval-source-map',
entry: {
main: [
// configuration for babel6
['babel-polyfill', './src/js/main.js']
]
},
}
Alternative to Webpack - load babel-polyfill as an external script in the browser html
The alternative to using webpack would mean including the module as an external script in your html. It will then be available to code in the browser but the webpack bundle won't be directly aware of it.
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.22.0/polyfill.js"></script>

webpackJsonp not defined using karma-webpack?

I am building a boilerplate with webpack and karma with mocha.
This is the configuration I am using for karma-webpack. I am new to webpack.
var path = require('path');
var webpack = require('webpack');
var entries = {
"app": ["./index.js"]
};
var root = './';
var testSrc = path.join(root, 'tests/');
var jsSrc = path.join(root, 'src/javascripts/');
var publicPath = path.join(root , 'public/');
var filenamePattern = 'index.js';
var extensions = ['js'].map(function(extension) {
return '.' + extension;
});
var webpackConfig = {
context: jsSrc,
resolve: {
root: jsSrc,
extensions: [''].concat(extensions)
},
resolveLoader: {
root: path.join(__dirname, "node_modules")
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}]
},
entry: entries,
output: {
filename: filenamePattern,
publicPath: publicPath
},
plugins: [new webpack.optimize.CommonsChunkPlugin({
name: 'shared',
filename: filenamePattern,
})]
};
var karmaConfig = {
frameworks: ['mocha'],
files: ['tests/test-index.js'],
preprocessors: {
'tests/**/*.js': ['webpack']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
},
singleRun: false,
autoWatch: true,
colors: true,
reporters: ['nyan'],
browsers: ['Chrome'],
plugins: [
require("karma-nyan-reporter"),
require("karma-mocha"),
require("karma-firefox-launcher"),
require("karma-webpack"),
require("karma-chrome-launcher")
]
};
module.exports = function(config) {
config.set(karmaConfig);
};
When I run karma start karma.local.conf.js it does not execute the tests becouse it says in the browser webpackJsonp is not defined. I was wondering if I am missing something in this configuration.
You can solve this problem by changing the order of your files loaded into your Karma browser.
karma.conf.js
files: [
'build/shared.js',
'build/**/*.js',
]
Shared (in my case) is the file where "webpackJsonp" is defined.
By putting this one at the top of the files it will be loaded before the other js files. Solving the error.
I had also same problem coming in Browser in my Asp.Net MVC 5 based web application:
"webpackJsonp is not defined"
although I am not using Karma. The solution I found was to move the commons chunk file to normal script tag based inclusion. I was earlier loading this file via Asp.Net MVC's bundling BundleConfig.cs file. I guess sometimes for some unknown reason this commons chunk file loads after my other module files and thus Browser complaints.
I removed the commons.chunk.js inclusion from BundleConfig.cs and added it to page using a normal script tag, right before my bundle class:
<script type="text/javascript" src="#Url.Content("~/Scripts/build/commons.chunk.js")"></script>
#Scripts.Render("~/bundles/myModules")
After doing some research on why or how this problem was happening I found out that there is a plugin of web pack messing with karma.
So the configuration result would be:
var path = require('path');
var webpack = require('webpack');
var entries = {
"app": ["./index.js"]
};
var root = './';
var testSrc = path.join(root, 'tests/');
var jsSrc = path.join(root, 'src/javascripts/');
var publicPath = path.join(root , 'public/');
var filenamePattern = 'index.js';
var extensions = ['js'].map(function(extension) {
return '.' + extension;
});
var webpackConfig = {
context: jsSrc,
resolve: {
root: jsSrc,
extensions: [''].concat(extensions)
},
resolveLoader: {
root: path.join(__dirname, "node_modules")
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}]
},
entry: entries,
output: {
filename: filenamePattern,
publicPath: publicPath
}
};
var karmaConfig = {
frameworks: ['mocha'],
files: ['tests/test-index.js'],
preprocessors: {
'tests/**/*.js': ['webpack']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
},
singleRun: false,
autoWatch: true,
colors: true,
reporters: ['nyan'],
browsers: ['Chrome'],
plugins: [
require("karma-nyan-reporter"),
require("karma-mocha"),
require("karma-firefox-launcher"),
require("karma-webpack"),
require("karma-chrome-launcher")
]
};
module.exports = function(config) {
config.set(karmaConfig);
};
So I removed webpack plugin CommonsChunkPlugin. Here is another reference to this problem.
https://github.com/webpack/karma-webpack/issues/24

Categories