Webpack includes unused library in bundle.js - javascript

I don't understand why...
Include like 100Kbytes of a unused library:
/*!
* The buffer module from node.js, for the browser.
*
* #author Feross Aboukhadijeh <feross#feross.org> <http://feross.org>
* #license MIT
*/
...
...
My webpack.deploy.config.js
'use strict';
/* eslint-env node */
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const config = {
addVendor: function (name, path) {
this.resolve.alias[name] = path;
this.module.noParse.push(new RegExp(`^${name}$`));
},
node: {
Buffer: false,
global: false,
process: false,
setImmediate: false
},
entry: {
app: [
'./src/main.jsx'
],
vendors: [
'jquery',
'semantic',
'semantic.css',
'react',
'react-dom'
]
},
resolve: { alias: {} },
output: {
path: `${__dirname}/build`,
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new CopyWebpackPlugin([{ from: './src/static', to: './' }]),
new webpack.optimize.CommonsChunkPlugin('app', null, false),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
],
module: {
noParse: [],
loaders: [
{
test: /\.(jsx)?$/,
exclude: /node_modules/,
loader: 'babel'
},
{
test: /\.(js)$/,
loader: 'babel',
exclude: [/node_modules/, /bower_components/]
},
{
test: /\.(css)$/,
loader: 'style!css'
},
{
test: /\.(scss)$/,
loader: 'style!css!sass'
},
{
test: /\.(less)$/,
loader: 'style!css!less'
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000'
}
]
}
};
config.addVendor('jquery', `${__dirname}/bower_components/jquery/dist/jquery.min.js`);
config.addVendor('semantic', `${__dirname}/bower_components/semantic/dist/semantic.min.js`);
config.addVendor('semantic.css', `${__dirname}/bower_components/semantic/dist/semantic.min.css`);
config.addVendor('react', `${__dirname}/bower_components/react/react.min.js`);
config.addVendor('react-dom', `${__dirname}/bower_components/react/react-dom.min.js`);
module.exports = config;
I am using es6 with babel and react, the code works well, just trying to minify the package.
Also uses a cross library (node/browser) that use http and https, but I think its not the problem.

I faced the similar problem when migrated from webpack1 to webpack2. The bundle size increased from 125kb to 164kb (minimized).
Looks like the major part takes the buffer library which presumably comes from css-loader and adds source-map support.
I opened an issue https://github.com/webpack-contrib/style-loader/issues/194 and looks like the simple workaround is to add node: {Buffer: false} to the webpack config. Read more at: https://webpack.js.org/configuration/node/

Related

Webpack cannot find properly path for slick files

I started to using a webpack bundler, and I got a little issue with slick slider.
Slick fonts and gif doesn't load properly
It looks like webpack skips main folder, where my project is, and looking for files in d:/node_modules instead of d:/main_folder/node_modules
I was trying to fix this by creating slick-fix.scss and set font and loader path
but it doesn't work properly
This is the error screenshot:
slick-fix.scss
$slick-loader-path: "/node_modules/slick-carousel/slick/" !default;
$slick-font-path: "/node_modules/slick-carousel/slick/fonts/" !default;
main.scss
#import "slick-fix";
#import "~slick-carousel/slick/slick.scss";
#import "~slick-carousel/slick/slick-theme.scss";
main.js
require('./styles/main.scss');
require('jquery');
import 'slick-carousel/slick/slick';
$('.slider').slick();
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const webpack = require('webpack');
const $ = require('jquery');
module.exports = {
context: path.resolve(__dirname),
entry: './src',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
}
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.$': 'jquery',
'window.jQuery': 'jquery'
})
]
}
You cannot access local paths from your http server. In other words, you cannot load files from your harddrive directly. They have to be served by the server.

Using Imports with .Net, React.Js, and Url.Content

