Webpack builds on production environment - node.js

In React JS starter kits like the one at https://github.com/wallacyyy/reactly-starter-kit, I see package.json files that have content like this:
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config ./webpack.prod.config.js --progress --colors",
...
},
"dependencies": {
"express": "^4.15.2",
"react": "^15.5.4",
"react-dom": "^15.5.4"
},
"devDependencies": {
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.2"
}
The build script uses webpack to process the production build. How is it able to run on production when webpack is only a devDependency?

Webpack doesn't run on your production environment. Your build script just sets the NODE_ENV variable to equals production and thus letting Webpack and his plugins know they should prepare the bundle for production use. What exactly happens when you run this command depends on your webpack configuration, but among most common things would be code minification. You can also specify different kind of source maps and many other things. See https://webpack.js.org/guides/production/ for more information.

You keep both prod and dev webpack config. And in prod webpack config use definePlugin to set process.env.NODE_ENV as production ( you can also use other env variables ).
Now during transpiling and minification, NODE_ENV will be used in your vendor lib or in you app js.
'use strict';
var webpack = require('webpack');
var uglifyPlugin = new webpack.optimize.UglifyJsPlugin({
minimize: true,
comments: false
});
var definePlugin = new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
});
var commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
chunks: ['vendor', 'source'],
filename: 'vendor.bundle.js'
});
module.exports = {
context: __dirname + '/jsFolder',
entry: {
source: ['./app.jsx'],
vendor: [
'react',
'react-dom',
'redux',
'axios'
]
},
output: {
filename: "[name].bundle.js"
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
loaders: [
{ test: /\.json$/, loader: 'json-loader' },
{
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['react', 'es2015', 'stage-0']
}
},
{ test: /\.css$/, loader: "css-loader" },
]
},
plugins: [commonChunkPlugin, definePlugin, uglifyPlugin],
node: {
console: true,
fs: 'empty',
net: 'empty',
tls: 'empty'
},
target: 'web'
};

Related

Webpack throws "ReferenceError: describe is not defined" when bundling mocha test

I have a node.js mocha test that when I run it through webpack I get:
"ReferenceError: describe is not defined"
How do I make webpack ignore this global method that mocha has defined when when it runs?
Here is my test case with a work-around hack
// This is a nasty hack so webpack can compile without throwing "ReferenceError: describe is not defined"
// This global is replaced via sed before mocha runs it
global.describe = function() {};
describe('My services', async function() { ... });
I'd prefer to not include my full webpack config, but can if required. Here are the important parts
cache: true,
mode: 'development',
target: 'node',
// Per https://github.com/liady/webpack-node-externals#quick-usage
externalsPresets: {node: true}, // ignore built-in modules like path, fs, etc.
externals: [nodeExternals()], // ignore all modules in node_modules folder
watchOptions: {
ignored: ['**/node_modules', '**/build'],
},
// Don't want source maps
devtool: undefined,
module: {
rules:{
test: /\.c?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'#babel/preset-env',
{
// #see https://babeljs.io/docs/en/options#targets (added in #babel/core 7.13)
targets: 'node 18.0',
// Per https://babeljs.io/docs/en/babel-preset-env#modules
// > If you are using a bundler with Babel, the default modules: "auto" is always preferred.
modules: 'auto',
useBuiltIns: 'usage',
corejs: '3.6',
},
],
],
plugins:[omitted],
},
},
},
},
Here is my sed trick that removes global describe from the bundled js:
sed 's|global.describe = function () {};||' build/serviceTests.cjs > build/serviceTestsNoGlobalDescribe.cjs && mocha build/serviceTestsNoGlobalDescribe.cjs
Environment info:
Node.js: v18
package.json:
"type": "module",
"[dev]dependencies": {
"mocha": "10.2.0",
"#babel/core": "7.20.12",
"#babel/plugin-proposal-class-properties": "7.18.6",
"#babel/plugin-proposal-decorators": "7.20.13",
"#babel/plugin-proposal-throw-expressions": "7.18.6",
"#babel/plugin-transform-runtime": "7.19.6",
"#babel/preset-env": "7.20.2",
"babel-loader": "8.0.6",
"webpack": "5.75.0",
"webpack-cli": "5.0.1",
"webpack-node-externals": "3.0.0"
},

How can I use Webpack to create bundle for a Rest API Express NodeJS Server

