Nodejs webpack and express server together - node.js

I am developing a browser game using nodejs and phaser framework and I really like this sandbox for the start: https://github.com/nkholski/phaser3-es6-webpack
The thing is, I need to use socket.io, but since I am kind of new to nodejs and these stuff, I jus can't manage to create a server and run it with this webpack at the same time.
I have made a server.js and pointed package.json for it as a start action.
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io').listen(server);
server.listen(8000, function () {
console.log("listening");
});
io.on('connection', (socket) => {...});
webpack.config.js:
module.exports = {
entry: {
app: [
'babel-polyfill',
path.resolve(__dirname, 'src/main.js')
],
vendor: ['phaser']
},
devtool: 'cheap-source-map',
output: {
pathinfo: true,
path: path.resolve(__dirname, 'dist'),
publicPath: './dist/',
filename: 'bundle.js'
},
watch: true,
plugins: [
definePlugin,
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor'/* chunkName= */, filename: 'vendor.bundle.js'/* filename= */}),
new BrowserSyncPlugin({
host: process.env.IP || 'localhost',
port: process.env.PORT || 3000,
server: {
baseDir: ['./', './build']
}
})
],
module: {
rules: [
{ test: /\.js$/, use: ['babel-loader'], include: path.join(__dirname, 'src') },
{ test: /phaser-split\.js$/, use: ['expose-loader?Phaser'] }
]
},
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
},
resolve: {
alias: {
'phaser': phaser
}
}
}
So what happened was, that I just created empty listening server and on the other port there was running the webpack project.
Is there any way to make this work together?
Thanks

Related

Webpack-dev-middleware and webpack-hot-middleware configuration

I have some conceptual troubles with webpack-dev-middleware and webpack-hot-middleware
I have SSR app (react + express), webpack (with clientside and serverside configs). Webpack configs:
client.config
const config: Configuration = {
name: 'client',
target: 'web',
mode: IS_DEV ? "development" : "production",
output: {
path: path.join(DIST_DIR, 'client'),
filename: IS_DEV ? 'core/js/[name].js' : 'core/js/[contenthash].js',
publicPath: '/',
},
entry: [
path.join(SRC_DIR, 'client.tsx'),
IS_DEV && 'webpack-hot-middleware/client',
].filter(Boolean) as Entry,
module: {
rules: [
*client rules here*
],
} as ModuleOptions,
optimization: *optimization here*,
resolve: *resolve*,
plugins: [
IS_DEV && new webpack.HotModuleReplacementPlugin(),
IS_DEV && new ReactRefreshWebpackPlugin({
overlay: {
sockIntegration: 'whm',
},
}),
new MiniCssExtractPlugin({
filename: IS_DEV ? "core/css/[name].css" : "core/css/[contenthash].css",
chunkFilename: IS_DEV ? "core/css/[id].css" : "core/css/[contenthash].css",
}),
new ESLintPlugin({
extensions: ["js", "jsx", "ts", "tsx"],
}),
new LoadablePlugin(),
new CopyWebpackPlugin({
patterns: [{ from: './src/assets', to: 'assets' }]
}),
].filter(Boolean) as WebpackPluginInstance[],
devtool: IS_DEV ? "source-map" : false,
}
and
server.config
const config: Configuration = {
name: 'server',
mode: IS_DEV ? "development" : "production",
target: 'node',
output: {
path: path.join(DIST_DIR, 'server'),
filename: 'server.js',
libraryTarget: 'commonjs',
publicPath: '/',
},
entry: path.join(SRC_DIR, 'server.ts'),
module: {
rules: [
*server rules here*
],
},
optimization: common.optimization,
resolve: common.resolve,
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devtool: IS_DEV ? "source-map" : false,
externals: [
nodeExternals(),
'#loadable/component'
],
node: {
__dirname: false,
__filename: false,
},
};
Server file:
import { IS_DEV } from '../webpack/env';
import devMiddleware from 'webpack-dev-middleware';
import hotMiddleware from 'webpack-hot-middleware';
import config from '../webpack/client.config';
const app = express();
const compiler = webpack(config);
if (IS_DEV) {
const devServer = devMiddleware(compiler, {
serverSideRender: true,
publicPath: '/'
});
app.use(hotMiddleware(compiler, {
path: '/__webpack_hmr'
}));
app.use(devServer);
}
app.get('*', *server render here*);
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`Application is started on ${port}`);
});
Result of compile here (build folder):
/build
/client
/assets
/core
/css
/js
/static
/server
Production version works well, client's files served by nginx, express runs on port with nginx proxy also. I want to make dev server with hot reload, make same as it written in instruction,but i'm stuck here. I cant understand how it must work and what command in package.json must be.
For example: what webpack config i must use in devMiddleware compiler - client or server or merged?
Be glad if someone explain (best with pointing out where i went wrong). Thanks a lot.

