Multiple Entry Point on Webpack by express js - reactjs

I want to use multiple entry point of webpack using express js instances in react boilerplate for two different application with sharable codebase
I have two html and two js files
vendor.html for vendor.js and
settings.html for settings.js.
One Server.js with two instances of express
`Server.js
const appVendor = express();
const appSetting = express();
setup(appVendor, {
domain: 'Vendor',
outputPath: resolve(process.cwd(), 'build_vendor'),
publicPath: '/',
});
setup(appSetting, {
domain: 'Setting',
outputPath: resolve(process.cwd(), 'build_setting'),
publicPath: '/',
});
// Start your Vendor app.
appVendor.listen('3000', host, (err) => {
if (err) {
return logger.error(err.message);
}
console.log('Server listing to port ', 3000);
});
// Start your Setting app.
appSetting.listen('5000', host, (err) => {
if (err) {
return logger.error(err.message);
}
console.log('Server listing to port ', 5000);
});
webpack.dev.babel.js
const plugins = [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
template: 'app/indexVendor.html',
chunk: ['vendor'],
}),
new HtmlWebpackPlugin({
template: 'app/indexSetting.html',
chunk: ['setting'],
}),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
failOnError: false,
}),
];
if (dllPlugin) {
glob.sync(`${dllPlugin.path}/*.dll.js`).forEach((dllPath) => {
plugins.push(new AddAssetHtmlPlugin({
filepath: dllPath,
includeSourcemap: false,
}));
});
}
module.exports = require('./webpack.base.babel')({
entry: {
vendor: [
'eventsource-polyfill',
'webpack-hot-middleware/client?reload=true',
path.join(process.cwd(), 'app/appVendor.js'),
],
setting: [
'eventsource-polyfill',
'webpack-hot-middleware/client?reload=true',
path.join(process.cwd(), 'app/appSetting.js'),
],
},
output: {
// path: path.resolve(__dirname, 'build'),
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
// Add development plugins
plugins: dependencyHandlers().concat(plugins),
// Emit a source map for easier debugging
// See https://webpack.js.org/configuration/devtool/#devtool
devtool: 'eval-source-map',
performance: {
hints: false,
},
});
How can i communication server.js(IP and port) with webpack multiple entry point

Related

I can't find the vender.js when I use webpack

I am using webpack and having a problem.I want to product a html in the public but I can't succeed.
when I use npm run dev ,I encounter a problem
this is my github
https://github.com/wohuifude123/webpack20180315
supplement
I have read you answer many times, and then I modidy webpack.dll.js
output: {
path: __dirname + 'public/dist',
filename: '[name].[chunkhash:8].js',
library: '[name]_[chunkhash:8]'
},
and then I modify the webpack.dev.js
const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
// 引入dev-server配置文件
let BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// a third party
const manifest = require('./vender-manifest.json');
const _venderName = manifest.name.split('_');
const venderName = _venderName[0] + '.' + _venderName[1];
module.exports = merge(common, {
output: { //打包路径
//filename: '[name].bundle.js', //出口文件名
// filename: '[name].[chunkhash].js',
// 可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径
path: __dirname + 'dist', //打包路径
publicPath:'dist/', // 指定publicPath
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
library: '[venderName].js'
},
devtool: 'source-map',
devServer: {
contentBase: [path.join(__dirname, "./public")], // 本地服务器 加载页面 所在的目录
host: '127.0.0.1',
compress: true,
port: 6600,
open: false // 将自动打开浏览器
},
plugins:[
new BundleAnalyzerPlugin({
analyzerMode: 'server', // static/disabled
analyzerHost: '127.0.0.1',
analyzerPort: 9900,
openAnalyzer: false
})
]
});
finally I modify the webpack.common.js
plugins: [
new CleanWebpackPlugin(['dist'], { // 清除 dist 文件中的内容
exclude: [venderName + '.js'] // 排除 提取出的 第三方的 js
}),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vender-manifest.json') // 加载 manifest.json
}),
new HtmlWebpackPlugin({
filename: './index.html',
template: './src/index.html',
//favicon: './src/favicon.ico',
alwaysWriteToDisk: true // 是否开启 new HtmlWebpackHarddiskPlugin()
}),
new HtmlWebpackIncludeAssetsPlugin({
assets: [venderName + '.js'],
append: false // 不会被 webpack 自动打包
}),
// new HtmlWebpackIncludeAssetsPlugin({
// assets: ['config/env-config.js'],
// append: false, // 不会被 webpack 自动打包
// hash: true
// }),
new HtmlWebpackHarddiskPlugin(), // 将[venderName + '.js']和['env-config.js']放进 index.html 中
new webpack.DefinePlugin({ // 创建一个编译时可以配置的全局常量
PRODUCTION: JSON.stringify(true),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
})
]
Although I have read your answer carefully, I can't understand details.
I try to modify many places ,but the product can't work .
There are 2 problems in your code:
You are not matching the dll library to your app's output library:
Your webpack.dll.js:
output: {
// some properties
library: '[name]_[chunkhash:8]'
}
//...
new webpack.DllPlugin({
name: '[name]_[chunkhash:8]'
})
Your webpack.dev.js:
const manifest = require('./vender-manifest.json');
//...
module.exports = merge(common, {
output: {
// some properties
library: manifest.name // this was missing
}
}
What I see you were doing was matching the DllPlugin name to the dll output file library, which is not the case.
The webpack dll plugin docs inform to Keep the name consistent with output.library, but applying to where you are using the dll (while using DllReferencePlugin), not where you are creating them (DllPlugin).
You are not creating the dll in the dist folder:
Your webpack dll config looks like:
output: {
path: __dirname + '/dist'
}
which writes your dll file into rootDir/dist and not rootDir/public/dist as you rather wanted.
So the fix for this one would be to just change it to path: __dirname + 'public/dist'.
After those fixes your code started to work for me. If you have any more questions feel free to ask ;)

Setting up React on the front end and Express.js as a server with Webpack 4

Right now I have everything working in regards to React and webpack:
Here is my webpack.config.js
const HtmlWebPackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: {
index: './client/index.js',
},
output: {
filename: '[name].bundle.js',
path: path.join(__dirname, 'public'),
},
devServer: {
contentBase: path.join(__dirname, 'public'),
port: 3000,
},
/* module info */
......
/* module info */
plugins: [
new HtmlWebPackPlugin({
filename: './index.html',
template: './src/index.html',
}),
],
};
When running npm run dev this kicks off the webpack-dev-server on localhost:3000 \o/
Now I would also like to use express to serve data from a route or api and have react on the front end make calls to it as well.
My Express setup:
const express = require('express');
const app = express();
const path = require('path');
app.set('port', process.env.PORT || 8016);
const issues = [
{
id: 1,
status: 'Open',
owner: 'Ravan',
created: new Date('2016-08-15'),
effort: 5,
completionDate: undefined,
},
{
id: 3,
status: 'Assigned',
owner: 'Eddie',
created: new Date('2016-08-16'),
effort: 14,
completionDate: new Date('2016-08-30'),
title: 'Missing bottom border on panel',
},
]; // global data
app.use(express.static(path.join(__dirname, '..', 'public')));
app.get('/api/issues', (req, res) => {
var metadata = { total_count: issues.length };
res.json({ _metadata: metadata, records: issues });
});
// sends index.html
app.use('*', (req, res) => {
res.sendFile(path.join(__dirname, '..', 'public/index.html'));
});
app.listen(app.get('port'), function(error) {
console.log(`App started on port ${app.get('port')}!`);
});
module.exports = app;
So you can see express is going to run on http://localhost:8016
and react on http://localhost:3000. Is there a way to have them run on the same port? If not can you explain why?
Thanks in advance!
Is not possible because you can't run two servers in the same port (if that's possible I don't have that knowledge yet :P).
What you can do to make request to your api is to setup the devServer's proxy option:
devServer: {
contentBase: resolve(__dirname, 'public'),
clientLogLevel: 'warning',
historyApiFallback: true,
host: '0.0.0.0',
hot: true,
port: 3000,
proxy: {
'/api/*': 'http://localhost:8016'
}
Now you'll be able to make to make request like this from react:
axios.get('/api/issues').then((res) => { console.log(res.data) })
You can review the doc here.

How do you configure Webpack to clear the React Warning for production minification?

I am sure everyone has seen this error but here it is again:
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 https://facebook.github.io/react/docs/optimizing-performance.html#use-the-production-build for more details.
So of course I followed the instructions in the link provided, yet though I have made all the necessary updates to my code, I am still getting this error.
According to some other answers I have seen on StackOverflow and Github, the process.env.NODE_ENV being set to production through the Webpack plugin DefinePlugin tells React to build using the minified version. So I logged process.env.NODE_ENV in my main application component and it is in fact being set to production by the plugin and still I am getting the warning.
So even though the environment variable is being set to production, I am getting the warning and my React Dev Tools says:
This page is using the development build of React. 🚧
Note that the development build is not suitable for production.
Make sure to use the production build before deployment.
I cannot seem to isolate where the problem might be here since I have done all the necessary changes to get the production build to work.
Here is my webpack.config.js file:
const webpack = require('webpack');
const resolve = require('path').resolve;
const SRC_BASE = resolve(__dirname, 'src');
const merge = require('webpack-merge');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const argv = require('yargs').argv;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const definePlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
__PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false')),
__PRODUCTION__: JSON.stringify(JSON.parse(process.env.NODE_ENV === 'production' || 'false')),
'process.env': {
NODE_ENV: process.env.NODE_ENV === 'production' ? // set NODE_ENV to production or development
JSON.stringify('production') : JSON.stringify('development'),
},
});
const loaderOptionsPlugin = new webpack.LoaderOptionsPlugin({ options: { context: __dirname } });
const commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
const cssOutput = new ExtractTextPlugin({ filename: 'style.css', allChunks: true });
const sourceMapPlugin = new webpack.SourceMapDevToolPlugin({ filename: '[name].map' });
const htmlPlugin = new HtmlWebpackPlugin({
template: `${SRC_BASE}/index.template.ejs`,
filename: '../index.html', // relative to public/build/ so this is public/index.html
inject: true,
hash: true,
});
let config = {
cache: true,
entry: {
main: ['babel-polyfill', resolve(SRC_BASE, 'index')],
},
output: {
path: resolve(__dirname, 'public/build'),
filename: '[name].bundle.js',
publicPath: '/build/',
sourceMapFilename: '[name].map',
},
resolve: {
modules: [
SRC_BASE,
'node_modules',
],
extensions: ['.js', '.jsx'],
},
module: {
rules: [
{
test: [/\.jsx$/, /\.js$/],
loader: 'babel-loader',
exclude: /(local_modules|node_modules|bower_components)/,
query: {
presets: [
'react',
'es2015',
'stage-1',
],
},
},
{
test: /\.(eot|woff|woff2|ttf|svg|png|jpe?g|gif)(\?\S*)?$/,
loader: 'file-loader',
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader!sass-loader',
}),
},
],
},
node: {
fs: 'empty',
},
plugins: [
definePlugin,
commonsPlugin,
cssOutput,
htmlPlugin,
loaderOptionsPlugin,
sourceMapPlugin,
],
};
// Only load dashboard if we're watching the code
if (argv.watch) {
const DashboardPlugin = require('webpack-dashboard/plugin');
config = merge(config, { plugins: [new DashboardPlugin()] });
}
if (process.env.NODE_ENV === 'production') {
console.log('******* I AM MERGING PRODUCTION CONFIGS ******');
console.log(`process.env.NODE_ENV = ${process.env.NODE_ENV}`);
config = merge(config, {
devtool: 'cheap-module-source-map',
plugins: [
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false,
}),
new webpack.optimize.UglifyJsPlugin(),
],
module: {
rules: [
{ test: /redux-logger/, loader: 'null-loader' },
],
},
});
}
module.exports = config;
And here is my gulpfile.js tasks that runs gulp build --production:
/* Production Builds use this task */
gulp.task('webpack', (done) => {
if (argv.production) {
process.env.BUILD_DEV = false;
process.env.NODE_ENV = 'production';
}
const buildConfig = require('./webpack.config');
const compiler = webpack(buildConfig);
const tag = '[webpack]';
const info = gutil.colors.green;
const error = gutil.colors.red;
const warning = gutil.colors.yellow;
const filterStackTraces = err =>
err.toString().split(/[\r\n]+/).filter(line => ! line.match(/^\s+at Parser/)).join(EOL);
if (argv.watch) {
compiler.watch({}, (err, stats) => {
const statDetails = stats.toJson();
if (err) {
gutil.log(error(tag), err.toString({ colors: true }));
}
else if (stats.hasErrors()) {
statDetails.errors.forEach(ex => gutil.log(error(tag), filterStackTraces(ex)));
}
else if (stats.hasWarnings()) {
statDetails.warnings.forEach(wx => gutil.log(warning(tag), filterStackTraces(wx)));
}
else {
statDetails.chunks.forEach(chunk => {
if (chunk.entry) gutil.log(info(tag), `Built ${chunk.files[0]} (${chunk.size} bytes)`);
});
gutil.log(info(tag), 'Build complete');
}
});
}
else {
compiler.run((err, stats) => {
if (err) {
return done(new gutil.PluginError('webpack', err));
}
if (stats.hasErrors()) {
const statDetails = stats.toJson();
statDetails.errors.forEach(ex => gutil.log(error(tag), filterStackTraces(ex)));
return done(new gutil.PluginError('webpack', 'Parse/ build error(s)'));
}
gutil.log(gutil.colors.green(tag), stats.toString({ colors: true }));
done();
});
}
});
gulp.task('build', ['webpack']);
After stumbling around the interweb for some different ways to configure webpack to overcome this problem I found a configuration option in the UglifyJsPlugin that cleared the error.
plugins: [
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/, <------This option fixed it
})
]
All though this cleared the warning in the console, I am still seeing my React Dev Tools saying that it is not using the production version.
I've had the same problem, but it doesn't seem to be a problem with webpack- it's likely something to do with Gulp. Have you tried running webpack with the config directly from the command line (i.e. webpack --config webpack-build.config.js or whatever) ? That produced a build without the warning quite happily. Here's my webpack config, cobbled together from various sources:
const path = require('path')
const webpack = require('webpack')
module.exports = {
devtool: 'cheap-module-source-map',
entry: './src/scripts/app',
output: {
path: path.join(__dirname, 'dist/scripts'),
filename: 'bundle.js',
publicPath: '/static/'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['env', 'react']
}
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
screw_ie8: true
},
comments: false
})
]
}
If I track down what's going on with gulp + webpack I'll write an update.

