webpack react bundle file is huge - reactjs

Im trying to build react app using webpack as bundle tool.
the output bundle is huge. here is my webpack settings:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');
const validate = require('webpack-validator');
const parts = require('./libs/parts');
const PATHS = {
app:path.join(__dirname.toLowerCase(),'shared'),
build:path.join(__dirname.toLowerCase(),'build'),
//css:path.join(__dirname.toLowerCase(),'client','main.css')
css:[
//path.join(__dirname,'node_modules','purecss'),
//path.join(__dirname,'client','client.less'),
path.join(__dirname,'client','client.less')
]
};
const common = {
entry:{
app:PATHS.app,
style:PATHS.css
},
output:{
path:PATHS.build,
filename:'[name].js',
},
/*plugins:[
new HtmlWebpackPlugin({
title:"Webpack to pack the whole web",
template:"client/index.html"
})
]*/
};
var config;
switch (process.env.npm_lifecycle_event) {
case "build":
config = merge(common,
{
devtool: 'cheap-module-source-map',
output: {
path: PATHS.build,
filename: '[name].js',
// This is used for require.ensure. The setup
// will work without but this is useful to set.
chunkFilename: '[chunkhash].js'
}
},
parts.clean(PATHS.build),
parts.setFreeVariable(
'process.env.NODE_ENV',
'production'
),
parts.supportESSix(PATHS.app),
parts.extractBundle({
name: 'vendor',
entries: ['react','react-dom','react-router','react-addons-pure-render-mixin',
'redux','react-redux','immutable',"redux-thunk","superagent"]
}),
parts.purifyCSS(PATHS.css),
parts.setupLess(PATHS.css),
parts.minify(),
parts.compressBundle()
);
break;
default:
config = merge(common,
{
devtool: 'source-map',
output: {
path: PATHS.build,
filename: '[name].js',
// This is used for require.ensure. The setup
// will work without but this is useful to set.
chunkFilename: '[chunkhash].js'
}
},
parts.clean(PATHS.build),
parts.setFreeVariable(
'process.env.NODE_ENV',
'production'
),
parts.supportESSix(PATHS.app),
parts.extractBundle({
name: 'vendor',
entries: ['react','react-dom','react-router','react-addons-pure-render-mixin',
'redux','react-redux','immutable',"redux-thunk","superagent"]
}),
parts.purifyCSS(PATHS.css),
parts.setupLess(PATHS.css),
parts.minify()
);
}
module.exports = validate(config);
the parts.js file which run specific task:
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
exports.devServer=function(options){
return {
devServer:{
historyApiFallback:true,
hot:true,
inline:true,
stats:'errors-only',
host:options.host,
port:options.port
},
plugins:[
new webpack.HotModuleReplacementPlugin({
multiStep:true
})
]
};
};
exports.setupCSS=function(paths) {
return {
module:{
loaders:[
{
test: /\.css$/,
loaders: ['style', 'css'],
include: paths
}
]
}
};
};
//minify output
exports.minify=function(){
return {
plugins:[
new webpack.optimize.UglifyJsPlugin({
beautify:false,
comment:false,
compress:{
warnings:false,
drop_console:true
}
})
]
}
};
exports.setFreeVariable = function(key, value) {
const env = {};
env[key] = JSON.stringify(value);
return {
plugins: [
new webpack.DefinePlugin(env)
]
};
}
exports.extractBundle = function(options) {
const entry = {};
entry[options.name] = options.entries;
return {
// Define an entry point needed for splitting.
entry: entry,
plugins: [
// Extract bundle and manifest files. Manifest is
// needed for reliable caching.
new webpack.optimize.CommonsChunkPlugin({
names: [options.name, 'manifest']
})
]
};
}
exports.clean = function(path) {
return {
plugins: [
new CleanWebpackPlugin([path], {
// Without `root` CleanWebpackPlugin won't point to our
// project and will fail to work.
root: process.cwd()
})
]
};
}
exports.extractCSS = function(paths) {
return {
module: {
loaders: [
// Extract CSS during build
{
test:/\.less$/,
loader: ExtractTextPlugin.extract('style','css'),
include: paths
}
]
},
plugins: [
// Output extracted CSS to a file
new ExtractTextPlugin('[name].[chunkhash].css')
]
};
}
exports.purifyCSS = function(paths) {
return {
plugins: [
new PurifyCSSPlugin({
basePath: process.cwd(),
// `paths` is used to point PurifyCSS to files not
// visible to Webpack. You can pass glob patterns
// to it.
paths: paths
}),
]
}
}
exports.setupLess=function(path) {
return {
module:{
loaders:[
{
test:/\.less$/,
loader:ExtractTextPlugin.extract('style-loader','css-loader!less-loader'),
include:path
},
{ test: /\.(ttf|eot|svg)$/, loader: "file-loader" },
{test: /\.eot$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader: "url?limit=10000&minetype=application/font-woff" }
]
},
plugins: [
// Output extracted CSS to a file
new ExtractTextPlugin('style.css')
]
}
};
exports.supportESSix=function(path) {
return {
module:{
loaders:[
{
test:/\.js$/,
loader:"babel",
include:path,
exclude:"node_modules"
}
]
}
};
};
exports.compressBundle=function(){
return {
plugins: [
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
}
}
These are dependencies packages:
"dependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"body-parser": "^1.15.2",
"compress": "^0.99.0",
"cookie-parser": "^1.4.3",
"csurf": "^1.9.0",
"es6-promise": "^3.2.1",
"express": "^4.14.0",
"express-jwt": "^5.0.0",
"express-session": "^1.14.1",
"form-data": "^2.0.0",
"history": "^3.2.1",
"immutable": "^3.8.1",
"isomorphic-fetch": "^2.2.1",
"jsonwebtoken": "^7.1.9",
"method-override": "^2.3.6",
"mongoose": "^4.6.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"password-hash": "^1.2.2",
"q": "^1.4.1",
"react": "^15.3.2",
"react-addons-pure-render-mixin": "^15.3.1",
"react-dom": "^15.3.1",
"react-redux": "^4.4.5",
"react-router": "^2.7.0",
"redux": "^3.6.0",
"redux-immutable": "^3.0.8",
"redux-thunk": "^2.1.0",
"sanitize-html": "^1.13.0",
"superagent": "^2.3.0"
},
but the output is really big:
Question:
anything wrong with my webpack config ?
is that normal for this bundle size ?
3.if not. How do I get smaller size of this bundle?
Thank you.

