Webpack: difference about entry between production and development environment - reactjs

I'm reading tutorial about Webpack on this: Github Webpack tutorial In this, there is a section about config webpack for production and development.
Here is development configuration:
// webpack.config.dev.js
module.exports = {
devtool: 'cheap-eval-source-map',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
],
Here is production configuration:
// webpack.config.prod.js
module.exports = {
devtool: 'source-map',
entry: ['./src/index'],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
I understand the difference in option of devtool. The thing I don't understand about entry. Why in production, entry is only about src/index but in development configuration, entry also includes webpack-dev-server
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'

The lines 'webpack-dev-server/client?http://localhost:8080' and 'webpack/hot/dev-server' are configuring/defining which port to attach an active websocket to, in this case localhost:8080, and the content base which in this case is folder/path /client. In a production environment you would never run webpack-dev-server as your bundled client assets (bundle.js or similar) would be served by a server (IIS, Node, etc), that is why there are no webpack related items in entry of the production configuration.
The Webpack plugin in question webpack-dev-server is not required to run Webpack and compile your JS sources, it simply is a tool that can be used during the development process to watch for changes and reload changes.
Technically the entry array property in development could simply be the './src/index', but then it wouldn't enable the webpack-dev-server and/or it's hot module reloading. If you wanted to run webpack-dev-server without these configuration items then you'd then need to add command line arguments when starting webpack to specify the port and/or content base.
Hopefully that helps!

Here is the 2 things you should know before understanding:
As your linked in Webpack the confusing part, there are 3 types of entry: String Array and Object. As above code, that is array type. Meaning of entry array is: Webpack will merged all those javascript files in array together. This is often unnecessary because Webpack is intelligent enough to know which javascript files need to merge while processing. You often need to do this to enhance some features from different javascript files that you don't include somewhere else in your code.
This is "little tricky" part. You see webpack/hot/dev-serverand webpack-dev-server/client?http://localhost:8080 look like a web url rather than some javascript files, right? If you check your project directory, you see there are those files: your_app_directory/node_modules/webpack/hot/dev-server.js and your_app_directory/node_modules/webpack-dev-server/client.js. And that is the real meaning: you are importing two javascript files from two modules webpack-dev-server and webpack.
Back again to your webpack configuration:
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
],
That means we will merge three different javascript files together as point 2 I have figured out. As I explain in point 1, you will do this for enhancing some features. You include file webpack-dev-server/client.js for making a server for serving your code. You include file webpack/hot/dev-server.js for allowing your code autoloading. This is super useful when you in development mode without start/stop server each time you modify your code.

Related

Plugin system for apps compiled using Webpack

For the context: I'm developing my own product using Symfony on the back-end and react/react-router on the front-end, which is tied together by Webpack. I'm planning to divide my app into "extensions", so I would have "core" bundle and multiple different extending bundles around it (which would be sets of additional features for my product).
Now, I would like for my front-end to be as extensible as my back-end. I would like to be able to add new React components with my extending bundles to the existing "core" set of components in my "CoreBundle".
However, it seems like the Webpack is encapsulating everything too tightly to be able to produce that kind of a plugin system. Is it possible to have multiple bundles that would have separate Webpack configurations, but their JavaScript would be interconnected in a way that would allow for developing of a plugin system? The goal is being able to develop JS of one Bundle independently but at the same time being able to use some already compiled JS resources from another Bundle in the process.
I think you should be able to achieve this using the DllPlugin and the DllReferencePlugin
The DllPlugin is used in a separate webpack config to create a dll
only bundle. It also creates a manifest.json file which is used by the
DllReferencePlugin to map dependencies.
Refer to the detailed documentation at
https://webpack.js.org/plugins/dll-plugin/
In my case, I use this to combine all vendor libraries (React, Flux, etc) in one build and then use that as a reference in my Other Webpack Config which bundles all my React components etc. but references React and other libraries using the DllReferencePlugin.
My webpack.dll.js config file:
var path = require("path");
var webpack = require("webpack");
module.exports = {
entry: {
libs: [path.join(__dirname, "common", "lib.js")]
},
output: {
path: path.join(__dirname, "dist", "dll"),
filename: "[name].dll.js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "dll", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "common")
}),
]
};
And then in my main webpack.config.js, I use the reference plugin.
new webpack.DllReferencePlugin({
context: path.resolve(__dirname, "common"),
manifest:require('./dll/libs-manifest.json')
})
Depending upon how you want to split your code, you can create multiple Dlls, each with a separate webpack config as per your requirements. And then refer the dll's as per your requirements in different other webpack bundles.

