Webpack output bundle larger than expected - javascript

The only thing I have in my entry JS file is:
import $ from 'jquery';
The jQuery JS file has the size of 29.5kb from jsdelivr.
My entry, that only includes jQuery, and nothing else, has the size of 86kb.
webpack.config.js
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: './src/js/scripts.js',
output: {
publicPath: "./dist/",
path: path.join(__dirname, "dist/js/"),
filename: "bundle.js"
},
watch: true,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: [
['env', { loose:true, modules:false }],
'stage-2'
],
plugins: [
['transform-react-jsx', { pragma:'h' }]
]
}
},
{
test: /\.pug$/,
use: [
"file-loader?name=[name].html&outputPath=../dist",
"extract-loader",
"html-loader",
"pug-html-loader"
]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?url=false', 'sass-loader']
})
},
]
},
resolve: {
alias: {
"TweenMax": path.resolve('node_modules', 'gsap/src/uncompressed/TweenMax.js'),
"TimelineMax": path.resolve('node_modules', 'gsap/src/uncompressed/TimelineMax.js'),
"animation.gsap": path.resolve('node_modules', 'scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap.js'),
}
},
plugins: [
new ExtractTextPlugin('../css/main.css'),
new UglifyJsPlugin({
test: /\.js($|\?)/i
})
],
stats: {
warnings: false
}
};
I should also mention, that going into the output bundle.js it still has the jQuery comments.
jQuery JavaScript Library v3.3.1
https://jquery.com/ ...
Even though I'm calling webpack with the -p argument and have the UglifyJS plugin, but the rest of the file is minified and mangled. Any ideas?
Thanks!

Try to copy and paste minified jquery from your link. It's has size of 86.9 kb.
This link also show that jquery v3 minified file size is also around 80kb.
So you already have correct setup. Maybe your 29.5kb file size is minified+gzipped file.

The 29.5kb file size is definitely the minified+gzipped version as per the link Niyoko posted.
I would also recommend checking out Fuse-Box It brought down our project size from over 1mb to under 200kb (Vendor and App bundles combined). Very easy to get going as well and it is TypeScript first :) It takes the best features from a number of the more popular bundlers and brings them together and builds on those features.

Related

Webpack configuration vs multiple bundles and ordering

I have a big javascript (angularjs) application which I have bootstrapped in a Angular 8 project. Now I also have many vendor libraries that are javascript files. For example Kendo libs, JQuery, foundation (zurb).
I have these vendor files, and my app files included in my webpack configuration. Which looks like this:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
'ang': './chunks/angularjs.ts',
'fou': './chunks/foundation.ts',
'ken': './chunks/kendo.ts',
'vws': './chunks/views.ts',
'dir': './chunks/directives.ts',
'ser': './chunks/services.ts',
'con': './chunks/controllers.ts',
'app': './main.ts',
'toastr': './app-old/scripts/toastr.js'
},
output: {
path: helpers.root('dist/dev'),
publicPath: '/',
filename: '[name].bundle.js'
},
// Currently we need to add '.ts' to the resolve.extensions array.
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
// Add the loader for .ts files.
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader?keepUrl=true'],
exclude: [/\.(spec|e2e)\.ts$/]
},
{
test: /\.less$/,
loader: 'less-loader', // compiles Less to CSS
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|tff|otf|eot|ico)$/,
loader: 'file-loader?name=assets/[name].[hash].[ext]'
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
// Exposes jQuery for use outside Webpack build
test: require.resolve(path.resolve(__dirname, './app-old/scripts/jquery-2.1.4.js')),
use: [{
loader: 'expose-loader',
options: 'jQuery'
}, {
loader: 'expose-loader',
options: '$'
}]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: '../config/index.html'
}),
// new webpack.ProvidePlugin({
// foundation: 'foundation-sites/js/foundation/foundation'
// }),
new webpack.ProvidePlugin({
$: path.resolve(__dirname, './app-old/scripts/jquery-2.1.4.js'),
jQuery: path.resolve(__dirname, './app-old/scripts/jquery-2.1.4.js'),
"window.jQuery": path.resolve(__dirname, './app-old/scripts/jquery-2.1.4.js')
}),
new webpack.ProvidePlugin({
toastr: 'toastr',
"window.toastr": "toastr"
})
]
}
You see that I have created different entry points, because I want smaller chunks (because of performance).
It compiles perfectly, but when I start up the application the troubles begin. I get al kinds of erros. It keeps telling my that JQuery needs to be loaded before Kendo is being loaded. And the foundation files need don't see the JQuery files.
But I made sure that they are globally available, as you can see in the file.
Not the strange thing.
When I throw everything in 1 TS file and use just only 1 entry point everything runs ok and I have no errors. :-)
But then my bundled file is huge and this is not good for the performance.
So my main question is?
How can I get multiple chunks for my vendor javascript files so that they can see each other?
I am starting to think that I don't need to use the entry points for smaller chunks.