Related

ModuleParseError with NextJs

I try to migrate my app created with create-react-app to nextJs, and I got always this error :
[ error ] ./src/sass/common.scss
ModuleParseError: Module parse failed: Unexpected character '' (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
and here my file next.config.js :
const withPlugins = require("next-compose-plugins");
const withBundleAnalyzer = require("#next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true"
});
const withSass = require("#zeit/next-sass");
const withCSS = require("#zeit/next-css");
const withImages = require("next-images");
module.exports = withPlugins(
[withBundleAnalyzer, withImages, withSass, withCSS],
{
webpack(config, { buildId, dev, isServer, defaultLoaders, webpack }) {
config.module.rules.push({
test: /\.(png|woff|woff2|eot|ttf|svg|jpg|gif)$/,
use: [
defaultLoaders.babel,
{
loader: "url-loader",
options: {
limit: 100000,
name: "[name].[ext]"
}
}
]
});
return config;
}
});
and my package.json :
"devDependencies": {
"css-loader": "^3.4.2",
"cypress": "^3.1.0",
"file-loader": "^5.0.2",
"node-sass": "^4.13.1",
"redux-devtools": "^3.5.0",
"sass-loader": "^8.0.2",
"url-loader": "^3.0.0"
}
I don't understand... I have a loader for file scss, if someone could explain to me, thanks you!
You didn't add loader for SCSS file type. You can do it like this:
config.module.rules.push({
test: /\.(scss)$/,
loaders: [
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
],
});
Here I use two loaders. sass-loader convert your SCSS to CSS, then run through css-loader to process #import(), url(), etc.
Don't forget to install these two loaders using npm install.

bundle.js still contains arrow function and default parameters after using babel pollyfill

