How to improve Webpack performance in Dev Environment? - javascript

How do i improve the webpack build time. Presently i am packing around 150 files. and taking around 15 secs(Which is too much time). And majority of time is being eaten up during "optimize chunk assets" which takes around 10 secs. Any way to bring this down to 3-4 secs max.
Or how do i disable the optimize step in webpack. I am not explicitly using any configuration for minifying/uglifying.
This is the Configuration i am using presently::
module.exports = {
context: __dirname,
entry: './js/main.js',
target: 'web',
module: {
loaders: [
{ test: /text!/, loader: 'raw-loader'},
{ test: /backbone/, loader: 'imports-loader?this=>window' },
{ test: /marionette/, loader: 'imports-loader?this=>window' },
{ test: /sprintf/, loader: 'script-loader' },
{ test: /\.css$/, loader: "style!css" },
{ test: /\.scss$/, loader: 'style!css!sass' },
{ test: /\.js$/, loader: 'jsx-loader?harmony' }
]
},
resolveLoader: {
root: path.join(__dirname, 'node_modules'),
alias: {
'text': 'raw'
}
},
output: {
filename: 'bundle.js',
library: 'require',
libraryTarget: 'this'
},
resolve: {
alias: alias,
root: path.join(__dirname, 'node_modules'),
extensions: ['', '.js', '.jsx']
},
externals: {
jquery: 'jQuery'
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'root.jQuery': 'jquery',
'Backbone': 'backbone',
'_': 'underscore',
'Marionette': 'marionette',
'sprintf': 'sprintf'
})
],
devtool: 'source-map'
};
Thanks for the help in Advance.

There are a couple of optimizations you can do with your build.
First, as it is, you are parsing all the files in your node_modules through the jsx loader. You want to exclude them.
loaders: [{
test: /\.js$/,
loader: 'jsx-loader?harmony',
exclude: /node_modules/, // <---
}]
Second, all your vendor files (which don't change during development) are compiled on every file change. That's not very efficient, you should separate the vendor files from the application code by using the CommonsChunkPlugin.
In essence, you have to add:
config.entry = {
app: './js/main.js',
vendor: ['react', 'moment', 'react-router', /* etc. all the "big" libs */],
};
config.output = {
filename: '[name].js', /* will create app.js & vendor.js */
};
config.plugins = [
/* ... */
new webpack.optimize.CommonsChunkPlugin(
/* chunkName= */"vendor",
/* filename= */"vendor.bundle.js"
),
];

Webpack offers many devtools: https://webpack.github.io/docs/configuration.html#devtool
you are using devtools: 'source-map'.
I changed to devtools: 'cheap-eval-source-map' and the chunk asset optimization goes from 4500ms to 306ms, and with devtools: 'eval' goes to 1ms.
Take note that both are not Production Suported, because the final .js file is too big, in my case is 13MB.

Related

bundle.js slow loading

bundle.js (2.4 Mb) loading take 40 sec - 1.5 min:
This is my webpack.config.js :
const webpack = require('webpack');
const config = {
entry: {
"App":__dirname + '/js/App.jsx'
},
output: {
path: __dirname + '/dist',
filename: 'bundle.js',
},
resolve: {
extensions: ['.js', '.jsx', '.css']
},
module: {
rules: [
{
test: /\.jsx?/,
exclude: /node_modules/,
use: 'babel-loader',
loader: 'babel-loader?cashezdirectory'
},
// { test: /\.css$/, loader: 'style-loader!css-loader' }
]
},
externals: {
react: 'React',
jquery: 'jQuery'}
};
module.exports = config;
Is the any way to make loading faster?
The configuration that you are using for webpack seems to be a development version. Try using a production configuration which usually provides extra optimisations like uglification and extract CSS plugin.
plugins: [
new ExtractTextPlugin('styles.css'),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true
})
],
This should reduce the bundle size considerably(at least half).
You should also check your server configuration for further optimisations like gzipping which will reduce the download size by ~5 times.

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/.

How to make webpack consume files