Why can I only hit my react/webpack app at root (/)?

I spent today setting up react-transform with the hot-loader. I have an app with 2 routes, / and /reports. I can hit the / and then click on a Link to take me to /reports and it works fine, but it I try to go to /reports straight away, then I get a 404. Here is my webpack.config.js
module.exports = {
devtool: 'source-map',
entry: {
app: [
'./App.js',
'webpack-hot-middleware/client'
],
vendors: vendors
},
output: {
filename: './bundle.[hash].js',
chunkFilename: './[id].[hash].js',
path: __dirname + '/dist'
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}, {
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.ejs'
}),
new CommonsPlugin({
name: 'vendors',
filename: 'vendors.js',
minChunks: Infinity
}),
new CleanWebpackPlugin(['dist'], {
root: __dirname,
verbose: true,
dry: false
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
And here is my server.js
var app = express();
var compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler));
app.use(webpackHotMiddleware(compiler));
app.use(express.static('/'));
app.listen(3000);
I have tried adding a route with
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
But /dist/index.html is not there because of the hot-loader has it in memory. The exact error is
Error: ENOENT: no such file or directory, stat '/Users/jason/Developer/stack/webapp/dist/index.html'
at Error (native)
What do I need to change in my configuration?
My express server was set up wrong. I added this route to express:
app.get('*', function(req, res) {
var memoryFs = compiler.outputFileSystem;
var index = path.join(webpackConfig.output.path, 'index.html');
var html = memoryFs.readFileSync(index);
res.end(html)
});
And now I am working perfectly.