I have added many settings given by Babel or others from stack overflow but the new features of ES6 such as arrow function and default parameter are still in my bundle.js
The bundle.js has content like below:
var nn = function(e={}) {
const {baseClasses: t, newClasses: n, Component: r} = e;
if (!n)
return t;
const a = At()({}, t);
return Object.keys(n).forEach(e=>{
n[e] && (a[e] = `${t[e]} ${n[e]}`)
}
),
a
};
As a result, when I open my page in IE11, the error missing ')' happened which point to function(e={}).
Here is my webpack.config.js:
const entries = require("./config/pages").reduce(function(map, page) {
map[page] = `./src/${page}/index.js`;
return map;
}, {});
module.exports = {
mode: 'development',
entry: ["#babel/polyfill",...entries],
output: {
path: path.resolve(__dirname,'dist'),
publicPath: '/',
filename: 'myapp/static/js/[name]/bundle.js'
},
devtool: 'source-map',
module: require("./config/loaders"),
devServer:{
open: true,
publicPath: '/',
historyApiFallback: true,
disableHostCheck: true
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new webpack.ProvidePlugin({
fetch: "isomorphic-fetch",
})
]
};
and ./config/loaders for module
module.exports = {
rules: [
{
test: /\.(js|jsx)$/,
// exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.(css|less)$/,
use: ["style-loader", "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 500, //small than 500 use url, otherwise use base64
outputPath:'inquiry/static/img/'
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
outputPath: 'myapp/static/fonts/'
}
}]
}
]
};
the .babelrc:
{
"presets": [
// ["#babel/env",
// {
// "targets": {
// "browsers": "ie 11"
// },
// "useBuiltIns": "usage",
// "corejs": "3.0.1",
// }
// ],
["#babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": "3.0.1",
}],
"#babel/react"
],
"plugins": [
["#babel/transform-runtime"],
["#babel/plugin-transform-parameters"],
["#babel/plugin-transform-arrow-functions"],
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"#babel/plugin-proposal-class-properties",
{
"loose": true
}
],
]
}
Also, I have imported '#babel/polyfill' in my index.js
PS: I have noticed that the code contains ES6 features is from Meterial UI lib in node_modules, so I deleted exclude: /node_modules/, in babel loader rule but it still does not work.
I am using webpack 5, and setting target to es5 in webpack.config.js solved the problem for me.
module.exports = {
target: 'es5',
...
}
We are targeting specific browsers in the #babel/preset-env plugin, defined in the babel.config.js (which is a another way of declaring the babel configuration).
presets: [
[
'#babel/preset-env',
{
modules: 'commonjs',
useBuiltIns: 'entry',
targets: {
chrome: '58',
firefox: '54',
ie: '11',
safari: '10',
opera: '44',
edge: '16'
}
}
],
[
'#babel/preset-react'
]
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties'
]
Please try the target declaration like I posted above.
We use babel/preset-env 7.3.1 and it's corejs is not a top-level config option.
Update
I was able to make it work with a test project of which I tried to match your setup as best as possible. You can use this to slowly add complexity and modules that you use in your project to isolate the problem. This basic setup matches yours and works well. You can use this as a starting point.
package.json
{
"name": "babel-transprile-error",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"#babel/core": "^7.4.3",
"#babel/plugin-proposal-class-properties": "^7.4.0",
"#babel/plugin-proposal-decorators": "^7.4.0",
"#babel/plugin-transform-arrow-functions": "^7.2.0",
"#babel/plugin-transform-parameters": "^7.4.3",
"#babel/plugin-transform-runtime": "^7.4.3",
"#babel/polyfill": "^7.4.3",
"#babel/preset-env": "^7.4.3",
"#babel/preset-react": "^7.0.0",
"#babel/runtime": "^7.4.3",
"babel-loader": "^8.0.5",
"mini-css-extract-plugin": "^0.6.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.1"
}
}
webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: ["#babel/polyfill", './src/page/index.js'],
output: {
path: path.resolve(__dirname,'dist'),
publicPath: '/',
filename: 'myapp/static/js/[name]/bundle.js'
},
devtool: 'source-map',
module: require("./config/loaders.js"),
devServer:{
open: true,
publicPath: '/',
historyApiFallback: true,
disableHostCheck: true
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new webpack.ProvidePlugin({
fetch: "isomorphic-fetch",
})
]
};
.babelrc
{
"presets": [
// ["#babel/env",
// {
// "targets": {
// "browsers": "ie 11"
// },
// "useBuiltIns": "usage",
// "corejs": "3.0.1",
// }
// ],
["#babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": "3.0.1",
}],
"#babel/react"
],
"plugins": [
["#babel/transform-runtime"],
["#babel/plugin-transform-parameters"],
["#babel/plugin-transform-arrow-functions"],
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"#babel/plugin-proposal-class-properties",
{
"loose": true
}
],
]
}
src/page/index.js
import React, { Component } from 'react';
class someComponent extends React.Component {
constructor(props) {
super(props);
}
method(e = {}) {
console.log(e);
var nn = function(e={}) {
const {baseClasses: t, newClasses: n, Component: r} = e;
if (!n)
return t;
const a = At()({}, t);
return Object.keys(n).forEach(e=>{
n[e] && (a[e] = `${t[e]} ${n[e]}`)
}
), a
};
}
render() {
return (
<div onClick={ e => { this.method(e) }}/>
)
}
}
export default someComponent;
config/loaders.js
module.exports = {
rules: [
{
test: /\.(js|jsx)$/,
// exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.(css|less)$/,
use: ["style-loader", "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 500, //small than 500 use url, otherwise use base64
outputPath:'inquiry/static/img/'
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
outputPath: 'myapp/static/fonts/'
}
}]
}
]
};
In my case, it caused by some packages that contains default parameters. So I fixed that by include node_modules in babel-loader:
{
test: /\.(jsx?)$/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/env', '#babel/react'],
plugins: [
'#babel/plugin-transform-runtime',
[
'#babel/plugin-proposal-class-properties',
{
loose: true
}
],
['#babel/plugin-proposal-export-default-from'],
'#babel/plugin-transform-parameters'
]
}
}
/** Include the node_modules folder to fix !! **/
// exclude: /node_modules/ // <== Here is the magic works !
},