So I use Typescript with Webpack.
tsc compiles everything from .ts to .js and then I want to use webpack to make it usable by the browser. However the problem is that I still have all of these .js files lying around from tsc.
Is there some way to tell webpack:
"Pack all these things into a nice bundle, and destroy them after you're done!"
Yes, use the typescript loader for webpack.
The Configuration section of that page presents a sample webpack config
module.exports = {
entry: './app.ts',
output: {
filename: 'bundle.js'
},
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['.ts', '.tsx', '.js'] // note if using webpack 1 you'd also need a '' in the array as well
},
module: {
loaders: [ // loaders will work with webpack 1 or 2; but will be renamed "rules" in future
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{ test: /\.tsx?$/, loader: 'ts-loader' }
]
}
}
As a second real world example, here is the appropriate section from my personal webpack.config.js which also sets up babel and (p)react
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
'ts-loader'
]
}
]
},
resolve: {
modules: [
__dirname,
'node_modules'
],
extensions: ['.ts','.tsx','.js'],
alias: {
'react': 'preact-compat/dist/preact-compat.js',
'react-dom': 'preact-compat/dist/preact-compat.js'
}
},
Yes, it's possible. I recommend using awesome-typescript-loader for this purpose.
const rootDir = path.resolve(__dirname);
const path = require('path');
module.exports = {
entry: {
boot: [path.resolve(rootDir, 'src', 'boot')]
},
output: {
filename: 'js/[name].bundle.js',
path: path.resolve(rootDir, 'build')
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
}
};
If you use 3rd party modules or libraries, it's also recommended to create separate bundle for vendor files and use webpack.optimize.CommonsChunkPlugin. Check out configuration of webpack-typescript-postcss-universal-starter to see how you can easily use it.

webpack - splitting files and create 2 bundle

