webpack using with nodejs - node.js

I am new in reactjs. I am just start learning reactjs. I have problem using webpack in nodejs. I want to create node server which will run the webpack file. I have webpack file:
const {resolve} = require('path');
const webpack = require('webpack');
const validate = require('webpack-validator');
const {getIfUtils, removeEmpty} = require('webpack-config-utils');
module.exports = env => {
const {ifProd, ifNotProd} = getIfUtils(env)
return validate({
entry: './index.js',
context: __dirname,
output: {
path: resolve(__dirname, './build'),
filename: 'bundle.js',
publicPath: '/build/',
pathinfo: ifNotProd(),
},
devtool: ifProd('source-map', 'eval'),
devServer: {
port: 8080,
historyApiFallback: true
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.css$/, loader: 'style-loader!css-loader'},
{test: /(\.eot|\.woff2|\.woff|\.ttf|\.svg)/, loader: 'file-loader'},
],
},
plugins: removeEmpty([
ifProd(new webpack.optimize.DedupePlugin()),
ifProd(new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false,
quiet: true,
})),
ifProd(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
})),
ifProd(new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
screw_ie8: true, // eslint-disable-line
warnings: false,
},
})),
])
});
};
How can i use this configuration with nodejs. please help

First of all your webpack configuration will not run on webpack 2+, because webpack-validator is deprecated, so I have removed it. I would recommend you to install npm install webpack-dev-server -g globally and use it as a server in your react development. This is how you can modify your configuration to use it (webpack.config.js):
const path = require("path");
const webpack = require('webpack');
const {getIfUtils, removeEmpty} = require('webpack-config-utils');
module.exports = env => {
const {ifProd, ifNotProd} = getIfUtils(env)
return {
entry: [
"webpack-dev-server/client?http://localhost:3003",
"webpack/hot/only-dev-server",
"react-hot-loader/patch"
],
context: __dirname,
output: {
path: path.join(__dirname, './build'),
filename: 'bundle.js',
publicPath: '/build/',
pathinfo: ifNotProd(),
},
devtool: ifProd('source-map', 'eval'),
devServer: {
contentBase: path.join(__dirname, "src"),
// enable HMR
hot: true,
// embed the webpack-dev-server runtime into the bundle
inline: true,
// serve index.html in place of 404 responses to allow HTML5 history
historyApiFallback: true,
port: 3003
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.css$/, loader: 'style-loader!css-loader'},
{test: /(\.eot|\.woff2|\.woff|\.ttf|\.svg)/, loader: 'file-loader'},
],
},
plugins: removeEmpty([
//...
// same as before
//...
])
};
};
package.json :
{
...
"dependencies": {},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"react-hot-loader": "^3.1.1",
"webpack": "^3.8.1",
"webpack-config-utils": "^2.3.0",
"webpack-dev-server": "^2.9.4",
}
}
in the same folder where webpack.config.js is make one file webpack.development.js, that will just set enviorment:
var config = require('./webpack.config.js')
module.exports = config("development"); // can be "production" or "development"
Files structure:
root
build
bundle.js
src
index.html
index.js
package.json
webpack.config.js
webpack.development.js
At the end just run it:
webpack-dev-server --config webpack.development.js --progress -p --hot -w
--hot - will run server,
-w - watch files

My suggestion:
package.json scripts (install webpack (-g and –save-dev), nodemon (-g and –save-dev) and concurrently (–save-dev))
"scripts": {
"webpack-watch-client": "webpack -w",
"server": "nodemon server",
"dev": "concurrently --kill-others \"npm run webpack-watch-client\" \"npm run server\""
}
webpack.config.js example
'use strict'
const path = require('path');
const PATHS = {
app: path.join(__dirname, 'src'),
public: path.join(__dirname, 'public')
};
module.exports = {
entry: {
app: PATHS.app,
},
output: {
path: PATHS.public,
filename: 'js/bundle.js'
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['react', 'es2015']
}
}
]
},
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
},
{
test: /\.(woff|woff2|eot|ttf)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/fonts/'
}
}
]
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/img/'
}
}
]
}
]
},
plugins: [
// plugins
]
};
Node server start point is ./server.js
React client start point is ./src/index.js
Output path ./public contain index.html with lines:
<div id="root"></div>
<script type="text/javascript" src="/js/bundle.js" charset="utf-8"></script>
Output path for bundle.js is ./public/js
Output path for fonts is ./public/assets/fonts
Output path for images is ./public/assets/img
Start: npm run dev (listening port is defined in server.js)
etc.

I don't know if this would help, but i think that you want do the other way round:
Create your configuration un Webpack.config file (Webpack).
Your webpack file lauch the Node server (Express).
Your server return your font-end file (React).
You can learn some info about webpack in this post.

Try this. Save this code in webpackConfig.js
var webpack = require('webpack')
var config = require('./your_config')
var compiler = webpack(config)
compiler.run(function(err, stats){
console.log(err, stats)
})
run with "node webpackConfig.js"