How to point assets and html angular templates folder after building angularjs with webpack?

i am new to webpack, i have configured webpack to a working condition where my index.html file and budle.js file comes to /dist folder. iam aware that i can build css files too but for now i want to build js and run the app. please check the attached images for better understanding of the directory structure and the webpack build configuration.
My doubt is that if i run app from dist folder i would lose all the path of angular templates and image paths etc. how can i overcome this situation? any help is appreciated.
First of all, you need to know that the goal is to have a fully runnable stand alone application inside ./dist/ after build. All sourcefiles which are needed to run your application should be placed there. In that way you will be able to distribute your application by copy/upload/or-what-ever based on your ./dist/ directory. All other directories in your project are just for development. Those will be not a part of your distribution package.
Wrong approach: Trying to change the include path's in your application.
You need to copy or concat your sourcefiles (static files) into your distribution folder. I realy don't know why your views/templates are not stored in ./app/assets/ and not in ./app/views/ because ./app/views/ should be the correct path to store your views. Well, you need to copy your static sourcefiles. For example: You could use copy-webpack-plugin.
Your webpack config could look like this in the end:
var CopyWebpackPlugin = require('copy-webpack-plugin');
var path = require('path');
module.exports = {
context: path.join(__dirname, 'app'),
devServer: {
// This is required for older versions of webpack-dev-server
// if you use absolute 'to' paths. The path should be an
// absolute path to your build destination.
outputPath: path.join(__dirname, 'dist')
},
plugins: [
new CopyWebpackPlugin([
{
from: 'assets/**/*',
to: 'assets/'
},
{
from: 'views/**/*',
to: 'views/'
},
], {
ignore: [
],
// By default, we only copy modified files during
// a watch or webpack-dev-server build. Setting this
// to `true` copies all files.
copyUnmodified: true
})
]
};

Debugging ES6 mdules in browser

I have a large angular 1.6 application. Most of it is written in ES5 syntax and some small parts are sort of ES6. I'm saying sort of ES6 because we don't actually use modules/import/export. The reason for that is although we do use gulp to bundle all source code when deploying, we don't want to do that on dev, because it involves running gulp every small code change, and running it takes time, plus the fact that its much nicer to debug the original file per class structure rather then the bundled code (even when not uglified).
Is there a way, to debug angular 1.6 in ES6 syntax without bundling? Can Babel somehow help me keep the original files structure, for development purposes only?
Babel is basically a transpiler, so its job is only to make sure to output es5 code. It will NOT help u organize folder structure.
Bundling it with webpack helps u maintain a sane folder structure. u can have a configuration object which specifies your entry-point,(called "entry"), output-file, loaders, inline : true, so it automagically refreshes the browser for you for any small change. webpack also comes with a dev-server.
Below is what i use in my webpack.config.js.
It helps me maintain a local sandbox for my es6 escapades.
module.exports = {
entry : ['./app/index.js'], //entrypoint
output: {
path: 'D:\\js\\es6\\build',
filename: 'bundle.js'
},
module: {
loaders: [ //specify objects for each loader
{
loader: 'babel-loader' ,
test: /\.js$/,
exclude: /node_modules/, //we dont want to transpile the .js on node_modules
}
]
},
devServer: {
port: 3000,
contentBase: './build',
inline: true, //allows us to run automatic live code update
}
}

How to temporarily turn on/off React development mode when using webpack?

