Kuzma
Kuzma

Reputation: 711

Webpack: how to combine client and server side into one final bundle?

I already have a vertigo from numerous webpack configurations and use cases and came into deadlock. Finally I've built my app: react.js + express.js.

The server side now just processes the submitted form data and uses the nodemailer to send the emails. In the nearest future it will inject data to html template depending on route.

So locally everything works just fine, but I haven't figured out how to combine the client and server side for the final production bundle with webpack.

Here is a part from my packages.json:

  "main": "src/index.js",
  "scripts": {
    "start": "start npm run start:client && start npm run start:server",
    "start:client": "webpack-dev-server",
    "start:server": "node server.js"
  },
  "proxy": "http://localhost:3000",

The webpack part:

module.exports = {

    devtool: 'source-map',
    devServer: {
        historyApiFallback: true,
        contentBase: './src',
        proxy : {
            '/contact': 'http://localhost:3000'
          }     
    },

    entry: {
        vendor:  ['./src/js/plugins.js', 
            './src/js/classList.min.js'].map(function(link){ 
                return path.resolve(__dirname, link); 
            }),



        base: ['./src/css/animate.css', './src/css/outdatedbrowser.css'].map(function(link){ 
                return path.resolve(__dirname, link); 
            }),
        entry: ["babel-polyfill", './src/index.js']
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].[chunkhash].js',
        publicPath: '/'
    },
    resolve: {
        extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
        modules: [
             path.join(__dirname, 'node_modules')
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('development')
        }),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: 'vendor.[chunkhash].js',
            minChunks: Infinity
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false,
                screw_ie8: true,
                conditionals: true,
                unused: true,
                comparisons: true,
                sequences: true,
                dead_code: true,
                evaluate: true,
                if_return: true,
                join_vars: true
            },
            output: {
                comments: false
            }
        }),
        new webpack.LoaderOptionsPlugin({
            options: {
                postcss: [
                    autoprefixer({
                        browsers: [
                            'last 3 version',
                            'ie >= 10'
                        ]
                    })
                ],
                context: staticSourcePath
            }
        }),
        new webpack.HashedModuleIdsPlugin(),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, './public/index.html'),
            path: buildPath,
            excludeChunks: ['base'],
            filename: 'index.html',
            minify: {
                collapseWhitespace: true,
                collapseInlineTagWhitespace: true,
                removeComments: true,
                removeRedundantAttributes: true
            }
        }),
        new PreloadWebpackPlugin({
            rel: 'preload',
            as: 'script',
            include: 'all',
            fileBlacklist: [/\.(css|map)$/, /base?.+/]
        }),
        new ExtractTextPlugin({
            filename: '[name].[contenthash].css',
            allChunks: true
        }), 
        new StyleExtHtmlWebpackPlugin({
            minify: true
        }),
        new webpack.NoEmitOnErrorsPlugin(),
        new CompressionPlugin({
            asset: '[path].gz[query]',
            algorithm: 'gzip',
            test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
            threshold: 10240,
            minRatio: 0.8
        })
    ],
    module: {

        rules: [{
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env', 'react', 'stage-1'],
                    }
                },
                include: sourcePath
            }

        ]
    }

};

And file structure:

    dist <folder>
    node_modules <folder> ----   
    public <folder> ---- 
        index.html
    src <folder> ----   
        components <folder>
        ---css < folder > 
        ---fonts < folder >
        ---icons < folder >
        ---img < folder >
        ---js < folder > - third party JS
        ---.env    
        ---i18n.js    
        ---index.js
        ---myDetector.js
        ---sitemap.xml    
    server.js   
    package.json     
    package-lock.json 
    webpack.config.js

Could anybody help with configuration in order to get it working?

Upvotes: 1

Views: 2206

Answers (2)

Kuzma
Kuzma

Reputation: 711

Well, I don't know why nobody answered, but the answer is simple: they can't be bundled together. The server side should be run on VPS

Upvotes: 2

radhey shyam
radhey shyam

Reputation: 769

I am sharing my reactjs project structure with conifguration..

Install nodemon for watching server whenever to changes anything in server side code and babel for transpiling your es6 or es7 to es5

Package.json

"scripts": {
"server": "nodemon --watch server --exec babel-node -- server/index.js",
"start": "nodemon --watch server --exec babel-node -- server/index.js",
"test": "echo \"Error: no test specified\" && exit 1"

},

webpack.config.dev.js

let outputPath = path.join(__dirname);


export default {
// devtools: 'eval-source-map',
devtool: 'source-map',
entry: [
    'webpack-hot-middleware/client',
    path.join(__dirname, 'client/index.js'),
],
output: {
    path: outputPath,
    publicPath: "/",
    filename: 'bundle.js'
},
module:{        
    loaders:[
        {
            test: /\.js$/,                
            include: path.join(__dirname, 'client'),
            exclude: /(node_modules|bower_components)/,
            loaders: ['react-hot-loader','babel-loader'],                
        }
    ]
},
node: {
    fs: 'empty'
},
plugins: [
    new webpack.ProvidePlugin({
        "React": "react",
    }),
    new webpack.NoErrorsPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
],
resolve: ['','.js']

}

Project structure

node_modules <folder> ----   
public <folder> ----   
    components <folder>
    ---css < folder > 
    ---fonts < folder >
    ---icons < folder >
    ---img < folder >
    ---js < folder > - third party JS
    ---.env    
    ---i18n.js    
    ---index.js
    ---myDetector.js
    ---sitemap.xml    
server
    ---index.html
    ---index.js
package.json     
package-lock.json 
webpack.config.dev.js

Upvotes: 0

Related Questions