Webpack production build: Unexpected token

I have been trying to deploy my production build with webpack but I can't get it done. I almost read and tried everything and can't make it work.
This is the last error that I have:
My webpack configuration looks like this:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const autoprefixer = require('autoprefixer');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const staticSourcePath = path.join(__dirname, 'static');
const sourcePath = path.join(__dirname, 'src');
const buildPath = path.join(__dirname, 'dist');
module.exports = {
devtool: 'cheap-module-source-map',
entry: {
// base: path.resolve(staticSourcePath, 'src/sass/base.scss'),
app: path.resolve(sourcePath, 'index.prod.jsx')
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js',
publicPath: '/'
},
resolve: {
extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
modules: [
sourcePath,
path.resolve(__dirname, 'node_modules')
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[chunkhash].js',
minChunks(module) {
return module.context && module.context.indexOf('node_modules') >= 0;
}
}),
new UglifyJsPlugin({
sourceMap: true,
uglifyOptions: {
ecma: 8,
compress: {
warnings: false
}
}
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer({
browsers: [
'last 3 version',
'ie >= 10'
]
})
],
context: staticSourcePath
}
}),
new webpack.HashedModuleIdsPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'),
path: buildPath,
excludeChunks: ['base'],
// filename: 'index.html',
minify: {
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
removeComments: true,
removeRedundantAttributes: true
}
}),
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script',
include: 'all',
fileBlacklist: [/\.(css|map)$/, /base?.+/]
}),
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'defer'
}),
new ExtractTextPlugin({
filename: '[name].[contenthash].css',
allChunks: true
}),
new CompressionPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.jsx$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8
})
],
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
},
{
test: /\.(js|jsx)$/,
loader: "babel-loader",
exclude: /node_modules/,
query: {
presets: ["es2015", "react", "env"],
plugins: [
"transform-object-rest-spread",
"transform-class-properties"
]
}
},
{
test: /\.(eot?.+|svg?.+|ttf?.+|otf?.+|woff?.+|woff2?.+)$/,
use: 'file-loader?name=assets/[name]-[hash].[ext]'
},
{
test: /\.(png|gif|jpg|svg)$/,
use: [
'url-loader?limit=20480&name=assets/[name]-[hash].[ext]'
],
include: staticSourcePath
}
]
}
};
I tried changing the presets of babel. I don't know if it could be a problem with the library query-string but even when I don't use it the error persists.
I also tried almost all configurations from https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/104 and can't make it work :C....
I hope someone can help me I have been fighting with this error since weekend and im near to kill myself T_T
Already tried babel-polyfill and dont work :(
Just updated to webpack 4 and solved my problem. To many people have this kind of error with webpack < 4.
I will leave my webpack 4 configuration here for those who had suffered like me
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
entry: ["babel-polyfill", "./src/index.js"],
resolve: {
extensions: ['.js', '.jsx']
},
output: {
publicPath: '/'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|jp(e*)g|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
}]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
devServer: {
// host: '0.0.0.0', /******* Para ver en lan*/
// disableHostCheck: true,/****** Para ver en lan */
historyApiFallback: true,
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new CompressionPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8
})
]
};
package.json
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"compression-webpack-plugin": "^1.1.11",
"css-loader": "^0.28.11",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.0.7",
"mini-css-extract-plugin": "^0.2.0",
"react": "^16.3.0",
"react-dom": "^16.3.0",
"url-loader": "^1.0.1",
"webpack": "^4.2.0",
"webpack-cli": "^2.0.12",
"webpack-dev-server": "^3.1.1"
},
.babelrc
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-object-rest-spread",
"transform-class-properties",
"transform-regenerator"
]
}
In my experience, it's usually Uglify being too aggressive.
I noticed that in your answer, you've swapped out Uglify for compression-webpack-plugin. That's probably what made the bug go away.
In your original package.json, I'd change the Uglify config to
new UglifyJsPlugin({
sourceMap:true,
cache: true,
parallel: true,
uglifyOptions:{
ecma:8
}
}),
First, you want to see Uglify's warnings. It'll tell you if there's code that's likely to get clobbered by the minification / obfuscation algorithm. If there are, you may have to play with the compress, mangle, toplevel or keep_fnames options depending on how your code is structured. https://github.com/mishoo/UglifyJS2#minify-options
I understand that this might show a lot of warnings from 3rd party libraries. There's a couple things you can do:
Find alternative libs that minify correctly (they'll probably be higher quality anyways).
Import the already minified versions of the lib from /dist instead of from /src and then exclude the lib from the Uglify plugin
The settings for cache and parallel just make the minification run a bit faster.
Sometimes such a problem may be a result of the non-transpiled packages (excluded from transpiling).
To solve this you should include these packages to transpiled code:
rules: [
...
test: /\.jsx?$/,
exclude(resource) {
return (
/node_modules/.test(resource)
&& !/node_modules\/(query-string|strict-uri-encode|split-on-first)/.test(resource)
);
},
...
]

Webpack config to consume an API with no CORS header

I need to consume a public API with no CORS header in it. I'm very new in webpack so i take this approach by readind articles. The scaffolding is provided by the company. This is a second part from a exercise for a job.
I been looking for hours and nothing seems to help. I always get the same response No 'Access-Control-Allow-Origin' header is present on the requested resource ...
This is my webpack.config.js at the moment
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './client/index.html',
filename: 'index.html',
inject: 'body'
})
module.exports = {
entry: './client/index.js',
output: {
path: path.resolve('dist'),
filename: 'index_bundle.js'
},
module: {
rules: [
{ test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{ test: /\.jsx$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.(sass)$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
}]
},
{
test: /\.html/,
loader: 'raw-loader'
},
],
},
plugins: [HtmlWebpackPluginConfig],
devServer: {
contentBase: './src/public',
port: 1184,
proxy: {
'https://api.mcmakler.de/v1/advertisements': {
target: 'https://api.mcmakler.de/v1/advertisements',
secure: false
}
}
},
resolve: {
extensions: [ '.js', '.jsx' ]
}
};
my dependecies are:
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.9",
"eslint": "^4.0.0",
"file-loader": "^1.1.8",
"html-webpack-plugin": "^2.28.0",
"node-sass": "^4.7.2",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.6",
"style-loader": "^0.20.2",
"url-loader": "^0.6.2",
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.5"
},
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"yarn": "^1.3.2"
}
and this is my jsx file which is a simple component to render an advertisement
import React from 'react';
import House from './index.jsx';
const publicApi = "https://api.mcmakler.de/v1/advertisements";
export default class Dinamic extends React.Component {
constructor () {
super();
this.state = {
advertisements: [],
};
}
componentDidMount() {
fetch(publicApi)
.then((results) => {
console.info('results: ', results);
return results.blob();
})
.then ((data) => {
console.info('data: ', data);
const advertisements = data.results.map((ad) => {
return (
<div key="ads.results" >
<p>{ad.title}</p>
</div>
)
});
this.setState({ advertisements });
})
.catch((err) => {
console.error("boom!: ", err);
})
}
render() {
return (
<div className="container-fluid">
<div className="container">
<h1>Dinamic</h1>
<div className="row">
{this.state.advertisements}
</div>
</div>
</div>
);
}
}
Did i miss something important or this is completely wrong?
Disclaimer: The job is for Web UI developer, but i think this is also fun to learn
The browsers don't allow reading forbidden headers like 'set-cookie' from response and browser also does not allow setting 'Cookie' header. So I resolved this issue by reading cookie in onProxyRes method and saving it in a variable and setting the saved cookie on following request in onProxyReq method.
let cookie;
devConfig.devServer = {
proxy: {
'*': {
target: https://target.com,
secure: false,
changeOrigin: true,
onProxyReq: (proxyReq) => {
proxyReq.setHeader('Cookie', cookie);
},
onProxyRes: (proxyRes) => {
Object.keys(proxyRes.headers).forEach((key) => {
if (key === 'set-cookie' && proxyRes.headers[key]) {
const cookieTokens = split(proxyRes.headers[key], ',');
cookie = cookieTokens.filter(element => element.includes('JSESSIONID')).join('');
}
});
},
},
},
}