Hope you are all well :)
I was working on a REST API server with Nodejs and after completing an alpha version, I wanted to create a bundle for it with build tools, Although I succeeded at some point in bundling the app still could not make the Express Rest API scripts to be bundled. As I am not really experienced with the Webpack, I am pretty sure that I am doing something wrong and there has to be a way to do this. You can also see my my webpack.config.js, .babelrc and package.json below:
Webpack.config.js
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var module_dir = `${__dirname}/node_modules`;
const path = require('path');
module.exports = {
entry: {
app: [
'babel-polyfill',
'./index.js',
],
},
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js',
},
module: {
rules: [{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['env', 'stage-0']
}
}]
},
resolveLoader: {
modules: [
__dirname + '/node_modules'
]
}
}
.Babelrc
{
"presets": ["#babel/env"]
}
package.json
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "nodemon index.js",
"build": "webpack --mode production --progress"
},
"keywords": [
"log",
"npm",
"node",
"rest",
"api",
"debug",
"bug"
],
"author": "Mehdi Roshan Fekr",
"license": "ISC",
"dependencies": {
"#babel/core": "^7.3.4",
"#babel/preset-env": "^7.3.4",
"express": "^4.16.4",
"joi": "^14.3.1",
"nodemon": "^1.18.10"
},
"devDependencies": {
"#babel/core": "^7.1.6",
"#babel/preset-env": "^7.1.6",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.4",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2"
}
}
I also have read this article about using express with webpack but I couldn't implement it properly, which I think one the reason for, is it is for a ReactJS app:
How can I use webpack with express?
----Updates-----
Error
ERROR in ./index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module 'babel-preset-env' from 'C:\Projects\# App Projects\Qcentic-Log'
- Did you mean "#babel/env"?
at Function.module.exports [as sync] (C:\Projects\# App Projects\Qcentic-Log\node_modules\resolve\lib\sync.js:58:15)
at resolveStandardizedName (C:\Projects\# App Projects\Qcentic-Log\node_modules\#babel\core\lib\config\files\plugins.js:101:31)
at resolvePreset (C:\Projects\# App Projects\Qcentic-Log\node_modules\#babel\core\lib\config\files\plugins.js:58:10)
at loadPreset (C:\Projects\# App Projects\Qcentic-Log\node_modules\#babel\core\lib\config\files\plugins.js:77:20)
at createDescriptor (C:\Projects\# App Projects\Qcentic-Log\node_modules\#babel\core\lib\config\config-descriptors.js:154:9)
at items.map (C:\Projects\# App Projects\Qcentic-Log\node_modules\#babel\core\lib\config\config-descriptors.js:109:50)
index.js
const express = require('express');
const app = express();
const CustomModule = require('./CustomModule');
app.use(express.json());
//My Endpoints...
app.listen(80, () => console.log('Listening on port 80'));
Since you are passing babel config directly to the loader, you do not need the .babelrc file. Also, you are using babel v7, so below is the updated config (your config and package.json contain mixed packages of babel v6 and v7 and they don't work together):
module.exports = {
target: "node",
entry: './index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js',
},
module: {
rules: [{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
"#babel/preset-env",
{
targets: {
node: "8.10"
}
}
]
]
}
}]
},
resolveLoader: {
modules: [
__dirname + '/node_modules'
]
}
}
Note that I removed #babel/polyfill, you don't need it for the server environment (I am sure because I am also bundling my server code with webpack and never needed it).
Make sure to set the version of node to whatever your target version is.
Also note that query is a very old way of passing options to webpack loaders, so I updated it to the new syntax, using options. And it is always best to pass full name of babel plugins, e.g.: #babel/preset-env instead of just env. The old way of resolving plugin names would generate a babel-preset-env based on env, but since babel v7 they restructured the project to "scoped packages", thus the #babel/ prefix, so best to specify full name.

How to set up react and nodeJS on your local machine(npm error)?

I'm new in React and nodeJS and I have some problems with webpack and npm. I've tried to configure my localhost based on this tutorial : https://www.tutorialspoint.com/reactjs/reactjs_environment_setup.htm
When I write into the cmd: "npm start" it throws me the following message(on the picture). I've installed webpack but it says it doesn't recognise it. And what is a "weird error" by the way?
Can you give me some links, where I can properly config my machine?
My webpack.config.js file:
var config = {
entry: './main.js',
output: {
path:'./',
filename: 'index.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2016', 'react']
}
}
]
}
}
module.exports = config;
package.json file:
{
"name": "reactApp",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --hot"
},
"author": "",
"license": "BSD"
}
The error message is in Hungarian I think, but from what I see I guess the system isn't able to find webpack-dev-server.
Try to install it locally using npm install --save-dev webpack-dev-server. Make sure it is there inside node_modules/.bin/webpack-dev-server. If your console says it can't find the command, try running node_modules/.bin/webpack-dev-server
Refer to this for more info regarding webpack-dev-server installation: https://webpack.js.org/guides/development/#webpack-dev-server
==================
edit: regarding the new error, as it says in the console, you need to add the suffix -loader to babelin your webpack.config.js
var config = {
entry: './main.js',
output: {
path:'./',
filename: 'index.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2016', 'react']
}
}
]
}
}
module.exports = config;

