Webpack: как объединить клиентскую и серверную часть в один окончательный пакет?

У меня уже закружилась голова от многочисленных webpack конфигураций и вариантов использования, и я зашел в тупик. Наконец я создал свое приложение: react.js + express.js.

Серверная сторона теперь просто обрабатывает отправленные данные формы и использует nodemailer для отправки электронных писем. В ближайшее время он будет вводить данные в шаблон html в зависимости от маршрута.

Так что локально все работает просто отлично, но я так и не понял, как совместить клиентскую и серверную часть для окончательного производственного пакета с webpack.

Вот часть моего файла 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",

Часть webpack:

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
            }

        ]
    }

};

И структура файла:

    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

Может ли кто-нибудь помочь с настройкой, чтобы заставить его работать?


person Kuzma    schedule 07.02.2018    source источник


Ответы (2)


Ну, я не знаю, почему никто не ответил, но ответ прост: они не могут быть связаны вместе. Серверная часть должна работать на VPS

person Kuzma    schedule 08.02.2018

Я делюсь своей структурой проекта reactjs с конфигурацией.

Установите nodemon для наблюдения за сервером всякий раз, когда нужно изменить что-либо в коде на стороне сервера, и babel для переноса вашего es6 или es7 в es5.

Пакет.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']

}

Структура проекта

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
person radhey shyam    schedule 07.02.2018
comment
Кажется, это не относится к моему вопросу: мне нужно объединить в одну связку работающее фронтенд-приложение реакции + серверную часть - express.js - person Kuzma; 08.02.2018
comment
bundle.js — это файл, в котором будет привязываться весь интерфейсный код: вывод: { путь: outputPath, publicPath: /, имя файла: 'bundle.js' }, - person radhey shyam; 08.02.2018
comment
Я не думаю, что это возможно для файлов на стороне сервера. - person radhey shyam; 08.02.2018