Require not defined in script tag

I am writing an electron app using react as for the UI and webpack for bundling. Webpack is configured right now for the react part of the application as follows:
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.tsx',
target:'node',
output: {
filename: '[name].bundle.js',
path: path.join(__dirname, 'build')
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'ts-loader'
}
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader'
}
]
},
{
test: /\.css$/,
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
test: /\.scss$/,
use: [{
loader: "css-loader", options: {
sourceMap: true
}
}, {
loader: "sass-loader", options: {
sourceMap: true
}
}]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
plugins: [
new HtmlWebPackPlugin({
template: "./index.html",
filename: "./index.html"
}),
new CopyWebpackPlugin([{ from: 'public',ignore: ['*.html'] }])
],
devtool: 'eval-source-map'
}
In my index.html I need to use the following script tag for electron's rendering process :
<script>
require('build/bundle.js')
</script>
When I run webpack-dev-server everything compiles without error, but when I open chrome dev tools I see this error :
Uncaught ReferenceError: require is not defined
at (index):12
I had to target node in my webpack.config to make electron work so I assume the require function works in browser as well since if I were to create an electron app in a pure node.js environment(without webpack and react) it works without any additional configuration. So I guess there is an issue with my webpack configuration, but I can't find any useful resource online unfortunately. Can anyone help me out? Thanks in advance!
Electron is basically a chromium browser connected to a node process through « IPC ».
This means you don’t have require available in the browser.
You need to import your script like this:
<script src="/build/bundle.js"></script>
And also you need to change the target from node to electron-renderer for the browser code.
If you also need to build code for the node side you need to add the electron-main target.
See https://webpack.js.org/configuration/

configure Laravel mix mix.webpackConfig({}) with entry points and outputs