Deploying an app developed with babel-node

I have been using webpack for the first time, starting for a tutorial, but I'm stuck trying to deploy this to digital ocean.
I have been running the server during development by typing
npm start
Which calls:
babel-node devServer.js
This works fine for me locally, but when I try to run it on digital ocean it first works for a few minutes, then dies. I read somewhere that running babel-node on a live server isn't recommended, so I guess this is something to do with that.
I can see from this line in package.json :
"build:webpack": "NODE_ENV=production node_modules/webpack/bin/webpack.js --config webpack.config.prod.js",
that I should be doing some sort of deploy step, which I do, but I can still only get it to run using npm start, which uses babel-node devServer.js
How do I actually run this after doing the build? What am I doing wrong?
From package.json:
"scripts": {
"build:webpack": "NODE_ENV=production node_modules/webpack/bin/webpack.js --config webpack.config.prod.js",
"build": "npm run clean && npm run build:webpack",
"test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js \"test/**/*#(.js|.jsx)\"",
"clean": "rimraf dist",
"start": "babel-node devServer.js",
"tunnel": "browser-sync start --proxy localhost:7770 --tunnel wesbos",
"test:watch": "npm run test -- --watch"
},
My dev config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: [
'webpack-hot-middleware/client',
'./client/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
resolve: {
root: [
path.resolve('./client')
],
alias: {
},
},
module: {
loaders: [
// js
{
test: /\.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'client')
},
// CSS
{
test: /\.styl$/,
include: path.join(__dirname, 'client'),
loader: 'style-loader!css-loader!stylus-loader'
}
]
}
};
Prod config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'source-map',
entry: [
'./client/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': "'production'"
}
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
],
resolve: {
root: [
path.resolve('./client')
],
alias: {
},
},
module: {
loaders: [
// js
{
test: /\.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'client')
},
// CSS
{
test: /\.styl$/,
include: path.join(__dirname, 'client'),
loader: 'style-loader!css-loader!stylus-loader'
}
]
}
};
You could try using babel-loader and running the build script in npm start
In your package.json:
"start": "npm run build && babel-node --presets es2015 devServer.js"
Also include the following dependencies in your package.json:
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
In your webpack.config:
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]

postinstall webpack not working on Heroku

I'm using Heroku to host my app and webpack to build it.
Basically, I'm trying to deploy my app, but it doesn't work at all.
The postinstall doesn't seem to occur since when I load the page it's missing the file bundle.js (which is built via webpack).
Here is my package.json scripts:
"main": "server.js",
"scripts": {
"dev": "webpack-dev-server --devtool eval --content-base build/ --colors --hot",
"start": "node server.js",
"postinstall": "webpack -p --config webpack.prod.config.js --progress"
}
When I push my project to heroku, there is no error displayed during the process. I can see in the console that it's running my postinstall:
remote: > pistou#1.0.0 postinstall /tmp/build_80dea0f9774d7a9a5f8f33ee9c913bca
remote: > webpack -p --config webpack.prod.config.js --progress
Here is my whole webpack.prod.config.js file:
var path = require('path');
var webpack = require('webpack');
var node_dir = path.resolve(__dirname, 'node_modules');
module.exports = {
entry: [
'unveil',
path.resolve(__dirname, 'app/main.js')
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
loaders: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'app'),
loader: 'babel'
},
{
test: /\.scss$/,
include: path.join(__dirname, 'app/styles'),
loader: 'style!css!sass'
},
{
test: /\.(png|jpg)$/,
loader: "file"
},
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" }
]
},
plugins: [
new webpack.NoErrorsPlugin(),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
}),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /(fr|en)$/),
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": JSON.stringify("production")
}
}),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compress: {
warnings: false
}
}),
],
resolve: {
alias: {
"unveil": "./app/statics/jquery.unveil.js",
}
},
};
The --progress flag leads to a high number of print statements and log messages which heroku doesn't like and makes the process crash. Try to run without the --progress flag

Resources