I am using a .Net MVC framework, and trying to render a jsx (React) file that has imports. I am including this file in the razor page (cshtml) through the standard Url.Content injection as follows:
<script src="#Url.Content("~/js/queue/QueueIndex.js")"></script>
<script>
ReactDOM.render(React.createElement(QueueIndex), document.getElementById("queue-index"));
jQuery(window).on("load scroll", function () {
'use strict'; // Start of use strict
// Loader
$("#dvLoading").fadeOut("fast");
});
</script>
If I do not have an import at the top of my React file (QueueIndex.jsx) the page loads just fine. However, I would like to import the react-table package, but if include any imports in my QueueIndex.jsx file, the page breaks.
The error I'm getting is require is not defined.
I think the solution is somewhere in the use of webpack, here is my config:
const webpack = require("webpack");
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
nhqueue: './wwwroot/js/queue/QueueIndex.jsx'
},
output: {
path: __dirname + '/wwwroot/js/',
publicPath: '/wwwroot/js/',
filename: '[name].bundle.js'
},
module: {
preLoaders: [
],
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{ test: /\.tsx?$/, loaders: ['babel', 'ts'] },
{ test: /\.json$ /, loader: "json-loader" },
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: "babel",
query:
{
presets: ['react']
}
}
],
externals: {
"moment": "moment",
},
},
devtool: 'source-map',
target: 'web',
plugins: [
new CleanWebpackPlugin(['./wwwroot/js/*.js'], {
root: __dirname,
verbose: true,
dry: false
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin()
],
resolve: {
extensions: ['', '.jsx', '.js', '.tsx', '.ts']
},
node: {
fs: "empty",
child_process: "empty"
}
}
Unfortunately, I have had no luck there. Please let me know if you have any ideas of how to resolve this issue. Thanks!
Also, Here is the Babel configuration:
{"presets" : ["es2015", "react"]}

How to setup webpack for supporting ES6 Modules in Node

I'm using Webpack for bundle client and server code, so my webpack.config.js looks like:
module.exports = [
{ /* client config */ },
{ /* server config */ },
];
I want to write ES6 (modules) in both and transpile code to ES5 using Babel.
For client, this can be done with babel-loader:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
},
}
Based on this, I wrote babel loader for server:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
},
}
Something tells me that babel-loader will never work for this purpose.
After ran webpack, bundles are right located but server entry point (server.js) aren't transpiled correctly:
SyntaxError: Unexpected token import
Generally when we want to transpile Node code, we would use babel-cli package and add a script in package.json:
"scripts": {
"build": "babel src -d dist"
}
and manually:
npm run build
My question is: How to setup ES6 transpiling with Babel for Node inside webpack.config.js?
+BONUS
webpack.config.js
const path = require('path');
const babelRcClient = {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
};
const babelRcServer = {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
};
const babelLoaderClient = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcClient,
};
const babelLoaderServer = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcServer,
};
module.exports = [
{
context: __dirname,
entry: './shared/index.js',
output: {
path: path.resolve(__dirname, './static'),
filename: 'bundle.js',
},
module: {
loaders: [
babelLoaderClient,
],
},
plugins: [],
},
{
context: __dirname,
entry: './server/server.js',
target: 'node',
output: {
path: path.resolve(__dirname, './build'),
filename: 'server.js',
libraryTarget: 'commonjs',
},
externals: [ /^(?!\.|\/).+/i, ],
module: {
loaders: [
babelLoaderServer,
],
},
plugins: [],
},
]
By specifying
targets: {
'node': 'current',
}
you are telling babel to transpile your code to node version which you are using to transpile the code.
Are you using the same node version on production?
Try specifying numeric node version, e.g. 6.11.2 and then run transpilation.
Another thing you can do is tell babel to leave ES6 modules in ES6 way and don't replace it with commonjs approach (which is default) by setting:
targets: {
'node': ...,
},
modules: false
This thing worked for me. Try and check once.
{
test: /\.(js|jsx)$/,
include: [].concat(
path.resolve('./app') //path to your application
),
use: ['babel-loader']
}

Webpack vendor 3rd party modules and babel-loader