I'm developing an application that use php 5.6 and laravel 5.4. I'm using laravel mix for build my assets. I need to know how to use mix.webpackConfig({}) method to use another webpack configurations like use babel-loader, riot-tag-loader etc. Is there any way to use this method to do that with entry point and output files? For an example, I need to do following thing inside my mix.webpackConfig({}).
module.exports = {
entry: {
admin: ['./resources/assets/admin/js/app.js'],
'manuals/parent/child/js': ['./resources/views/manuals/parent/child/js/app.js']
},
output: {
filename: '[name]/app.js',
path: path.resolve(__dirname + '/public')
},
module: {
rules: [
{
test: /\.tag$/,
exclude: /node_modules/,
loader: 'riot-tag-loader',
query: {
type: 'es6',
hot: true
}
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
Is that possible? Is that so, please let me know how to do that. Thanks
I've hardly found the laravel-mix mix.webpackConfig({}) successfully initiated, and even working samples are rear. I do not know what framework you are trying to manage but this sample works; this is a config for less-loader, hope you can tune it to suit your purpose.
const path = require('path');
mix.webpackConfig({
module: {
rules: [
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader",
exclude: [
path.resolve(__dirname, "node-modules"),
path.resolve(__dirname, "resources/assets/less"),
],
},
]}
})
Mix is a configuration layer on top of Webpack, so to run your Mix tasks you only need to execute one of the NPM scripts that is included with the default Laravel package.json file: more details in official site
https://laravel.com/docs/5.7/mix

Extracting sass as css using webpack

First. I know questions like this were asked, but I am missing something to understand them. I am trying to compile scss to css. And I would like webpack to basically do the same as sass app.scss : app.css. I tried to configure it using extract-text-webpack-plugin, but I am doing something wrong or missing smth.
It worked if I include(app.scss) in app.js but this makes no sense because if anyone has disabled JavaScript the styles won't work.
This is my webpack.config.js file. I have no idea how to do it.
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var jsConfig = {
entry: "./_dev/scripts/app.js",
output: { filename: "./scripts/bundle.js" },
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
var scssConfig = {
entry: "./_dev/scss/app.scss",
output: { filename: "./content/app.css" },
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin({filename:"./_dev/scss/app.scss"}),
]
};
var config = [scssConfig, jsConfig];
module.exports = config;
Edit: I also found this. This series would have helped with all my questions so if you have similar questions make sure to read it before asking!
https://codeburst.io/simple-beginner-guide-for-webpack-2-0-from-scratch-part-v-495dba627718
You need to include your app.scss for webpack to be able to find your scss references because webpack will traverse your project and apply loaders to all files it can find through references starting from app.js recursively down. If you don't have references to app.scss somewhere in the project webpack can't find it and it won't build it. So in the entry of you project (assume it is app.js) you need to do this:
import 'relative/path/to/styles/app.scss';
But it doesn't mean that those who don't have js enabled won't receive your styles. You need to include app.scss only for the build phase of your project, after that your styles will be included in html and will be loaded even for those without js enabled.
webpack concepts section explains how webpack finds dependencies based on your entry point building its internal graph of dependencies.
Update:
There is a way that allows you to not add your app.scss in your js. You can include multiple files in your entry object in your webpack config. Here is an example of how configuration might look in your case:
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
entry: {
main: [
"./_dev/scripts/app.js",
"./_dev/scss/app.scss"
],
},
output: {
path: './scripts',
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(css|scss)/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin("./_dev/scss/app.scss"),
]
};
module.exports = config;
More information available on SO question webpack-multiple-entry-points-sass-and-js.
You also have incorrect configuration of ExtractTextPlugin in webpack. You are placing the whole path in the option for filename, which is not correct. In your case it should look like this:
plugins: [
new ExtractTextPlugin("./_dev/scss/app.css"),
]

Webpack and Angular HTML image loading

I have been breaking my head with webpack and angular. This might have a simple answer but I cant figure it out. I have read almost every answer here in stack overflow on this topic to no avail.
I have an html page like this (also other template that have images):
<body>
<img ng-src="../images/angular-webpack.png">
<md-button class="md-primary md-raised">
Button
</md-button>
</body>
I also have a webpack config:
var webpack = require('webpack');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
module.exports = {
context: path.resolve(__dirname + '/src'),
entry: ['./js/core/app.module.js'],
output: {
path: './release',
publicPath:'/',
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.html/,
exclude: 'node_modules',
loader: 'raw-loader'
},
{
test: /\.css/,
exclude: 'node_modules',
loader: 'style-loader!css-loader'
},
{
test: /\.(jpe?g|png)$/i,
exclude: 'node_modules',
loader: 'url-loader?limit=8192!img'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new CopyWebpackPlugin([
{from: './index.html', to: './index.html'}
], {
ignore: [
'*.txt',
{glob: '**/*', dot: true}
]
})
],
devServer: {
contentBase: './release'
},
watch: true
};
...but i do not see my images loading. I have tried url-loader, file-loader with publicPath and without it. I am confused, I do not know how to format the webpack config or the html image tag for it to work.
Anyone has any experience on getting images to work with webpack? Also I do not want to include my images in the controllers or any other js file. I want the images to be declared in the html page.
The raw-loader is supposed to turn a text file into a CommonJS module that exports the file contents as a string – nothing more.
If you want webpack to recognize the file as HTML and all its references in it, you need the html-loader. The html-loader parses the given file with an HTML parser and picks up references to other files within attributes. By default, that is only <img src="...">. In your case, you need to tell the html-loader to also look for ng-src attributes, like this:
// webpack.config.js
...
loaders: [{
test: /\.html$/,
loaders: [
"html?" + JSON.stringify({
attrs: ["img:src", "img:ng-src"]
})
]}
]

Categories