Related

How to use Development Version of Reactjs with Webpack 4

This is my current webpack configuration. Its been a while since I've had to do this, and the last time I did it webpack 2 was just coming out. At that point there was a plugin that would allow me to define my output. Now that plugin is no longer valid.
What I need to do is use the development version of ReactJS but my builds keep building with the production version. So error handling is next to impossible since react removes a bulk of the errors in a production build.
const fs = require('fs');
const os = require('os');
const path = require('path');
const webpack = require('webpack');
const files = fs.readdirSync('./src/scripts/').filter(function (file) {
return path.extname(file) === '.js';
});
const entries = files.reduce(function (obj, file, index) {
const key = path.basename(file, '.js');
obj[key] = [
'./src/scripts/' + key
];
return obj;
}, {});
entries.hotreload = 'react-hot-loader/patch';
console.log(argv.mode);
module.exports = {
mode: 'development',
entry: entries,
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
path: __dirname + '/dist/scripts',
publicPath: '/',
filename: '[name].js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist/scripts',
hot: true
}
};
This is also how I start webpack webpack-dev-server --config ./webpack.config.js --mode development which doesn't seem to do me any good.
Well, I create a script to run the webpack server. This is how I start the dev server npm start.
Here is my scripts:
"scripts": {
"dev": "webpack --mode development",
"start": "webpack-dev-server",
"build": "cross-env NODE_ENV=production webpack-dev-server --client-log-level none --color --compress"
},
And here my webpack.config.js:
const modoDev = process.env.NODE_ENV != "production";
const webpack = require('webpack');
const ExtractTextPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const path = require('path');
module.exports = {
mode: modoDev ? 'development' : 'production',
entry: './src/index.jsx',
output: {
path: __dirname + '/public',
filename: './app.js',
publicPath: '/'
},
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true
}),
new OptimizeCssAssetsPlugin({})
]
},
devServer: {
host: '0.0.0.0',
port: 8080,
contentBase: './public',
historyApiFallback: {
index: "/"
},
},
resolve: {
extensions: ['*', '.js', '.jsx'],
alias: {
modules: path.resolve(__dirname + '/node_modules/')
}
},
plugins: [new ExtractTextPlugin({
filename: 'app.css'
}), new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})],
module: {
rules: [{
test: /.js[x]?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(sa|sc|c)ss$/,
use: [ExtractTextPlugin.loader, 'css-loader', 'sass-loader']
}, {
test: /\.woff|.woff2|.ttf|.eot|.svg|.png|.jpg*.*$/,
use: ['file-loader']
},
],
}
};

React + Webpack: process.env is EMPTY after run build

A common problem but as usual, every solution found on this website, not fit my case.
I've create a .env.production file with specific constant.
In my package.json I have:
"build": "NODE_ENV=production webpack --config webpack.config.js --colors",
I run the build with the classic: npm run build
This is my webpack.config
const webpack = require('webpack');
const path = require('path');
var config = {
context: __dirname + '/src',
entry: {
javascript: "./index.js",
},
output: {
// path:path.join(__dirname, './dist'),
path: path.join(__dirname,'../static/js/'),
filename: 'bundle.js',
},
devServer: {
inline: true,
port: 8080
},
resolveLoader: {
modules: [path.join(__dirname, 'node_modules')]
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react']
}
},
{
test: /\.css$/,
loader: 'style-loader'
},
{
test: /\.css$/,
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
{
test: /\.svg$/,
use: [
{
loader: "babel-loader"
},
{
loader: "react-svg-loader",
options: {
jsx: true // true outputs JSX tags
}
}
]
}
]
},
}
module.exports = config;
As you can see, Im not overriding ENV in webpack config using the webpack.DefinePlugin plugin.
So why my process.env is EMPTY?
When I start the app with npm start, the process.env is normally filled and process.env.NODE_ENV is set to development.
Thank you for any help!

Webpack prod vs dev

