I have followed as many tips as I can find in packaging my Webpack ReactJS app for production. Unfortunately, the file size is still 3MB. What am I doing wrong?
Here is my Webpack Config file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
'./index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle-webpack.js',
publicPath: './'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
screw_ie8: true,
warnings: false
}
})
],
module: {
loaders: [
{
test: /\.js$/,
loaders: [ 'babel' ],
exclude: /node_modules/,
include: __dirname
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{test: /node_modules\/react-chatview/, loader: 'babel' }
]
}
}
Any help would be greatly appreciated!
I use the following command to package it:
> NODE_ENV=production webpack -p
I get the following output:
bundle-webpack.js 3.1 MB 0 [emitted] main
Best,
Aaron
Looks like you've still got a fair amount of dev stuff there, e.g. hot module replacement.
Take a look at webpack.config.prod.js at React Transform Boilerplate as a guide.
You may also be able to optimise your imports by including only the parts of the packages you need and leaving out the rest. See: Reduce Your bundle.js File Size By Doing This One Thing .
So, it turns out that David L. Walsh was correct that I had too much development stuff in my app. However, the answer provided did not resolve the issue.
I resolved the issue using 3 steps.
Remove all the "hot-reloading" plugins from my webpack configuration, as David instructed.
Remove the hot reloading "react-transform" plugin from my .babelrc file.
Change the "devtool" parameter to "source-map" from "cheap-module-eval-source-map"
After following those steps, the final bundle file was 340kb while the source map was still 3MB. Fortunately, I don't have to include the source map in my application, so it can be downloaded at 340kb, which is still fairly large, but reasonable for modern browsers running on modern internet connections.
I would up-vote David's answer, but I don't have enough reputation points yet to do so.
Related
I'm setting up react with webpack, here is my webpack config file \n
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: path.join(__dirname, "src", "index.js"),
devtool: 'sourcemaps',
cache: true,
mode: 'development',
output: {
path:path.resolve(__dirname, "dist"),
filename: './dist/bundle.js'
},
module: {
rules: [
{
test: /\.?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "public/templates/", "budget_account2.html"),
}),
],
}
when i run npm run-script watch then it throw error: \n
Invalid configuration object. Webpack has been initialized using a
configuration object that does not match the API schema.
configuration.devtool should match pattern "^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$".
BREAKING CHANGE since webpack 5: The devtool option is more strict.
Please strictly follow the order of the keywords in the pattern.
Thanks all
It's exactly as the error says.
configuration.devtool should match pattern "^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$".
See a description of the various options here.
To follow it, your devtool value should:
Optionally start with inline-, hidden-, or eval-, depending on where you want the source map to be
Optionally followed by nosources-, if you want the source code to be excluded from the map
Optionally followed by cheap or cheap-module - cheap indicates a fast rebuild time, and module preserves the original lines
Followed by source-map at the end.
Figure out which one(s) of the above you want, construct a string that matches, and use that. For a random example, you could have inline-nosources-cheap-source-map.
(You may also use none, to omit source maps entirely)
I have a React app that uses Webpack and Babel. I am trying to load an image anyway possible (svg, png...) but I keep getting the error "Unexpected character '�' (1:0) > 1 | �PNG". I installed url-loader (npm install url-loader --save-dev) which is supposed to help load images when using Webpack. Nothing has changed.
This is my webpack.config.js:
const {NODE_ENV} = process.env;
module.exports = {
mode: NODE_ENV === 'production' ? NODE_ENV : 'development',
entry: ['./client/index.js'],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 25000
}
}
]
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js',
},
};
This is how I was trying to load my image:
import hiker from './hiker.png';
<img src={hiker} />
Any help would be greatly appreciated, thank you.
Several issues here. First, you're using babel-node that's pointing to the index.js. If you want it to point to your webpack config, then you'll need to remove index.js from the package.json's dev scripts:
"dev": "nodemon --exec babel-node",
And rename webpack.config.js to babel.config.js.
Unfortunately, there's also quite a bit more work required to get your project up-and-running. It appears that this setup uses some server-side-rendering configuration. Admittedly, I've never used koa, so I can't be of much help here.
It also appears to be a bit outdated, and someone updated it and included a walkthrough.
That said, I'd recommend steering toward a new-developer friendly boilerplate if you're just learning.
I'd suggest starting with create-react-app, which obscures a lot of this webpack configuration.
Or, you can download my react-starter-kit, which has an exposed webpack configuration that you can play around with (if desired) and utilizes webpack-dev-server for development and webpack with a very simple express configuration for production.
Up to you.
Good luck!
I have finished my ReactJS app and I want to put it in production. I run next command: webpack --progress -p but in chrome F12 I get next error: index.js:1 Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See WebSiteFbReactJs for more details..
It is my webpack.config.js:
'use strict';
const WEBPACK = require('webpack');
const PATH = require('path');
const CopyFiles = require('copy-webpack-plugin');
const BaseName = "/upct";
module.exports = {
resolve: {
extensions: ['', '.js', '.jsx']
},
context: __dirname,
entry: {
app: ['./src/index.jsx']
},
output: {
path: PATH.join(__dirname, '/public'),
/*path: './public',*/
publicPath: BaseName+'/',
filename: 'index.js'
},
devServer: {
host: 'localhost',
port: 3000,
contentBase: PATH.join(__dirname, '/public'),
inline: true,
historyApiFallback: true,
headers: { "Access-Control-Allow-Origin": "*" }
},
module: {
loaders: [
{
test: /(\.js|.jsx)$/,
loader: 'babel',
query: {
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": [
"react-html-attrs",
"transform-decorators-legacy",
"transform-class-properties"
]
}
}
]
},
plugins: [
new WEBPACK.DefinePlugin({
BASENAME: JSON.stringify(BaseName)
})
]
}
What could this error be?. It is all OK, right? How could I solve this? Thank you.
EDIT: I am getting next error too: DevTools failed to parse SourceMap: http://MYSERVER.com/upct/src/css/bootstrap.css.map
Please add NODE_ENV = 'production' environmental variable to your Webpack build in order to disable debug information and warnings, most of the property type checks and other developer-friendly tools. It will make the app faster but harder to debug. Use this only when deploying to the production.
In your case, in the plugins section just add:
new WEBPACK.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
Please see documentation about optimizing the production build with React, especially Webpack section.
As for the error with the source maps, it seems that the link is broken and returns 404 Not Found error so Chrome can't fetch the original source code mapping for Bootstrap's CSS. That's not a big issue as you probably won't be looking at it's source but that might be a signal that your Webpack build doesn't deploy source maps when building the app. Please add devtool: 'source-map' to your config file in order to produce source maps which will improve the debugging experience on production by translating bundled code to original source files.
UglifyJs will minimize the code size by renaming variables, function names and by other optimization tricks. You can add it to your plugins section of the config file the same way:
new WEBPACK.optimize.UglifyJsPlugin({
compress: {
// suppresses warnings, usually from module minification
warnings: false,
},
}),
There are many possible optimizations, for more information please see this optimization guide.
Being new to webpack, the answer might be staring me down but I don't see it. No matter how I try to pass them along, the file-loader options aren't found.
I'm using file-loader and I'm trying to pass a publicPath (or simply anything, at first) along as an option. I went into the file loader source code and added a log for all the options it detected, but they always come up empty.
webpack.config.prod.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: [
'./src/index.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'idlink-1.1.1.js',
publicPath: ''
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'})
],
module: {
loaders: [
{
exclude: /node_modules/,
loader: 'babel',
query: { presets: ['react', 'es2015', 'stage-1'] }
},
{test: /\.css$/, loader: "style-loader!css-loader" },
{test: /\.scss$/, loaders: ["style", "css", "sass"]},
{test: /\.less$/, loader: "style-loader!css-loader!less-loader" },
{
test: /\.(jpe?g|png|gif|svg|pdf)$/i,
loader: "file",
options: { publicPath: 'https://apps.ixordocs.be/'}
},
{test: /\.gif$/, loader: "url-loader?mimetype=image/png" }
]
},
}
I've also tried with
loader: "file-loader"
as well as added the options as one string like this
loader: "file?name=[name].[ext]&publicPath=https://apps.ixordocs.be/"
Some context info:
I don't want to have a hardcoded publicPath defined in my output: {}, i want to grab it dynamically from a parameter placed on the div that my plugin is loaded into.
I've tried using the __webpack_public_path__ variable and it works, but not for images. The public path is grabbed from the parameter, set, and used to fetch a chunk. Somehow it has no effect on images though. If I hardcode a publicPath under output, it DOES work for images. This leads me to believe there is a problem with the loader's communication to the variable, so the idea is to get the options working and eventually try to pass a dynamic publicPath in there.
Your question is totally valid based on the documentation of the loader on both loader's GitHub repo and webpack docs. The problem is the publicPath and outputPath features are implemented in a pull request that is merged but not yet released to a new version of loader, and the README on npm doesn't mention the features for the same reason.
You can still use these features by installing from the GitHub repo with npm install webpack/file-loader --save-dev and your options should work. If not try replacing options with query.
{
test: /\.(jpe?g|png|gif|svg|pdf)$/i,
loader: "file-loader",
query: { publicPath: 'https://apps.ixordocs.be/'}
}
Using URLs for publicPath is also valid because it happens often that you want to load your assets from a CDN or another server.
Ok I have read many posts(like this one) on here about optimizing bundle.js for a production build but they are not changing my bundle.js file at all so I must be doing something wrong. I am building with the command:
webpack -p --config webpack.production.config.js
and webpack.production.config.js looks like this:
var webpack = require('webpack');
var path = require('path');
module.exports = {
devtool: 'inline-source-map',
entry: [
'./src/index.js'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
resolve: {
modulesDirectories: ['node_modules', 'src'],
extensions: ['', '.js']
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel?presets[]=react,presets[]=es2015']
}
]
},
alias: {
'react$': path.join(__dirname, 'node_modules', 'react','dist','react.min.js'),
'react-dom$': path.join(__dirname, 'node_modules', 'react-dom','dist','react-dom.min.js')
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
],
};
I am at a loss. I have 17 node_modules including all the basics like react and webpack. My bundle.js file is 15.6MB....absolutely massive and unacceptable. From what I am reading it looks like the -p and this plug in
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
should automatically use the .min.js version of everything. Is that correct? Do I have to do anything to force my application to use that?
Any optimization would help tremendously! The application is not really that large and the initial load of the page is taking WAY to long.
Thanks!!
For a production build try changing devtool: 'inline-source-map' to devtool: 'source-map'
The webpack config from https://webpack.github.io/docs/configuration.html says:
inline-source-map - A SourceMap is added as DataUrl to the JavaScript
file.
Also, and again for production builds, you can remove 'react-hot' in the loaders section.
For example, with these differences in one of my projects the development bundle is 9MB but the production one is 600KB. Hopefully you'll see similar improvements.
I highly recommend you read this tutorial,the answer is very obvious after reading this.
Put simply ,you can use a plugin named uglify which can reduce the bundle size dramatically.
In addition, 'NODE_ENV': JSON.stringify('production') is used by React ,nothing to do with webpack