transpiled code (babel) seems not working in Browser

Hi I'm working on an existing app which needs enhancements. The app is built using angularJS, Babel, webpack. I struggled running the app locally and finally succeeded in running it after making changes to how we call a basedirective (like below) which was using babel next generation javascript notation to regular notation (a compiler is present on babel site to do this).
function filtersDirective() {
return {
...baseDirective(template, FiltersCtrl),
...{
bindToController: {
customers: '=',
regions: '=',
managers: '=',
projects: '=',
statuses: '=',
},
},
}
}
Now the issue is I'm able to run this app locally and also able to build the bundle files (app.bundle.js, vendor.bundle.js, manifest.bundle.js) but when I deploy these files to my test server, the console error is like below.
ReferenceError: production is not defined
at dispatchXhrRequest (vendor.bundle.js:24340)
at new Promise (<anonymous>)
at xhrAdapter (vendor.bundle.js:24325)
at dispatchRequest (vendor.bundle.js:92054)
at <anonymous>
vendor.bundle.js:65932
TypeError: Cannot read property 'map' of undefined
at https://#domain/cdn/3.2.1/vendor.bundle.js:5202:31
at https://#domain/cdn/3.2.1/vendor.bundle.js:5090:28
at f1 (https://#domain/cdn/3.2.1/vendor.bundle.js:5070:27)
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4920:35
at https://#domain/cdn/3.2.1/vendor.bundle.js:4672:27
at getAttributeFromProjects (https://#domain/cdn/3.2.1/app.bundle.js:117:10)
at MainController (https://#domain/cdn/3.2.1/app.bundle.js:127:21)
at invoke (https://#domain/cdn/3.2.1/vendor.bundle.js:58052:17) <div ui-view="" class="ng-scope">
My Traspiled app.bundle.js looks like below
webpackJsonp([1], {
/***/
101:
/***/
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_deepmerge__ = __webpack_require__(69);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_deepmerge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_deepmerge__);
const baseConfig = {
title: 'Test Dashboard',
dashboard: {
title: 'Test Report',
subtitle: 'Weekly Highlights'
},
header: {
title: 'Company Confidential',
nav: 'Test'
}
}
let config = baseConfig
if (window.AppConfig) {
if (window.AppConfig.config) {
config = __WEBPACK_IMPORTED_MODULE_0_deepmerge___default.a(baseConfig, window.AppConfig.config)
}
}
const {
title,
dashboard,
header,
statusBar
} = config
/* harmony export (immutable) */
__webpack_exports__["c"] = title;
/* harmony export (immutable) */
__webpack_exports__["a"] = dashboard;
/* unused harmony export header */
/* unused harmony export statusBar */
/* harmony default export */
__webpack_exports__["b"] = (config);
/***/
}),
/***/
222:
/***/
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */
__webpack_require__.d(__webpack_exports__, "b", function() {
return resolve;
});
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_ramda__ = __webpack_require__(36);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_0_ramda___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_ramda__);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_1_angular__ = __webpack_require__(7);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_1_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_angular__);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_2__utils__ = __webpack_require__(4);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_3__services_api__ = __webpack_require__(99);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_4__appConfig_config__ = __webpack_require__(101);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_5__dashboard_html__ = __webpack_require__(479);
/* harmony import */
var __WEBPACK_IMPORTED_MODULE_5__dashboard_html___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5__dashboard_html__);
/* harmony reexport (default from non-hamory) */
__webpack_require__.d(__webpack_exports__, "c", function() {
return __WEBPACK_IMPORTED_MODULE_5__dashboard_html___default.a;
});
Which is very different from previous version of app.bundle.js which is on prod server which looks like below
webpackJsonp([1], {
/***/
10:
/***/
(function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getWebpartData = undefined;
var _keys = __webpack_require__(124);
var _keys2 = _interopRequireDefault(_keys);
var _deepmerge = __webpack_require__(76);
var _deepmerge2 = _interopRequireDefault(_deepmerge);
var _utils = __webpack_require__(4);
var _majorMilestones = __webpack_require__(501);
var _majorMilestones2 = _interopRequireDefault(_majorMilestones);
var _budget = __webpack_require__(502);
var _budget2 = _interopRequireDefault(_budget);
var _projectRisksAndIssues = __webpack_require__(503);
var _projectRisksAndIssues2 = _interopRequireDefault(_projectRisksAndIssues);
var _actionItems = __webpack_require__(504);
var _actionItems2 = _interopRequireDefault(_actionItems);
var _keyDates = __webpack_require__(505);
var _keyDates2 = _interopRequireDefault(_keyDates);
var _gantt = __webpack_require__(506);
var _gantt2 = _interopRequireDefault(_gantt);
var _statusBar = __webpack_require__(507);
var _statusBar2 = _interopRequireDefault(_statusBar);
var _angular = __webpack_require__(6);
var _angular2 = _interopRequireDefault(_angular);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
below is my package.json file for reference
{
"name": "pmrdashboard",
"version": "3.2.1",
"dependencies": {
"#cgross/angular-notify": "2.5.1",
"angular": "1.4.2",
"angular-bootstrap": "~0.12.2",
"angular-chart.js": "^1.0.1",
"angular-gantt": "^1.2.13",
"angular-google-chart": "^0.1.0",
"angular-messages": "~1.4.2",
"angular-moment": "1.0.1",
"angular-pubsub": "^0.2.0",
"angular-resource": "~1.4.2",
"angular-sanitize": "~1.4.2",
"angular-strap": "^2.3.9",
"angular-toastr": "~1.5.0",
"angular-ui-router": "~0.2.15",
"animate.css": "~3.4.0",
"axios": "^0.16.2",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-polyfill": "^6.23.0",
"babel-runtime": "^6.23.0",
"bootstrap-sass": "3.3.7",
"chart.js": "2.1.0",
"deepmerge": "^1.3.2",
"echo-loader": "0.0.1",
"jquery": "~2.1.4",
"lodash": "^4.13.1",
"moment": "2.10.6",
"ngsticky-puemos": "^0.0.4",
"node-sass": "4.5.3",
"ramda": "^0.22.1"
},
"scripts": {
"dev": "babel-node scripts/cli.js dev",
"serve": "babel-node scripts/cli.js serve",
"build": "babel-node scripts/cli.js build --upload=false --plugins dynamic-import-node",
"deploy": "babel-node scripts/cli.js build",
"serve:prod": "babel-node scripts/cli.js serve:prod",
"serve:optimize": "babel-node scripts/cli.js serve:prod --optimize=true",
"serve:cdn": "babel-node scripts/cli.js serve:prod --usecdn=true"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-plugin-angularjs-annotate": "^0.7.0",
"babel-plugin-dynamic-import-node": "^1.0.2",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.5.1",
"chalk": "^1.1.3",
"clean-webpack-plugin": "0.1.16",
"cross-env": "^5.1.3",
"css-loader": "0.28.1",
"eslint": "2.13.1",
"eslint-config-angular": "^0.5.0",
"eslint-plugin-angular": "^2.4.0",
"execa": "^0.6.3",
"exports-loader": "0.6.4",
"express": "^4.15.3",
"extract-text-webpack-plugin": "2.1.0",
"file-loader": "0.11.1",
"fs-extra": "^3.0.1",
"html-loader": "0.4.5",
"html-webpack-harddisk-plugin": "0.1.0",
"html-webpack-plugin": "2.28.0",
"http-proxy-middleware": "*",
"http-server": "^0.10.0",
"image-webpack-loader": "3.3.1",
"imports-loader": "0.7.1",
"jshint-loader": "^0.8.4",
"raw-loader": "0.5.1",
"resolve-url-loader": "2.0.2",
"rollup": "^0.43.0",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-node-resolve": "^3.0.0",
"sass-loader": "6.0.5",
"shelljs": "^0.7.7",
"ssh-webpack-plugin": "^0.1.7",
"style-loader": "0.17.0",
"svg-loader": "0.0.2",
"url-loader": "0.5.8",
"webpack": "3.0.0",
"webpack-dev-server": "^2.5.0",
"yargs": "^8.0.1"
},
"engines": {
"node": ">=0.10.0"
}
}
webpack config files: it's a folder with .babelrc, dev.js, server.js, prod.js, share.js and below is share.js file
const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {
rm
} = require('shelljs')
const pkg = require('../package.json')
const webpack = require('webpack')
const baseChunks = ['config', 'app']
const basePlugins = (chunks, enableHtml) => {
const html = enableHtml ?
[
new HtmlWebpackPlugin({
title: 'PMR Client',
filename: './index.html',
template: './src/client/index.ejs',
chunksSortMode: (a, b) => chunks.indexOf(a.names[0]) - chunks.indexOf(b.names[0]),
alwaysWriteToDisk: true,
env: process.env.NODE_ENV || 'development',
}),
new HtmlWebpackHarddiskPlugin(),
] :
[]
return [
new ExtractTextPlugin('style.css'),
...html,
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
}),
new webpack.optimize.ModuleConcatenationPlugin(),
]
}
const baseEntries = {
app: './src/app/index.js',
config: `./clients/${process.env.CLIENT}/config.js`,
}
const baseOutput = () => {
const output = {
path: path.join(__dirname, `../dist/cdn/${pkg.version}`),
filename: '[name].bundle.js',
}
if (process.env.NODE_ENV === 'production' && process.env.UPLOAD === 'true') {
output['publicPath'] = `//streamlinedoffice.com/pmr/cdn/${pkg.version}/`
}
return output
}
const sourceMap = (process.env.NODE_ENV === 'production') ? '' : 'sourceMap'
const getBaseConfig = ({
plugins = [],
chunks = [],
entries = baseEntries,
enableHtml = false
} = {}) => {
rm('-rf', path.resolve(__dirname, '../dist'))
const ch = [...baseChunks, ...chunks]
return {
entry: entries,
output: baseOutput(),
target: 'web',
devtool: 'cheap-module-eval-source-map',
plugins: [...basePlugins(ch, enableHtml), ...plugins],
module: {
rules: [{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: {
minimize: true,
root: '../src/assets/images',
},
}, ],
},
{
test: [/src\/app.*\.js$/, /client.*\.js$/],
exclude: /node_modules/,
use: {
loader: 'babel-loader',
// loader:'echo-loader',
},
},
{
test: [/\.css$/, /\.scss$/],
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', `sass-loader?${sourceMap}`],
}),
},
{
test: /bootstrap-sass\/assets\/javascripts\//,
use: 'imports-loader?jQuery=jquery'
},
// Font Definitions
{
test: /\.svg$/,
loader: 'url-loader?limit=65000&mimetype=image/svg+xml&name=public/fonts/[name].[ext]',
},
{
test: /\.woff$/,
loader: 'url-loader?limit=65000&mimetype=application/font-woff&name=public/fonts/[name].[ext]',
},
{
test: /\.woff2$/,
loader: 'url-loader?limit=65000&mimetype=application/font-woff2&name=public/fonts/[name].[ext]',
},
{
test: /\.[ot]tf$/,
loader: 'url-loader?limit=65000&mimetype=application/octet-stream&name=public/fonts/[name].[ext]',
},
{
test: /\.eot$/,
loader: 'url-loader?limit=65000&mimetype=application/vnd.ms-fontobject&name=public/fonts/[name].[ext]',
},
{
test: /\.png$/,
use: {
loader: 'url-loader?limit=8192',
},
},
{
test: /\.(jpe?g|gif)$/i,
use: [
'file-loader?hash=sha512&digest=hex&publicPath=../&name=./img/[hash].[ext]',
{
loader: 'image-webpack-loader',
query: {
gifsicle: {
interlaced: false,
},
progressive: true,
optipng: {
optimizationLevel: 7,
},
bypassOnDebug: true,
},
},
],
},
],
},
}
}
module.exports = getBaseConfig
Below is the script used to build the app.bundle.js, vendor.bundle.js an d manifest.bundle.js files (this file is on scripts/cmds/prod.js)
import {
echo,
head,
execStrict,
ls,
copy,
rmdir,
mkdir
} from '../utils'
import fs from 'fs-extra'
import path from 'path'
import {
rollup
} from 'rollup'
import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
const compiler = client =>
rollup({
entry: `./clients/${client}/config.js`,
plugins: [
resolve(),
babel({
exclude: 'node_modules/**',
babelrc: false,
presets: [
['env',
{
modules: false,
targets: {
browsers: [
"last 3 versions",
"Explorer 9",
],
},
},
],
],
plugins: ['external-helpers'],
externalHelpers: true
}),
],
}).then(bundle =>
bundle.write({
format: 'cjs',
dest: path.join(__dirname, `../../.tmpClients/${client}/config.js`),
})
)
const getClients = () =>
fs
.readdirSync('./clients')
.filter(file => fs.lstatSync(path.join('./clients', file)).isDirectory())
const handleCommand = async ({
upload = true,
optimize = true
}) => {
echo(head('Building clients...'))
const clients = getClients()
mkdir('./.tmpClients')
const promises = clients.map(client => {
compiler(client)
})
await Promise.all(promises)
echo(head('Run production build'))
await execStrict(
`cross-env UPLOAD=${upload} OPTIMIZE=${optimize} NODE_ENV=production webpack --config webpack/prod.js --progress --colors --define process.env.NODE_ENV="'production'"`
)
echo(head('Copying config files to clients'))
ls('./.tmpClients').forEach(client => {
copy({
origin: `./.tmpClients/${client}/*.js`,
dest: `./dist/clients/${client}`,
})
copy({
origin: `./dist/clients/${client}/index.html`,
dest: `./dist/clients/${client}/default.aspx`,
})
copy({
origin: './src/client/favicon.ico',
dest: `./dist/clients/${client}/`,
})
})
rmdir('./.tmpClients')
}
exports.command = 'build'
exports.describe = 'Create a production build'
exports.handler = handleCommand
exports.builder = {
upload: {
describe: 'Upload the production files to the cdn',
type: 'boolean',
default: true,
},
optimize: {
describe: 'Toggle the production optimizations, useful to check the production build as development',
type: 'boolean',
default: true,
},
}
below is .babelrc in webpack folder:
{
"presets": ["env"],
"plugins": ["transform-object-rest-spread", "dynamic-import-node"]
}
below .babelrc is in global same level as webpack folder
{
"presets": [
["env", {
"targets": {
"browsers": ["last 3 versions","Explorer 9"]
}
}]
],
"plugins": ["transform-runtime", "transform-object-rest-spread",
["angularjs-annotate", {
"explicitOnly": true
}]]
}
if anyone ran into such similar issue are know how to resolve it do share your inputs. Any help is much appreciated. Thanks

Resources