My webpack build has 2 entries the vendor.js => vendor.js file and index.js => bundle.js.
Obviously vendor.js is the file where all the 3rd party libraries go, and in index.js goes my code.
I've been encountering some issues, many of the 3rd party libraries I include (in vendor.js), does not execute from bundle.js . Why is that?
My webpack configuration:
import path from 'path';
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var CopyWebpackPlugin = require('copy-webpack-plugin');
var precss = require('precss');
var autoprefixer = require('autoprefixer');
module.exports = {
entry: {
bundle: './dev/index.js',
vendor: './dev/vendor.js'
},
output: {
path: path.join(__dirname, 'dist'),
// publicPath: 'http://localhost:3000/',
filename: '[name].[hash].js',
chunkFilename: '[id].bundle.js'
},
externals: [
{
"./dev/assets/Paraxify/paraxify.js": "paraxify",
}
],
module: {
loaders: [
{
test: /\.js$/,
// exclude: path.resolve(__dirname, "node_modules"),
loader: 'babel-loader',
// exclude: [
// path.resolve(__dirname, "node_modules"),
// ],
query: {
compact: true,
plugins: ["transform-es2015-modules-commonjs"],
presets: ['es2015', 'stage-0']
}
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(
"style",
"css!postcss-loader!sass")
},
// { test: /jquery/, loader: 'expose?$!expose?jQuery' },
{ test: /\.jpg$/, loader: "file-loader?name=./assets/imgs/[name].jpg" },
{ test: /\.png$/, loader: "file-loader?name=./assets/imgs/[name].png" },
{ test: /\.(gif|woff|woff2|eot|ttf|svg)$/, loader: "url-loader" },
// { test: /\grabbing.gif$/, loader: "url-loader" },
// { test: /\preloader.gif$/, loader: "url-loader" },
// { test: /\default-skin.svg$/, loader: "url-loader" },
// { test: /\/default-skin.png$/, loader: "url-loader" }
// { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
]
},
postcss: function () {
return [precss, autoprefixer];
},
plugins: [
new CopyWebpackPlugin([
{ from: './dev/assets', to: 'assets' }
]),
new CopyWebpackPlugin([
{ from: './dev/bootstrap3', to: 'bootstrap3' }
]),
new webpack.optimize.CommonsChunkPlugin({
name: ['bundle', 'vendor']
}),
new HtmlWebpackPlugin({
hash: false,
template: 'ejs!./dev/index.html',
inject: 'body'
}),
new ExtractTextPlugin("styles.[hash].css"),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
// new webpack.ProvidePlugin({
// twentytwenty: "frontend/dev/assets/twentytwenty/js/jquery.twentytwenty"
// })
]
};
Example of the issue :
Vendor.js : Importing Scrollreveal (https://scrollrevealjs.org/)
import $ from 'jquery';
// import 'eqcss';
// import Rx from 'rx';
import * as ScrollReveal from 'scrollreveal';
And when I do : window.sr = ScrollReveal({ reset: true }); for the variable to be available globally, I get an error in the browser's console : Uncaught TypeError: ScrollReveal is not a function
Can someone explain me What I'm doing incorrectly? Thanks

Webpack: Loading images from html templates

I'm trying to set up an angular project using Webpack but I can't figure out how to reference images from within html templates and have them included in the build.
My project tree is as follows:
package.json
app/
- images/
- foo.png
- scripts/
- styles/
- templates/
I'm trying to use html-loader along with url-loader and file-loader but it's just not happening.
This is an example template: app/templates/foo.html
<img src="../images/foo.png" />
Problem #1: I would like to be able to reference images relative to app/. Right now, the paths need to be relative to the template file and this will get ugly very quickly (../../../images/foo.png).
Problem #2: Even if I specify the relative path, as I have done above, the project builds successfully but nothing really happens. The paths are left as-is and no images appear in dist/.
Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
var ngminPlugin = require('ngmin-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
module.exports = function(config, env) {
var appRoot = path.join(__dirname, 'app/')
if(!env) env = 'development';
var webpackConfig = {
cache: true,
debug: true,
contentBase: appRoot,
entry: {
app: path.join(appRoot, '/scripts/app.coffee')
},
output: {
path: path.join(__dirname, 'dist/),
publicPath: '/',
libraryTarget: 'var',
filename: 'scripts/[name].[hash].js',
chunkFilename: '[name].[chunkhash].js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader?outputStyle=expanded&includePaths[]=./node_modules/foundation/scss/')
},
{
test: /\.coffee$/,
loader: 'coffee-loader'
},
{
loader: 'ngtemplate?relativeTo=' + (path.resolve(__dirname, './app')) + '/!html'
},
{
test: /\.png$/, loader: "url-loader?limit=100000&mimetype=image/png&name=[path][name].[hash].[ext]"
},
{
test: /\.jpg$/, loader: "file-loader?name=[path][name].[hash].[ext]"
},
{
test: /\.(woff|woff2)(\?(.*))?$/,
loader: 'url?prefix=factorynts/&limit=5000&mimetype=application/font-woff'
},
{
test: /\.ttf(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.eot(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.svg(\?(.*))?$/,
loader: 'file?prefix=fonts/'
},
{
test: /\.json$/,
loader: 'json'
}
]
},
resolve: {
extensions: [
'',
'.js',
'.coffee',
'.scss',
'.css'
],
root: [appRoot],
},
singleRun: true,
plugins: [
new webpack.ContextReplacementPlugin(/.*$/, /a^/),
new webpack.ProvidePlugin({
'_': 'lodash'
}),
new ExtractTextPlugin("styles/[name].[chunkhash].css", {allChunks: true}),
new HtmlWebpackPlugin({
template: appRoot + '/app.html',
filename: 'app.html',
inject: 'body',
chunks: ['app']
})
],
devtool: 'eval'
}
if(env === 'production') {
webpackConfig.plugins = webpackConfig.plugins.concat(
new ngAnnotatePlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin({
'process-env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
);
webpackConfig.devtool = false;
webpackConfig.debug = false;
}
return webpackConfig;
}
If you are using HTML templates in Webpack 2, in addition to use the file-loader you need to change in your HTML:
<img src="../images/foo.png" />
to this
<img src=<%=require("../images/foo.png")%> />
Yes, you will have to do so for loading images from different path.
I had similar issue and I resolved this using file loader:
.
loaders: [{
// JS LOADER
test: /\.js$/,
loader: 'babel-loader?optional[]=runtime',
exclude: /node_modules/
}, {
// ASSET LOADER
test: /\.(woff|woff2|ttf|eot)$/,
loader: 'file-loader'
},
{
//IMAGE LOADER
test: /\.(jpe?g|png|gif|svg)$/i,
loader:'file-loader'
},
{
// HTML LOADER
test: /\.html$/,
loader: 'html-loader'
},
{
//SCSS LOADER
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader?indentedSyntax"]
}
]
Good Luck
For Webpack 5 you have to write this way:
module: {
rules: [
// other stuff above.....
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
}
]
}
With Webpack 4, I was able to solve this problem by updating by html-loader to specify the root for my files. So given #syko's original structure; in webpack.config.js...
module: {
rules: [
// other stuff above.....
{
test: /\.html$/,
use: [
// ...The other file-loader and extract-loader go here.
{
loader: 'html-loader'
options: {
// THIS will resolve relative URLs to reference from the app/ directory
root: path.resolve(__dirname, 'app')
}
}
]
}
]
}
This tells the html-loader to interpret all absolute urls from the /app folder. So in our app/templates/foo.html, you can then use the following...
<img src="/images/foo.png" />
This then tells html-loader to see the above as path.resolve(__dirname, 'app', 'images', 'foo.png'). Then if you have extract-loader and/or file-loader, all the paths should be correct.
Managed to get this solution after hammering away at it for a while. The biggest confusion is where about in the loader stack the /images/foo.png is interpreted, in this case it starts at the html-loader plugin. Everything else after that, is more about how the image files are to be published.
Hope that helps.
You can use file-loader to extract images. Then using html-loader you can specify which tag-attribute combination should be processed by this loader via the query parameter attrs.
I could make it work with this configuration:
{
test: /\.(jpe?g|png|gif|svg|ico)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
},
{
test: /\.(html)$/,
use: {
loader: 'html-loader',
options: {
attrs: ['img:src', 'link:href']
}
}
}
Or in angular something like this:
attrs: [':ng-src', ':ng-href']

Categories

Resources