I'm using webpack 2.2.1 to build a react-redux app for production, but can't seem to set process.env.NODE_ENV to production.
Here is webpack.config.js:
var webpack = require('webpack');
var path = require('path');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');
const VENDOR_LIBS = [
'axios', 'lodash', 'react', 'react-dom', 'react-redux',
'react-router', 'redux', 'redux-form', 'redux-thunk'
];
module.exports = {
entry: {
bundle: './src/index.js',
vendor: VENDOR_LIBS
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin('style.css'),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
devServer: {
historyApiFallback: true,
contentBase: './'
}
};
And here are my scripts in package.json:
"scripts": {
"clean": "rimraf dist",
"build": "NODE_ENV=production npm run clean && webpack -p",
"serve": "webpack-dev-server"
}
When I run npm run build, my bundle.js is compiled but it's not for production. In my webpack.config.js, I replaced the option for the DefinePlugin to 'process.env.NODE_ENV': '"production"' and it worked. So I'm thinking there is something wrong with my package.json file, but I can't figure out what it is.
You are running two processes with your build command npm run clean and webpack -p. When you add NODE_ENV=production in front, it only applies to the current process. In you example, NODE_ENV=production npm run clean && webpack -p, only the clean command runs with the set environment variable.
When you add export NODE_ENV=production it will set it for all processes you start from that terminal. Keep this in mind because everything else you run from that same terminal window will have NODE_ENV=production set.
$ npm run build
> NODE_ENV=production npm run clean && webpack -p
...
$ echo $NODE_ENV
production
If you don't want to have NODE_ENV=production to stick for other processes, then add NODE_ENV=production in front of both processes:
NODE_ENV=production npm run clean && NODE_ENV=production webpack -p
Related
Before the next build, I want to remove the previous build because if we do not remove the old build, some change that did not generate the output file may not be found as soon as possible. I am tried to do this work using this command in the package.json right now:
"dev": "rm -rf src/bundle && webpack --mode development --config build/webpack.dev.config.js",
but I feel this way may be a little dangerous with the rm -rf command, any better suggetion?
Check out the docs: https://webpack.js.org/guides/output-management/#cleaning-up-the-dist-folder
Add clean:true
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Output Management',
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
};
I'm a newbie in webpack and I'm using webpack 4 for my project. But I have a problem, I have some file scripts. In the first time to build with webpack dev server, it's run okay. But when server running, I continue create a new file script(example: c.js), rename or delete the exist file the server not auto build this script to main.js. How can automatic webpack rebuild my new file(c.js) to main.js without run command again?
This is my repo on github:
https://github.com/aiduc93/webpack4-scss-pug-es6
You can follow this step to reproduce my problem:
Step 1: start server with 'npm run dev' and run localhost:3000 in browser.
Step 2: when server running, we create new file(c.js), you can copy my code in hide.js or show.js and change the pluginName to 'anything'(ie: pluginName='clickable')
Step 3: go to index.pug, create new p tag with data-clickable(ie: p(data-clickable) clickable)
Step 4: refresh page in browser and click to text clickable. Js will not run because it not recompile.
This is my structure
//folder javascript in project
javascript
| hide.js
| show.js
| server.js
//folder dist after build
dist
| main.js
This is script in package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --inline --hot",
"build": "webpack --mode production"},
This is webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
module.exports = {
entry: { main: glob.sync('./src/**/*.js*')} ,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
},
devtool: 'inline-source-map',
watch: true,
module: {
rules: [
{
test: /\.pug$/,
use: ["html-loader", "pug-html-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: [ 'css-loader', 'sass-loader']
})
},
{
type: 'javascript/auto',
test: /\.json$/,
use: [
{
loader: 'file-loader',
options: {
name: "./plugin-config/[name].[ext]"
}
}
]
}
]
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
inline: true,
port: 3000,
// historyApiFallback: true,
hot: true
},
plugins: [
new ExtractTextPlugin(
{ filename: 'style.css'}
),
new CleanWebpackPlugin('dist', { watch: true,
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
}),
new WebpackMd5Hash(),
]
};
In webpack 4 only real entry-points are entry-points, this means, no vendor-scripts, plugins...in entry.
You cannot use glob here beause it creates an array of all js-files and only server.js is your real entry-point for your application!
Adding a js-file to your wp project doesn't mean it will be compiled as you don't reference it anywhere, so wp cannot know that it is needed.
WP creates a dependency graph starting from the dependencies of your entry-point(s) and creates the bundle(s).
Your server.js is your entry-point and should look like this:
import "../stylesheets/style.scss";
import $ from 'jquery';
import "./clickable" // without import no recompile!
import "./hide"
import "./show"
console.log("his");
console.log("hello, world23");
The entry-point in your webpack.config.js:
module.exports = {
entry: {
main: path.resolve(__dirname, "./src/javascripts/server.js")
},
I tried using the solution from here but the icon is still read indicating dev mode.
Here is my current file with updates from the answer below:
const path = require('path');
const SRC_DIR = path.join(__dirname, '/client-react/src');
const DIST_DIR = path.join(__dirname, '/client-react/dist');
const webpack = require('webpack')
module.exports = {
entry: `${SRC_DIR}/index.jsx`,
output: {
filename: 'bundle.js',
path: DIST_DIR
},
plugins: [
new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')} })
],
module: {
loaders: [
{
test: /\.jsx?/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
plugins: ["transform-object-rest-spread", "transform-class-properties"],
presets: ['react', 'es2015']
}
}
]
}
};
If you use Webpack 4, you don't need to change webpack.config.js. It remains the same in both development and production modes.
The only thing needed is in your package.json:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
Having this, to create a development bundle:
npm run dev
Production bundle:
npm run build
When you want to build your app in production mode, you should use webpack production shortcut. Like this:
webpack -p
This will enable webpack optimize options to minify your JS. See more detailed explanation of webpack flags on this SO answer.
Webpack plugins need to be put under the plugins key in module.exports.
https://webpack.github.io/docs/using-plugins.html#built-in-plugins
Try this:
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
]
}
Had the same error so to fix it I did this:
package.json
"scripts": {
"build": "NODE_ENV=production webpack --progress --colors",
"start": "NODE_ENV=development webpack-dev-server --progress --colors"
}
webpack.config.js
const env = process.env.NODE_ENV
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env)
})
]
}
It should work for sure.
Here I have some configuration that you can try to optimize your build.
This worked for me: run npm run build followed by npm install -g serve and serve -s build
I am starting to learn webpack. I created a simple config file:
const path = require('path');
const webpack = require('webpack');
module.exports = {
context: __dirname,
entry: './src/index.js',
output: {
filename: 'bundle.js',
publicPath: '/',
path: path.resolve(__dirname, 'dist')
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'dist'),
hot: true
},
plugins: [new webpack.HotModuleReplacementPlugin()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
]
}
};
Then I created src/index.js with a simple console.log('hello').
In package.json I put this:
"start": "webpack-dev-server --config webpack.config.local.js -p",
When I run "npm start" in the terminal I get this weird error:
ERROR in bundle.js from UglifyJs
Unexpected token: name (urlParts) [(webpack)-dev-server/client?http:/localhost:8080:24,0][bundle.js:4026,4]
The bundle.js looks very weird since I haven't write all this code. I googled but cannot find the solution, do you have any idea what I am doing wrong? Thanks!
Edit: I added this in .babelrc but still same error:
{"presets": ["react", "stage-2", "es2015"]}
Remove the -p from your npm script, this is why is minifying the code.
It seems that you are using webpack-dev-server and a config.local file so I assume this is only for local development, in this case the -p from webpack it's not needed.
Regarding the size of bundle.js I see you are excluding the node_modules folder, so it seems ok for me. Try to add a new script in your package.json like this:
"build": ""webpack --config webpack.config.local.js"
and see the file that will be created, so you can better understand what is going on.
Hope this help, cheers!
I'm trying to create a production build of my React project, but it picks the wrong configuration.
In the development version I'm using HMR (Hot Module Replacement). This is configured in .babelrc, under env > development > plugins.
When adding an extra node env > production it seems to be ignored. It's still using the development configuration with HMR, which causes an error:
Uncaught Error: locals[0] does not appear to be a module object with
Hot Module replacement API enabled. You should disable
react-transform-hmr in production by using env section in Babel
configuration. See the example in README: https://github.com/gaearon/react-transform-hmr
Of course I've checked that information, but everything seems right.
When I removed the HMR plugin from .babelrc's development config, it works, proving it is indeed using the development config instead of production.
Here's my files:
package.json
{
"name": "myproject",
"main": "index.js",
"scripts": {
"serve": "cross-env NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
"deploy": "cross-env NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
}
//dependencies omitted in this example
}
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"plugins": [
["transform-decorators-legacy"]
],
"env": {
"development": {
"plugins": [
["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}]
}]
]
},
"production": {
"plugins": []
}
}
}
As you can see in package.json > scripts > deploy, I'm even explicitly setting the BABEL_ENV to 'production'.
Why is this happening? How do I make sure the production build ignores the HMR plugins?
By the way, searching often leads to issue #5 on the React-transform-HMR Github page, which is a long thread without a clear solution.
Edit 2016.03.30: Adding the Babel part of my webpack config on request.
Edit 2016.04.06: Adding whole webpack file on request.
webpack.production.config.js
require('es6-promise').polyfill();
var path = require('path');
module.exports = {
entry: './main.jsx',
context: __dirname + path.sep + 'src',
output: {
path: path.resolve(__dirname, './bin'),
filename: 'index.js'
},
devServer: {
port: 3333
},
module: {
loaders: [
{
test: /\.js(x?)$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0'],
plugins: [['transform-decorators-legacy']]
}
},
{
test: /\.css$/,
loader: "style!css"
},
{
test: /\.scss$/,
exclude: /(node_modules|bower_components)/,
loader: 'style-loader!css-loader!sass-loader?sourceMap'
}
]
}
};
The only thing that worked for me, is that I wrote -
process.env.NODE_ENV = 'production';
at the beginning of my webpack.config.prod.js file.
It seems that no matter what Babel keeps using the development section of the env value specified in .babelrc. What solved the problem for me, was to use name other than 'development' and set that as the value of BABEL_ENV.
"env": {
"dev": {
"plugins": [
]
},
"production": {
}
}
I use separate conf for development. In plugins I have:
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BABEL_ENV': JSON.stringify('dev')
}
}),
& in shell means that it will run in the background, so maybe your variable declaration is not caught by the build stuff that happens at the same time. The good thing is that you can just prepend the command with the variable declarations.
You could simplify the commands like this:
"serve": "NODE_ENV=development webpack-dev-server --content-base bin/ --devtool eval --progress --colors --hot --inline",
"deploy": "NODE_ENV=production BABEL_ENV=production webpack -p --config webpack.production.config.js"
You can just use the babel-preset-react-hmre.
.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"plugins": [
"transform-decorators-legacy"
],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
webpack
{
test: /\.js(x?)$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react', 'stage-0'],
plugins: ['transform-decorators-legacy'],
env: {
development: {
presets: ['react-hmre']
}
}
}
}