2017-02-16 9 views
3
私が代わりにWebPACKの-DEV-サーバーの特急ミドルウェア使用してい

webpack 2とwebpackDevMiddlewareで動作する反応ホットローダーを取得するには?

const config = require("../webpack.config.js"); 

if(process.env.NODE_ENV === 'development') { 
    const webpack = require('webpack'); 
    const webpackDevMiddleware = require('webpack-dev-middleware'); 
    const webpackHotMiddleware = require('webpack-hot-middleware'); 
    const compiler = webpack(config); 

    app.use(webpackDevMiddleware(compiler, { 
     stats: {colors: true}, 
    })); 
    app.use(webpackHotMiddleware(compiler)); 
} 

そして、私はreact-hot-loader/patchを試してみた、react-hot-loader/babelreact-hot-loader/webpack[email protected]から:

module.exports = { 
    context: path.join(__dirname, 'client'), 
    entry: [ 
     'webpack-hot-middleware/client', 
     'react-hot-loader/patch', 
     './entry.less', 
     './entry', 
    ], 
    output: { 
     path: path.join(__dirname, 'public'), 
     filename: 'bundle.js', 
     publicPath: '/', 
    }, 
    module: { 
     rules: [ 
      { 
       test: /\.jsx/, 
       use: [ 
        { 
         loader: 'babel-loader', 
         options: { 
          plugins: ['transform-react-jsx', 'transform-class-properties', 'react-hot-loader/babel'], 
         }, 
        }, 
        'react-hot-loader/webpack' 
       ], 
      }, 

をしかし、それらのどれもに思えるん作業。

[HMR]以下のモジュールはホット更新できませんでした:(フルリロードが必要) 変更されているモジュール(とその親)が方法がわからないので、これは通常、私はこのエラーメッセージが表示されますホットリロードする。詳細はhttp://webpack.github.io/docs/hot-module-replacement-with-webpack.htmlを参照してください。 logUpdates @ bundle.js:29964 applyCallback @ bundle.js:29932 (匿名)bundle.js @:29940 bundle.js:29972
[HMR] - ./client/components/CrawlForm.jsx

それを動作させるにはどのようなトリックですか?

N.B. CSSのホットローディングは正常に機能するので、私はその部分を動作させました。

答えて

2

最終的にケースをクラックさせるまで数日を費やしました。私はdevのミドルウェアやあなたと同じホットミドルウェアの両方を使用しています

const clientConfig = { 
    entry: { 
    client: [ 
     'react-hot-loader/patch', 
     'webpack-hot-middleware/client', 
     'babel-polyfill', 
     './src/client/client.js', 
    ], 
    }, 
    output: { 
    path: path.resolve(__dirname, './build/public'), 
    filename: '[name].js', 
    publicPath: '/', 
    }, 
    devtool: 'inline-source-map', 
    plugins: [ 
    new webpack.HotModuleReplacementPlugin(), 
    new webpack.NoEmitOnErrorsPlugin(), 
    new webpack.LoaderOptionsPlugin({ 
     debug: true, 
    }), 
    new CopyWebpackPlugin([ 
     { from: './src/assets/fonts', to: 'fonts' }, 
     { from: './src/assets/images', to: 'images' }, 
    ]), 
    new webpack.EnvironmentPlugin(['GOOGLE_MAP_API_KEY']), 
    ], 
    module: { 
    rules: [ 
     { 
     test: /(\.js|\.jsx)$/, 
     loader: 'babel-loader', 
     exclude: /node_modules/, 
     options: { 
      presets: [['es2015', { loose: true }], 'react', 'stage-2'], 
     }, 
     }, 
     { 
     test: /\.scss$/, 
     use: [ 
      'style-loader', 
      'css-loader', 
      'sass-loader', 
     ], 
     }, 
    ], 
    }, 
}; 

サーバー

index.js

WebPACKのconfigオブジェクト:ここで働く私のコードです。反応ホットローダーからAppContainerをインポートし、コンポーネントをラップしています。

import express from 'express'; 
import React from 'react'; 
import routes from 'components/Routes'; 
import html from './html'; 
import { renderToString } from 'react-dom/server'; 
import { match, RouterContext } from 'react-router'; 
import { Provider } from 'react-redux'; 
import makeStore from 'store'; 
import Immutable from 'immutable'; 
import setupNameless from './setupNameless'; 
import db from './database'; 
import { actions } from '../client/constants'; 
import webpack from 'webpack'; 
import webpackHotMiddleware from 'webpack-hot-middleware'; 
import webpackDevMiddleware from 'webpack-dev-middleware'; 
import { clientConfig as wpConfig } from '../../webpack.config.js'; 
import { AppContainer } from 'react-hot-loader'; 
import dotenv from 'dotenv'; 

dotenv.config(); 

const compiler = webpack(wpConfig); 

db(); 

const app = express(); 
app.use(webpackDevMiddleware(compiler, { 
    publicPath: wpConfig.output.publicPath, 
    // noInfo: true, 
    stats: { 
    colors: true, 
    }, 
})); 
app.use(webpackHotMiddleware(compiler)); 
app.use(express.static('build/public')); 

const { commander: nameless, apiPrefix } = setupNameless(app); 

app.use((req, res, next) => { 
    // make DB call here to fetch jobs. 
    nameless.exec('jobs', actions.GET_JOBS).then((jobs) => { 

    const store = makeStore(Immutable.fromJS({ 
     // filters: {}, 
     app: { 
     apiPrefix, 
     search: { 
      query: '', 
      options: {}, 
     }, 
     }, 
     jobs, 
    })); 

    match({ 
     routes, 
     location: req.originalUrl, 
    }, (error, redirectLocation, renderProps) => { 
     if (error) { 
     res.status(500).send(error.message); 
     } else if (redirectLocation) { 
     res.redirect(302, redirectLocation.pathname + redirectLocation.search); 
     } else if (renderProps) { 
     // You can also check renderProps.components or renderProps.routes for 
     // your "not found" component or route respectively, and send a 404 as 
     // below, if you're using a catch-all route. 
     try { 
      res.status(200).send(html(renderToString(
      <AppContainer> 
       <Provider store={store}> 
       <RouterContext {...renderProps} /> 
       </Provider> 
      </AppContainer> 
     ), store.getState())); 
     } catch (err) { 
      next(err); 
     } 
     } else { 
     res.status(404).send('Not found'); 
     } 
    }); 
    }, (e) => { 
    next(e); 
    }).catch(e => { 
    next(e); 
    }); 
}); 

app.use(logErrors); 

function logErrors(err, req, res, next) { 
    console.error(err.stack); 
    next(err); 
} 

app.listen(process.env.PORT || 3000,() => { 
    console.log(`App listening on port ${process.env.PORT || 3000}`); 
}); 

Client.js

これは、それがうまく行わ魔法でした。 if (module.hot)コードを追加し、反応ホットローダーからAppContainerをインポートしなければなりませんでした。もう一つの重要な側面は、私の<Router />コンポーネントにkey={Math.random()}を追加することでした。

import { match, Router, browserHistory as history } from 'react-router'; 
import routes from './components/Routes'; 
import ReactDOM from 'react-dom'; 
import React from 'react'; 
import { Provider } from 'react-redux'; 
import makeStore from './store'; 
import Immutable from 'immutable'; 
import createLogger from 'redux-logger'; 
import createSagaMiddleware from 'redux-saga'; 
import sagas from './sagas'; 
import { AppContainer } from 'react-hot-loader'; 

const logger = createLogger(); 
const sagaMiddleware = createSagaMiddleware(); 

const store = makeStore(
    Immutable.fromJS(window.__INITIAL_STATE__), 
    logger, 
    sagaMiddleware 
); 

sagaMiddleware.run(sagas); 

ReactDOM.render(
    <AppContainer> 
    <Provider store={store}> 
     <Router history={history} routes={routes} /> 
    </Provider> 
    </AppContainer>, 
    document.getElementById('app')); 

if (module.hot) { 
    module.hot.accept('./components/Routes',() => { 
    const nextRoutes = require('./components/Routes').default; 
    ReactDOM.render(
     <AppContainer> 
     <Provider store={store}> 
      <Router key={Math.random()} history={history} routes={nextRoutes} /> 
     </Provider> 
     </AppContainer>, 
     document.getElementById('app')); 
    }); 
} 

幸運

+0

うわー...それは以前よりももっと複雑です。 'と' if(module.hot) 'ビットが私のために働いていました。ありがとうございました!! – mpen

1

Dan Abramovから言い換えとrealseanpからいくつかのコードを借りて、完全な手順は以下のとおりです。

  1. yarn add [email protected]
  2. 更新webpack.config.js
    1. react-hot-loader/patchおよびを追加します。あなたのentry
    2. のトップへ
  3. webpack-dev-middlewareを追加するには、WebPACKのプラグインにnew HotModuleReplacementPlugin()を追加し、webpack-hot-middlwareを表現するためにあなたのbabel-loaderplugins

  4. react-hot-loader/babelを追加します。

    // server/entry.jsx 
    const express = require('express'); 
    const path = require('path'); 
    const cons = require('consolidate'); 
    const fs = require('fs'); 
    
    const port = 5469; 
    const app = express(); 
    
    app.disable('x-powered-by'); 
    app.engine('hbs', cons.handlebars); 
    app.set('view engine', 'hbs'); 
    app.set('views', path.join(__dirname, '../views')); 
    
    const wpConfig = require("../webpack.config.js"); 
    
    if(process.env.NODE_ENV === 'development') { 
        const webpack = require('webpack'); 
        const webpackDevMiddleware = require('webpack-dev-middleware'); 
        const webpackHotMiddleware = require('webpack-hot-middleware'); 
        const compiler = webpack(wpConfig); 
    
        app.use(webpackDevMiddleware(compiler, { 
         stats: {colors: true}, 
        })); 
        app.use(webpackHotMiddleware(compiler)); 
    } 
    
    app.use(require('./routes')); 
    
    app.use(express.static(wpConfig.output.path)); 
    
    app.listen(port, function() { 
        console.log(`Listening on http://localhost:${port}`); 
    }); 
    
  5. が追加<AppContainer>react.hotあなたのクライアントエントリーポイントに:

    // client/entry.jsx 
    import ReactDOM from 'react-dom'; 
    import App from './components/App'; 
    import { AppContainer } from 'react-hot-loader'; 
    
    function render(Root) { 
        ReactDOM.render(<AppContainer><Root/></AppContainer>, document.getElementById('react-root')); 
    } 
    
    render(App); 
    
    if(module.hot) { 
        module.hot.accept('./components/App',() => { 
         render(require('./components/App').default); 
        }); 
    } 
    
2

私はいくつかのトラブルランタイムエラーをレンダリングするために、エラー・オーバーレイを得るだけでなく、そこから回復していました。私は、エラーが発生したときにwebpack-dev-serverが完全なリロードを行うことに気づいた。

これは、次のスニペットでシミュレートすることができます。fork of react-hot-boilerplateを作業はGitHubの上で提供されています

if (module.hot) module.hot.accept('./App',() => { 
    try { 
    render(App) 
    } catch (e) { 
    location.reload(); 
    } 
}); 

私。

0

また、私は私のアプリにすべてのポイントを追加しましたが、それは問題は、私は、私は

publicPath: '/' 

そして今に変更

publicPath: '/client/dist' 

を持っていた私のwebpack.config.jspublicPathにあった を動作しませんでしたそれは動作する

関連する問題