In my webpack configuration, I've tried to make separate configuration to my prod and dev enviroments. I'm trying to achieve to different JS files for each task. Meaning, when I build it, I need my code to go to the prod environment with a specific name "lib.js" and when I run my Dev environment, I want the compiled files to go to the "dist" folder.
This is my webpack.config.js file:
const webpack = require('webpack')
const ExtractTextPlugin = require("extract-text-webpack-plugin")
let path = require('path');
let config = {
entry: [
'./src/index.js'
],
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
'react-hot-loader',
'babel-loader'
]
},
{
test: /\.(css)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
},
{
test: /\.less$/,
use:ExtractTextPlugin.extract({
use: 'less-loader'
})
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader',
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader', 'eslint-loader']
}
],
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css'],
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}
})
],
devServer: {
contentBase: './dist',
historyApiFallback: true
},
devtool : "cheap-module-source-map",
}
if (process.env.NODE_ENV === 'production') {
config.output= {
path: path.join(__dirname, '/build/'),
filename: 'lib.js',
library: ['MyLibrary'],
libraryTarget: 'umd'
};
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({ sourceMap: true }),
new ExtractTextPlugin({
filename: 'bundle.css',
disable: false,
allChunks: true
}),
new webpack.optimize.AggressiveMergingPlugin({
minSizeReduce: 1,
moveToParents: true
})
)
} else {
config.output= {
path: path.join(__dirname, '/dist/'),
filename: 'bundle.js',
library: ['MyLibrary'],
libraryTarget: 'umd',
publicPath: '/dist/'
};
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({ sourceMap: true }),
new ExtractTextPlugin({ disable: true })
)
}
module.exports = config
and these are my scripts:
"scripts": {
"dev": "webpack-dev-server -d --env.platform=default --progress --hot",
"build": "set NODE_ENV=production && webpack -p --progress --hot"
}
What actually happens is that only when I build, the files go to the dist folder, even though I've set the NODE_ENV param to "production".
Would be glad for help.
Thanks!
It could be the trailing space that you have after NODE_ENV=production, which probably sets NODE_ENV to production with a space after which won't match in your webpack config. Try to change it in the package.json like this:
"build": "set NODE_ENV=production&& webpack -p --progress --hot"
This is mentioned in the comment by #daw on this SO answer.

How to produce react bundle.js through webpack via server.js?

Server.js
var express = require('express');
app.use(express.static('public'));
app.listen(PORT, function () {
console.log('Express server is up on port ' + PORT);
});
Webpack.config.js
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractSass = new ExtractTextPlugin({
});
// const autoprefixer = require('autoprefixer');
module.exports = {
entry: path.resolve(__dirname, 'src', 'Main.js'),
output: {
path: __dirname,
publicPath: '/',
filename: 'bundle.js'
},
module: {
loaders: [{
exclude: /node_modules/,
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-1'],
plugin
s: ["react-html-attrs"]
}
}
, {
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
loader: 'url-loader?limit=10000',
},
{
test: /masonry|imagesloaded|fizzy\-ui\-utils|desandro\-|outlayer|get\-size|doc\-ready|eventie|eventemitter/,
loader: 'imports-loader?define=>false&this=>window'
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
}]
},
plugins: [
extractSass
],
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss'],
},
devServer: {
historyApiFallback: true,
contentBase: './',
}
};
I am trying to deploy on Heroku But before that when I run on cmd through npm start it starts on localhost but say Cannot GET / and nothing else runs but when I pass on cmd webpack-dev-server --config webpack.config.js it runs on localhost 8080 and works fine! I need to add serve.js before deploying on heroku what I am missing?
Make sure you have a file named Procfile that includes web: <command to run your project>. That command might be node server.js or something else dependent on Webpack, which has a Production Guide here (possibly webpack -p).

using webpack on server side of nodejs

I've been trying to use webpack with a nodejs application, and the client side is going fine - a reasonably good documentation on their website + links from google search.
Has anyone used webpack on server side of nodejs? or please guide me to any useful links.
Thanks.
This might be useful: http://jlongster.com/Backend-Apps-with-Webpack--Part-I
Key point is to make external all third party module (in node_modules directory) in webpack config file
Final config file
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
entry: './src/main.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
},
externals: nodeModules,
plugins: [
new webpack.IgnorePlugin(/\.(css|less)$/),
new webpack.BannerPlugin('require("source-map-support").install();',
{ raw: true, entryOnly: false })
],
devtool: 'sourcemap'
}
A real example with webpack 2.x
I want to highlight the difference from client side config:
1. target: 'node'
2. externals: [nodeExternals()]
for node.js, it doesn't make much sense to bundle node_modules/
3. output.libraryTarget: 'commonjs2'
without this, you cannot require('your-library')
webpack.config.js
import nodeExternals from 'webpack-node-externals'
const config = {
target: 'node',
externals: [nodeExternals()],
entry: {
'src/index': './src/index.js',
'test/index': './test/index.js'
},
output: {
path: __dirname,
filename: '[name].bundle.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['env', {
'targets': {
'node': 'current'
}
}]
]
}
}
}]
}
}
export default [config]
Here is the webpack configuration I have used to in my Nodejs application when I wanted it to read JSX which as you know, Node cannot do.
const path = require('path');
module.exports = {
// inform webpack that I am building a bundle for nodejs rather than for the
// browser
target: 'node',
// tell webpack the root file of my server application
entry: './src/index.js',
// tells webpack where to put the output file generated
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build')
},
// tells webpack to run babel on every file it runs through
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'react',
'stage-0',
['env', { targets: { browsers: ['last 2 versions'] } }]
]
}
}
]
}
};
After you implement this though, don't forget to head over to your package.json file and include this script:
{
"name": "react-ssr",
"version": "1.0.0",
"description": "Server side rendering project",
"main": "index.js",
"scripts": {
"dev:build:server": "webpack --config webpack.server.js"
},

Resources