I'm try to achieve the following target using webpack
in brief I have 2 entry point:
App.js and App2.js
App1.js have a dependency with App1def.js
App2.js have dependency with App2def0x.js files
Cats.js is used by App1.js and App2.js
all appx.js files have also a dependency with Jquery and babel-polyfill
I'd like to compile in:
Vendor.min.js contaning jquery, babel-polyfill (shim)
Common.min.js containg Cats.js (the common file used by appx.js)
App1.boundle.js containing app1def.js
App2.boundle.js containing app2def01.js app2def02.js
my webpack config is here:
var webpack = require("webpack");
const createVendorChunk = require('webpack-create-vendor-chunk');
module.exports = {
entry: {
app:"./src/js/app.js",
app2:"./src/js/app2.js"
},
output: {
path: './bin',
filename:"[name].bundle.js",
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}]
},
resolve: {
extensions: ['', '.js', '.es6']
},
plugins: [
/*
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename: "vendor.min.js",
minChunks: Infinity
})
*/
createVendorChunk({
name:"vendor.min.js"
}),
createVendorChunk({
name:"common.min.js",
chunks:["common"]
}),
]
};
complete project is here : https://github.com/mydiscogr/webpack-babel-config/
can you try this?
entry: {
app:"./src/js/app.js",
app2:"./src/js/app2.js"
vendor: [
'jquery',
'moment',
'lodash',
'some other vendor'
]
},
output: {
path: './bin',
filename:"[name].bundle.js",
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}]
},
resolve: {
extensions: ['', '.js', '.es6']
},
plugins: [
// it moves cat.js to common.js
new webpack.optimize.CommonsChunkPlugin({
name: 'Common',
chunks: ['App1', 'App2']
}),
// some third party libraries (eg: jquery, moment) when used in App1, App2, and Common moves to vendor.js
new webpack.optimize.CommonsChunkPlugin({
name: 'Vendor',
minChunks: Infinity
}
// Just Other Tricks!!
// Delete 2 CommonsChunkPlugin option above and add this
new webpack.optimize.CommonsChunkPlugin({
// The order of this array matters
names: ['Common', 'Vendor'],
minChunks: 2
})
]
let me know if it works

Webpack module-type sourcemaps are pointing to 'undefined' file

I'm building an app with multiple widgets. These widgets are fairly big in size, so they are placed in separate sub-directories within the parent directory. The file structure looks something like this:
./
+-- server/
|
+-- client/
|
+-- widget1/
|
+-- widget2/
|
+-- widget3/
|
+-- package.json
+-- webpack.base.config
Each widget is a module completely separated from the other client and widgets, and are developed on their own, with their own development servers, etc.
Now the problem: when setting the webpackConfig.devtool to anything that uses module (ie. cheap-module-source-map), the widget files do not receive the correct source-maps. Instead they receive a filename/line number that looks like: (index):40. (or webpack:///:40 when mousing over) When clicking on said file in chrome, it points me to a file with these contents:
undefined
/** WEBPACK FOOTER **
**
**/
Now the incredibly weird thing about this is that even when building the client app, which brings all the widgets and the client-side code together, only the widget files have these messed up source-maps.
The contents of each widget is simply a bunch of .js and .scss files, with an index.html and development-server.js for development. The client side code is virtually the same, expect for the development files.
This is webpack-1, version 1.13.0.
My webpack.base.config looks like such:
const babelQuery = {
es2015: require.resolve('babel-preset-es2015'),
react: require.resolve('babel-preset-react'),
};
function createQuery(...paths) {
return paths.map(resolvePath => `presets[]=${resolvePath}`).join(',');
}
const fullQuery = createQuery(babelQuery.es2015, babelQuery.react);
module.exports = {
cache: true,
context: __dirname,
debug: true,
devtool: '#cheap-module-source-map',
entry: {},
output: {},
resolve: {
extensions: ['', '.js', '.jsx'],
},
module: {
loaders: [
{
test: /\.js$/,
loader: `babel-loader?cacheDirectory,${createQuery(babelQuery.es2015)}`,
exclude: /node_modules/,
},
{
test: /\.jsx$/,
loader: `react-hot-loader!babel-loader?cacheDirectory,${fullQuery}`,
exclude: /node_modules/,
},
{
test: /\.json$/,
loader: 'json-loader',
},
{
test: /\.scss$/,
loader: 'style-loader' +
'!css-loader?modules&sourceMap&localIdentName=[name]__[local]___[hash:base64:5]' +
'!postcss-loader!sass-loader?outputStyle=expanded&sourceMap',
},
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader?name=img/[name].[ext]',
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?v=\d+\.\d+\.\d+)?(\?[a-z0-9]+)?$/,
loader: 'file-loader',
},
{
test: /\.css$/,
loader: 'style-loader!css-loader?modules&localIdentName=[name]__[local]___[hash:base64:5]',
include: /flexboxgrid/,
},
{
test: /\.css$/,
loader: 'style-loader!css-loader',
exclude: /flexboxgrid/,
},
],
},
postcss() {
return [autoprefixer];
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
}),
],
};
The widgets' development servers modify the base config like so: (if it matters)
context: __dirname,
entry: {
bundle: [
'webpack/hot/dev-server',
'webpack-hot-middleware/client',
'./entry.jsx',
],
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: `http://localhost:${PORT}/assets/`,
filename: '[name].js',
},
Try eval-source-map or source-map.
It's slower I know, but with a small cost of longer rebuilding time in dev mode it works just fine.
My loader in webpack config looks like this:
{
output: {
pathinfo: true,
path: path.join(__dirname, "build"),
filename: "app.js",
publicPath: "/"
},
entry: [
"webpack-dev-server/client?http://0.0.0.0:3000",
"webpack/hot/only-dev-server",
"babel-polyfill",
"whatwg-fetch",
path.join(__dirname, "./main")
],
devtool: "eval-source-map",
module: {
loaders: [
{
test: /\.jsx?$/,
include: [
path.join(__dirname, "src"),
path.join(__dirname, "node_modules/localforage")
],
loader: "react-hot!babel?cacheDirectory"
},
]
}
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": "\"development\"",
"BASE_DIR": "\"baseDir\"",
}
})
]
}
and my .babelrc:
{
"presets": ["es2015", "stage-0", "react"],
"plugins": ["transform-decorators-legacy"],
"env": {
"production": {
"presets": ["react-optimize"]
}
}
}

Categories

Resources