How to use webpack to create a front end and a admin?

I am actually new on node.js. I am trying to create an app with admin and frontend using webpack and express. I have created an example app but now the problem is how I can create the app with the admin. Below I have shared my webpack config file
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
frontend: './src/index',
backend: './admin/index'
},
module: {
loaders: [
{
test: /\.js?$/, loader: 'babel', exclude: /node_modules/
},
{
test: /\.css$/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
]
}
]
},
resolve: {
extensions: ['', '.js']
},
output: {
path: path.join(__dirname, '/public'),
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: './public',
hot: true
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
Webpack production configuration file
var config = require('./webpack.config.js');
var webpack = require('webpack');
config.plugins.push(
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": JSON.stringify("production")
}
})
);
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
);
Is there any easy solution or what I can do now?

Separate client and server in Webpack

Goal. Configuring app, which has: React, Webpack and MongoDB.
So, I've already setup Webpack for React and tried import Mongoose. The problem: React client-side and Mongoose - server-side, and because of that Webpack must have configurations for both. Using this answer: https://stackoverflow.com/a/37391247/7479176 I tried to configure Webpack. After that, I tried import Mongoose in my server.jsx file, but it didn't work.
Question. How to configure Webpack, so I can work with MongoDB?
Edited. I figured out how to rid of warnings (see Warnings):
output: {
filename: 'bundle.node.js',
libraryTarget: 'commonjs',
path: path.resolve(__dirname, 'dist')
},
externals: [
/^(?!\.|\/).+/i
],
But, when I added code into server.jsx (see server.jsx), it didn't log message in console.
Webpack configurations:
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = [
{
entry: {
index: './src/app/app.jsx'
},
devtool: 'inline-source-map',
devServer: {
port: 3000,
host: 'localhost',
historyApiFallback: true,
noInfo: false,
stats: 'minimal',
hot: true, // Tell the dev-server we're using HMR
contentBase: path.resolve(__dirname, './dist'),
publicPath: '/'
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(), // Enable HMR
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body'
})
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
},
{
entry: {
index: './src/server/server.jsx'
},
target: 'node',
output: {
filename: 'bundle.node.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
}
}
]
server.jsx:
import mongoose from 'mongoose'
import '../config/database.js'
mongoose.Promise = global.Promise
mongoose.connect(config.database)
// check connection
mongoose.connection.once('open', () => console.log('Connected to MongoDB'))
// check for db errors
mongoose.connection.on('error', err => console.log(err))
Warnings:
WARNING in ./node_modules/mongoose/lib/drivers/index.js
10:13-49 Critical dependency: the request of a dependency is an expression
WARNING in ./node_modules/require_optional/index.js
82:18-42 Critical dependency: the request of a dependency is an expression
WARNING in ./node_modules/require_optional/index.js
90:20-44 Critical dependency: the request of a dependency is an expression
WARNING in ./node_modules/require_optional/index.js
97:35-67 Critical dependency: the request of a dependency is an expression
WARNING in ./node_modules/es6-promise/dist/es6-promise.js
Module not found: Error: Can't resolve 'vertx' in 'D:\Projects\JavaScriptProjects\pizzaday\node_modules\es6-promise\dist'
# ./node_modules/es6-promise/dist/es6-promise.js 131:20-30
# ./node_modules/mongodb/lib/mongo_client.js
# ./node_modules/mongodb/index.js
# ./node_modules/mongoose/lib/index.js
# ./node_modules/mongoose/index.js
# ./src/server/server.jsx
Solution. I used webpack-dev-middleware and webpack-hot-middleware with basic Express server. I tried launch MongoDB with React on webpack-dev-server and thats was main problem.
I made new server.js within separate folder following advice from Neil Lunn and setup basic Express server with middleware and split Webpack config into 3 separate files common, dev and prod.
This fragment of code in server.js helped me to run server and client together with Webpack which bonded everything together:
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}))
app.use(webpackHotMiddleware(compiler))
New Webpack config (webpack.common.js):
const webpack = require('webpack')
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
app: [
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&reload=true',
'./src/index.jsx'
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
inject: 'body'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}