I'm using webpack as my bundler and I'd like to test the real performance sometimes without having to actually bundle the whole application. Is there a way how to temporarily turn off React development mode? As far as I know, the production version of React is actually a different file with all the extra debug info stripped but I don't know how to enforce which version should be loaded.
Tell Webpack to use Node's production environment. One way of doing this is to use DefinePlugin in your Webpack config to set the process.env to production:
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify("production")
}
})
]
Also make sure to use a production-ready devtool option, e.g. devtool: 'cheap-module-source-map' and not devtool: 'eval' (also in your Webpack config).
The production version of React is just the .min.js version. From the download page:
We provide two versions of React: an uncompressed version for development and a minified version for production. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages.
So if you include this in your asset pipeline, instead of the uncompressed version, you will be able to test your app in 'production' mode.
Assuming you install React 15.0.1 with npm, import react from 'react' or react = require('react') will run ./mode_modules/react/lib/React.js which is React's raw source.
The React docs suggest you use ./mode_modules/react/dist/react.js for development and react.min.js for production.
Should you minify /lib/React.js or /dist/react.js for production, React will display a warning message that you've minified non-production code:
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 fb.me/react-minification for more details.
react-dom, redux, react-redux behave similarly. Redux displays a warning message. I believe react-dom does too.
So you are clearly encouraged to use the production version from /dist.
However if you minify the /dist versions, webpack's UglifyJsPlugin will complain.
WARNING in ../~/react/dist/react.js
Critical dependencies:
4:478-485 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ../~/react/dist/react.js 4:478-4851
You cannot avoid this message because UglifyJsPlugin can only exclude webpack chunks, not individual files.
I use the both the development and production /dist versions myself.
Webpack has less work to do and finishes a bit sooner. (YRMV)
React docs say /dist/react.min.js is optimised for production. I've read no proof, just handwaving, that 'process.env': { NODE_ENV: JSON.stringify(IS_PRODUCTION ? 'production' : 'development') } plus uglify does as good a job as '/dist/react.min.js`.
I get 1 warning message from uglify rather than 3 from the react/redux ecosystem.
You can have webpack use the /dist versions with:
resolve: {
alias: {
'react$': path.join(__dirname, 'node_modules', 'react','dist',
(IS_PRODUCTION ? 'react.min.js' : 'react.js')),
'react-dom$': path.join(__dirname, 'node_modules', 'react-dom','dist',
(IS_PRODUCTION ? 'react-dom.min.js' : 'react-dom.js')),
'redux$': path.join(__dirname, 'node_modules', 'redux','dist',
(IS_PRODUCTION ? 'redux.min.js' : 'redux.js')),
'react-redux$': path.join(__dirname, 'node_modules', 'react-redux','dist',
(IS_PRODUCTION ? 'react-redux.min.js' : 'react-redux.js'))
}
}

How to turn on/off ReactJS 'development mode'?

Started using ReactJS's prop validation feature, which as the docs say only works in 'development mode' for performance reasons.
React seems to be validating the properties of a particular component I've annotated, but I don't remember explicitly turning on 'development mode'.
I tried searching for how to trigger/toggle development mode, but haven't had any luck.
The other answer assumes you are using external pre-built files from react, and while correct that is not how most folks are going to or should consume React as a package. Moreover, at this point most every React library and package also relies on the same convention to toggle dev time helpers off during production. Just using the minified react will leave all those potential optimizations on the table as well.
Ultimately the magic comes down to React embedding references to process.env.NODE_ENV throughout the codebase; these act like a feature toggle.
if (process.env.NODE_ENV !== "production")
// do propType checks
The above is the most common pattern, and other libraries follow it as well. So to "disable" these checks we need to toggle NODE_ENV to "production"
The proper way to disable "dev mode" is through your bundler of choice.
webpack
Use the DefinePlugin in your webpack config like so:
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
})
Browserify
Use the Envify transform and run your browserify build step with NODE_ENV=production ("set NODE_ENV=production" on Windows)
Result
This will produce output bundles that has all instances of process.env.NODE_ENV replaced with the string literal: "production"
Bonus
When minifying the transformed code you can take advantage of "Dead Code Elimination". DCE is when the minifier is smart enough to realize that: "production" !== "production" is always false and so will just remove any code in the if block saving you bytes.
Yeah, it's not really well documented, but on the ReactJS download page it talks about development and production modes:
We provide two versions of React: an uncompressed version for development and a minified version for production. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages.
Basically, the unminified version of React is "development" mode, and the minified version of React is "production" mode.
To be in "production" mode, just include the minified version react-0.9.0.min.js
I posted this elsewhere but, frankly, here would be a better place.
Assuming you install React 15.0.1 with npm, import react from 'react' or react = require('react') will run ./mode_modules/react/lib/React.js which is React's raw source.
The React docs suggest you use ./mode_modules/react/dist/react.js for development and react.min.js for production.
Should you minify /lib/React.js or /dist/react.js for production, React will display a warning message that you've minified non-production code:
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 fb.me/react-minification for more details.
react-dom, redux, react-redux behave similarly. Redux displays a warning message. I believe react-dom does too.
So you are clearly encouraged to use the production version from /dist.
However if you minify the /dist versions, webpack's UglifyJsPlugin will complain.
WARNING in ../~/react/dist/react.js
Critical dependencies:
4:478-485 This seems to be a pre-built javascript file. Though this is possible, it's not recommended. Try to require the original source to get better results.
# ../~/react/dist/react.js 4:478-4851
You cannot avoid this message because UglifyJsPlugin can only exclude webpack chunks, not individual files.
I use the both the development and production /dist versions myself.
Webpack has less work to do and finishes a bit sooner. (YRMV)
React docs say /dist/react.min.js is optimised for production. I've read no proof that 'process.env': { NODE_ENV: JSON.stringify(IS_PRODUCTION ? 'production' : 'development') } plus uglify does as good a job as '/dist/react.min.js`. I've read no proof you get the same resulting code.
I get 1 warning message from uglify rather than 3 from the react/redux ecosystem.
You can have webpack use the /dist versions with:
resolve: {
alias: {
'react$': path.join(__dirname, 'node_modules', 'react','dist',
(IS_PRODUCTION ? 'react.min.js' : 'react.js')),
'react-dom$': path.join(__dirname, 'node_modules', 'react-dom','dist',
(IS_PRODUCTION ? 'react-dom.min.js' : 'react-dom.js')),
'redux$': path.join(__dirname, 'node_modules', 'redux','dist',
(IS_PRODUCTION ? 'redux.min.js' : 'redux.js')),
'react-redux$': path.join(__dirname, 'node_modules', 'react-redux','dist',
(IS_PRODUCTION ? 'react-redux.min.js' : 'react-redux.js'))
}
}
For webpack based build, I used to setup separate webpack.config.js for DEV and PROD. For Prod, resolve the alias as below
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')
}
You can find the working one from here
If you're working from something like this ReactJS.NET / Webpack tutorial, you can't use process.env to switch React development mode on/off as far as I can tell. This sample links to react.js directly (see Index.cshtml), so you just have to pick .min.js or the non-minified variant by changing the URL.
I'm not sure why that is the case, because the sample's webpack.config.js has a comment that seems to imply the externals: { react: 'React' } would do the job, but then goes ahead and includes react directly into the page.
I use a manual build process that runs through Webpack, so it was a two-step process for me:
Set the environment variable from package.json using the cross-env package:
"scripts": {
"build-dev": "cross-env NODE_ENV=development webpack --config webpack.config.js",
"build-prod": "cross-env NODE_ENV=production webpack --config webpack.config.js"
}
Change the webpack.config.js file to use the environment variable (which is passed-on to React to determine if we are in development or production mode), and disable minimizing the produced bundle if we are in development mode so we can see the actual names of our components. We need to use webpack's optimization property in our webpack.config.js file for this:
optimization: {
nodeEnv: process.env.NODE_ENV,
minimize: process.env.NODE_ENV === 'production'
}
webpack v4.41.5, React v16.9.19, cross-env v7.0.0, node v10.16.14
For only Webpack v4 users:
Specifying mode: production and mode: development in your Webpack config will define process.env.NODE_ENV using the DefinePlugin by default. No additional code necessary!
webpack.prod.js (taken from docs)
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});
And in our JS:
console.log(process.env.NODE_ENV) // --> 'development' or 'production'
Webpack Docs: https://webpack.js.org/guides/production/#specify-the-mode

Resources