Why does my browser refresh instead of just reload the component with HMR?

I am trying to set up Hot Module Replacement (HMR), but my browser refreshes instead of just hot swapping. Here is my webpack.config.js:
module.exports = {
devtool: 'eval-source-map',
entry: {
app: [
path.join(__dirname, './App.js'),
'webpack-hot-middleware/client?reload=true'
],
vendors: ['react', 'react-router']
},
output: {
filename: './bundle.[hash].js',
chunkFilename: './[id].[hash].js',
path: path.join(__dirname,'/dist'),
publicPath: '/'
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}, {
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.ejs'
}),
new CommonsPlugin({
name: 'vendors',
filename: 'vendors.js',
minChunks: Infinity
}),
new CleanWebpackPlugin(['dist'], {
root: __dirname,
verbose: true,
dry: false
}),
new webpack.HotModuleReplacementPlugin()
]
};
I am serving it up with express
var app = express();
var compiler = webpack(config);
var middleware = webpackMiddleware(compiler, {
publicPath: config.output.publicPath,
contentBase: 'src',
stats: {
colors: true,
hash: false,
timings: true,
chunks: false,
chunkModules: false,
modules: false
}
});
app.use(middleware);
app.use(webpackHotMiddleware(compiler));
app.use(express.static('./dist'));
app.get('*', function(req, res) {
res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'dist/index.html')));
res.end();
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
Here is my App.js
const rootRoute = {
component: 'div',
childRoutes: [ {
path: '/',
component: Main,
childRoutes: [
require('./routes/reports')
]
} ]
};
render(
<Router history={browserHistory} routes={rootRoute} />, document.getElementById('app')
);
Which require in my reports
module.exports = {
path: 'reports',
getComponents(location, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Reports'))
})
}
}
And that particular component:
class Reports extends React.Component {
render() {
let style = {
background: 'green'
};
return (
<div style={style}>
<h2>Reports</h2>
</div>
)
}
}
module.exports = Reports;
When I change the style color in my component, the style is updated, but it refreshes the whole page.
What is wrong with my config?

Resources