WebPack and Express server not working together

I'm having a hard time finding resources that explain how to connect webpack to a express server app. I'm wanting to use webpack for babel to use es6 when writing react and use its hot-module and cheap-module-source-map. But, webpack runs it's own express server and that currently conflicts with my express app. I want my express app to dictate the port and routes but still get the benefits of using webpack.
Any ideas?
The express app looks something like this:
var express = require('express'),
Sequelize = require('sequelize'),
/*
set up sequelize ...
app.route ...
*/
app.listen(port), function () {
console.log('Express server listening on port ' + port
});
You don't need the webpack-dev-server to use Webpack for Babel to use ES2015 when writing React and use its hot-module and cheap-module-source-map.
Webpack configuration for React app in development env:
module.exports = {
entry: {
app: [
'react-hot-loader/patch',
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
'app/index.js,
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
})
.babelrc looks like this:
{
"presets": ["react", "es2015", "stage-0"],
"env": {
"development": {
"plugins": ["react-hot-loader/babel"]
}
}
}
app/index.js:
import { AppContainer} from 'react-hot-loader'
...
<AppContainer>
<App />
</AppContainer>
...
if (module.hot) {
module.hot.accept('./routes', () => {
// Hot reloading
})
}
server/index.js:
import webpack from 'webpack'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import webpackConfig from './webpack.dev.config'
const compiler = webpack(webpackConfig)
app.use(webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: webpackConfig.output.publicPath,
}))
app.use(webpackHotMiddleware(compiler, {
path: '/__webpack_hmr',
heartbeat: 10000,
}))
I am not sure if it's allowed to refer to my own repo here, but please check my Github repo here to see how I have integrated React, Express, Webpack, HMR and Babel.
What I ended up doing was I used 2 different configurations, 1 for packing the server stuff together using webpack, and 1 for packing all the browser stuff together and also run webpack dev server for hot reloading.
Server webpack config aka webpack.node.config.js now looks like this:
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
// note the path.resolve(__dirname, ...) part
// without it, eslint-import-resolver-webpack fails
// since eslint might be invoked with different cwd
fs.readdirSync(path.resolve(__dirname, 'node_modules'))
.filter(x => ['.bin'].indexOf(x) === -1)
.forEach(mod => { nodeModules[mod] = `commonjs ${mod}`; });
// es5 style alternative
// fs.readdirSync(path.resolve(__dirname, 'node_modules'))
// .filter(function(x) {
// return ['.bin'].indexOf(x) === -1;
// })
// .forEach(function(mod) {
// nodeModules[mod] = 'commonjs ' + mod;
// });
module.exports =
{
// The configuration for the server-side rendering
name: 'server',
target: 'node',
entry: './app/server/serverEntryPrototype.js',
output: {
path: './bin/',
publicPath: 'bin/',
filename: 'serverEntryPoint.js'
},
externals: nodeModules,
module: {
loaders: [
{ test: /\.js$/,
loaders: [
// 'imports?document=this',
// 'react-hot',
'babel-loader'
//,'jsx-loader'
]
},
{ test: /\.json$/, loader: 'json-loader' },
]
},
plugins: [
// new webpack.NormalModuleReplacementPlugin("^(react-bootstrap-modal)$", "^(react)$")
// new webpack.IgnorePlugin(new RegExp("^(react-bootstrap-modal)$"))
// new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
};
Browser webpack config aka webpack.browser.config.js now looks like this:
var webpack = require('webpack');
var path = require('path');
var buildPath = path.resolve(__dirname, 'assets');
var fs = require('fs');
var commonLoaders = [
{ test: /\.js$/,
loaders: [
'react-hot',
'babel-loader'
//,'jsx-loader'
]
}
];
module.exports =
{
// Makes sure errors in console map to the correct file
// and line number
name: 'browser',
devtool: 'eval',
entry: [
//'./bin/www.js',
'./app/index.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081' // WebpackDevServer host and port
],
output: {
path: buildPath,
filename: '[name].js',
// Everything related to Webpack should go through a build path,
// localhost:3000/build. That makes proxying easier to handle
publicPath: 'http://localhost:8081/assets/'
},
extensions: [
'',
'.jsx', '.js',
'.json',
'.html',
'.css', '.styl', '.scss', '.sass'
],
module: {
loaders: [
// Compile es6 to js.
{
test: /app\/.*\.jsx?$/,
loaders: [
'react-hot',
'babel-loader'
]
},
///app\/.*\.json$/
{ test: /\.json$/, loader: 'json-loader' },
// Styles
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.s(a|c)ss$/, loader: 'style!css?localIdentName=[path][name]---[local]---[hash:base64:5]!postcss!sass' },
// Fonts
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader' }
//{ test: /\.png$/, loader: 'url-loader?limit=100000' },
//{ test: /\.jpg$/, loader: 'file-loader' }
],
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
},
postcss: [
require('autoprefixer-core')
],
devtool: 'source-map'
}
;

Webpack external not cacheable

I'm using webpack to bundle node.js web server based on Express.js framework.
Webpack build works fine, but at the end it gives me two red messages:
[1] external "express" 42 bytes {0} [not cacheable]
[2] external "path" 42 bytes {0} [not cacheable]
What does that mean and should I fix it? If yes then how to fix it?
My webpack config is here:
var server = {
devtool: 'source-map',
entry: './src/server.ts',
target: 'node',
// Config for our build files
output: {
path: root('dist/server'),
filename: '[name].bundle.js',
sourceMapFilename: '[name].map',
chunkFilename: '[id].chunk.js'
},
externals: nodeModules,
module: {
preLoaders: [
// { test: /\.ts$/, loader: 'tslint-loader', exclude: [ root('node_modules') ] },
// TODO(gdi2290): `exclude: [ root('node_modules/rxjs') ]` fixed with rxjs 5 beta.2 release
{ test: /\.js$/, loader: "source-map-loader", exclude: [ root('node_modules/rxjs') ] }
],
loaders: [
// Support for .ts files.
{ test: /\.ts$/, loader: 'ts-loader', exclude: [ /\.(spec|e2e|async)\.ts$/ ] }
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(true),
// replace
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(metadata.ENV),
'NODE_ENV': JSON.stringify(metadata.ENV)
}
})
],
};
My server.ts module:
console.log('Starting web server...');
import * as path from 'path';
import * as express from 'express';
let app = express();
let root = path.join(path.resolve(__dirname, '..'));
var port = process.env.PORT || 8080; // set our port
var router = express.Router();
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
app.use('/api', router);
app.listen(port);
console.log('Server started on port ' + port);
It's because of the externals definition. See the relevant test case.

Resources