2

私は自分のアプリに反応ホットローダーを設定しようとしています。 webpack 2、webpack-dev-middleware、ブラウザ同期、エクスプレス、サーバサイドレンダリングをベースにしています。反応するホットローダーが働かない

はここで、私はこのように私のコードを変更している、我々は複数のバンドルを持って

const configureStore = (initialState = {}) => { 
    const store = createStore(
    // storage.reducer is what merges storage state into redux state 
    storage.reducer(rootReducer), 
    inflateDecorators(initialState), 
    applyMiddleware(...middleware) 
) 

    if (module.hot) { 
    module.hot.accept('./reducers',() => { 
     const nextRootReducer = require('./reducers') 

     store.replaceReducer(nextRootReducer) 
    }) 
    } 

    return store 
} 

私webpack.config

require('dotenv').config() 
import path from 'path' 
import webpack from 'webpack' 
import extend from 'extend' 
import AssetsPlugin from 'assets-webpack-plugin' 
import ExtractTextPlugin from 'extract-text-webpack-plugin' 
import bundles from '../src/bundles' 
import merge from 'lodash/merge' 
import fs from 'fs' 

const isDebug = !process.argv.includes('--release'); 
const isVerbose = process.argv.includes('--verbose'); 
const GLOBALS = { 
    'process.env.NODE_ENV': isDebug ? '"development"' : '"production"', 
    'process.env.MORTGAGE_CALCULATOR_API': process.env.MORTGAGE_CALCULATOR_API ? `"${process.env.MORTGAGE_CALCULATOR_API}"` : null, 
    'process.env.API_HOST': process.env.BROWSER_API_HOST ? `"${process.env.BROWSER_API_HOST}"` : process.env.API_HOST ? `"${process.env.API_HOST}"` : null, 
    'process.env.GOOGLE_ANALYTICS_ID': process.env.GOOGLE_ANALYTICS_ID ? `"${process.env.GOOGLE_ANALYTICS_ID}"` : null, 
    'process.env.OMNITURE_SUITE_ID': process.env.OMNITURE_SUITE_ID ? `"${process.env.OMNITURE_SUITE_ID}"` : null, 
    'process.env.COOKIE_DOMAIN': process.env.COOKIE_DOMAIN ? `"${process.env.COOKIE_DOMAIN}"` : null, 
    'process.env.FEATURE_FLAG_BAZAAR_VOICE': process.env.FEATURE_FLAG_BAZAAR_VOICE ? `"${process.env.FEATURE_FLAG_BAZAAR_VOICE}"` : null, 
    'process.env.FEATURE_FLAG_REALTIME_RATING': process.env.FEATURE_FLAG_REALTIME_RATING ? `"${process.env.FEATURE_FLAG_REALTIME_RATING}"` : null, 
    'process.env.SALE_RESULTS_PAGE_FLAG': process.env.SALE_RESULTS_PAGE_FLAG ? `"${process.env.SALE_RESULTS_PAGE_FLAG}"` : null, 
    'process.env.SALE_RELOADED_RESULTS_PAGE_FLAG': process.env.SALE_RELOADED_RESULTS_PAGE_FLAG ? `"${process.env.SALE_RELOADED_RESULTS_PAGE_FLAG}"` : null, 
    'process.env.TRACKER_DOMAIN': process.env.TRACKER_DOMAIN ? `"${process.env.TRACKER_DOMAIN}"` : null, 
    'process.env.USER_SERVICE_ENDPOINT': process.env.USER_SERVICE_ENDPOINT ? `"${process.env.USER_SERVICE_ENDPOINT}"` : null, 
    __DEV__: isDebug 
}; 

// 
// Common configuration chunk to be used for both 
// client-side (client.js) and server-side (server.js) bundles 
// ----------------------------------------------------------------------------- 

const config = { 
    output: { 
    publicPath: '/blaze-assets/', 
    }, 

    cache: isDebug, 

    stats: { 
    colors: true, 
    reasons: isDebug, 
    hash: isVerbose, 
    version: isVerbose, 
    timings: true, 
    chunks: isVerbose, 
    chunkModules: isVerbose, 
    cached: isVerbose, 
    cachedAssets: isVerbose, 
    }, 

    plugins: [ 
    new ExtractTextPlugin({ 
     filename: isDebug ? '[name].css' : '[name].[chunkhash].css', 
     allChunks: true, 
    }), 
    new webpack.LoaderOptionsPlugin({ 
     minimize: true, 
     debug: isDebug, 
    }), 
    ], 

    resolve: { 
    extensions: ['.webpack.js', '.web.js', '.js', '.jsx', '.json'], 
    modules: [ 
     path.resolve('./src'), 
     'node_modules', 
    ] 
    }, 

    module: { 
    rules: [ 
     { 
     test: /\.jsx?$/, 
     include: [ 
      path.resolve(__dirname, '../src'), 
     ], 
     loader: 'babel-loader', 
     }, { 
     test: /\.(scss|css)$/, 
     exclude: ['node_modules'], 
     use: ExtractTextPlugin.extract({ 
      fallback: 'style-loader', 
      use: [ 
      'css-loader', 
      'sass-loader', 
      ] 
     }) 
     }, { 
     test: /\.txt$/, 
     loader: 'raw-loader', 
     }, { 
     test: /\.(otf|png|jpg|jpeg|gif|svg|woff|woff2)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 
     loader: 'url-loader?limit=10000', 
     }, { 
     test: /\.(eot|ttf|wav|mp3)(\?v=[0-9]\.[0-9]\.[0-9])?$/, 
     loader: 'file-loader', 
     }, { 
     test: /\.jade$/, 
     loader: 'jade-loader', 
     } 
    ], 
    }, 
}; 

// 
// Configuration for the client-side bundles 
// ----------------------------------------------------------------------------- 
let clientBundles = {} 

Object.keys(bundles).forEach(function (bundle) { 
    clientBundles[bundle] = [ 
    'bootstrap-loader', 
    `./src/bundles/${bundle}/index.js` 
    ] 
}) 

merge(
    clientBundles, 
    { 
    'embedWidget': ['./src/components/Widgets/EmbedWidget/widgetLoader.js'] 
    }, 
) 

const clientConfig = extend(true, {}, config, { 
    entry: clientBundles, 
    output: { 
    path: path.join(__dirname, '../build/public/blaze-assets/'), 
    filename: isDebug ? '[name].js' : '[name].[chunkhash].js', 
    chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash].chunk.js', 
    }, 
    node: { 
    fs: "empty" 
    }, 
    // Choose a developer tool to enhance debugging 
    // http://webpack.github.io/docs/configuration.html#devtool 
    // devtool: isDebug ? 'cheap-module-source-map' : false, 
    plugins: [ 
    ...config.plugins, 
    ...(isDebug ? [ 
     new webpack.EvalSourceMapDevToolPlugin({ 
      filename: '[file].map', 
      exclude: /\.(css)($)/i, 
     }), 
     ] : []), 
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), 
    new webpack.DefinePlugin({ 
     ...GLOBALS, 
     'process.env.BROWSER': true 
    }), 
    ...(!isDebug ? [ 
     new webpack.optimize.UglifyJsPlugin({ 
     sourceMap: true, 
     compress: { 
      // jscs:disable requireCamelCaseOrUpperCaseIdentifiers 
      screw_ie8: true, 

      // jscs:enable requireCamelCaseOrUpperCaseIdentifiers 
      warnings: isVerbose, 
      unused: true, 
      dead_code: true, 
     }, 
     }), 
     new webpack.optimize.AggressiveMergingPlugin(), 
    ] : []), 
    new AssetsPlugin({ 
     path: path.join(__dirname, '../build'), 
     filename: 'assets.json', 
     prettyPrint: true, 
    }), 
    ], 
}); 

// 
// Configuration for the server-side bundle (server.js) 
// ----------------------------------------------------------------------------- 

var srcDirs = {}; 
fs.readdirSync('src').forEach(function(path) { 
    srcDirs[path] = true 
}); 

function isExternalFile(context, request, callback) { 
    var isExternal = request.match(/^[@a-z][a-z\/\.\-0-9]*$/i) && !srcDirs[request.split("/")[0]] 
    callback(null, Boolean(isExternal)); 
} 

const serverConfig = extend(true, {}, config, { 
    entry: './src/server.js', 
    output: { 
    path: path.join(__dirname, '../build/public/blaze-assets/'), 
    filename: '../../server.js', 
    libraryTarget: 'commonjs2', 
    }, 
    target: 'node', 
    externals: [ 
    /^\.\/assets\.json$/, 
    isExternalFile 
    ], 
    node: { 
    console: false, 
    global: false, 
    process: false, 
    Buffer: false, 
    __filename: false, 
    __dirname: false, 
    }, 
    devtool: isDebug ? 'cheap-module-source-map' : 'source-map', 
    plugins: [ 
    ...config.plugins, 
    new webpack.DefinePlugin({ 
     ...GLOBALS, 
     'process.env.BROWSER': false, 
     'process.env.API_HOST': process.env.API_HOST ? `"${process.env.API_HOST}"` : null 
    }), 
    new webpack.NormalModuleReplacementPlugin(/\.(scss|css|eot|ttf|woff|woff2)$/, 'node-noop'), 
    new webpack.BannerPlugin({ 
     banner: `require('dotenv').config(); require('newrelic'); require('source-map-support').install();`, 
     raw: true, 
     entryOnly: false 
    }) 
    ], 
}); 

export default [clientConfig, serverConfig]; 

start.jsファイル

ホットロード減速へ
import Browsersync from 'browser-sync' 
import webpack from 'webpack' 
import webpackMiddleware from 'webpack-dev-middleware' 
import webpackHotMiddleware from 'webpack-hot-middleware' 
import WriteFilePlugin from 'write-file-webpack-plugin' 
import run from './run' 
import runServer from './runServer' 
import webpackConfig from './webpack.config' 
import clean from './clean' 
import copy from './copy' 

const isDebug = !process.argv.includes('--release') 
const [, serverConfig] = webpackConfig 
process.argv.push('--watch') 
/** 
* Launches a development web server with "live reload" functionality - 
* synchronizing URLs, interactions and code changes across multiple devices. 
*/ 
async function start() { 
    await run(clean) 
    await run(copy.bind(undefined, { watch: true })) 
    await new Promise((resolve) => { 

    serverConfig.plugins.push(new WriteFilePlugin({ log: false })) 
    // Patch the client-side bundle configurations 
    // to enable Hot Module Replacement (HMR) and React Transform 
    webpackConfig.filter((x) => x.target !== 'node').forEach((config) => { 
     /* eslint-disable no-param-reassign */ 
     Object.keys(config.entry).forEach((entryKey) => { 
     if (!Array.isArray(config.entry[entryKey])) { 
      config.entry[entryKey] = [config.entry[entryKey]] 
     } 
     config.entry[entryKey].unshift('react-hot-loader/patch', 'webpack-hot-middleware/client') 
     }) 
     if (config.output.filename) { 
     config.output.filename = config.output.filename.replace('[chunkhash]', '[hash]') 
     } 
     if (config.output.chunkFilename) { 
     config.output.chunkFilename = config.output.chunkFilename.replace('[chunkhash]', '[hash]') 
     } 
     config.plugins.push(new webpack.HotModuleReplacementPlugin()) 
     config.plugins.push(new webpack.NoEmitOnErrorsPlugin()) 
     config 
     .module 
     .rules 
     .filter((x) => x.loader === 'babel-loader') 
     .forEach((x) => (x.query = { 
      ...x.query, 
      cacheDirectory: true, 
      presets: [ 
      ['es2015', {modules: false}], 
      'stage-0', 
      'react' 
      ], 
      plugins: [ 
      ...(x.query ? x.query.plugins : []), 
      [ 
       'react-hot-loader/babel', 
      ], 
      ], 
     })) 
     /* eslint-enable no-param-reassign */ 
    }) 

    const bundler = webpack(webpackConfig) 
    const wpMiddleware = webpackMiddleware(bundler, { 

     // IMPORTANT: webpack middleware can't access config, 
     // so we should provide publicPath by ourselves 
     publicPath: webpackConfig[0].output.publicPath, 

     // Pretty colored output 
     stats: webpackConfig[0].stats, 

     // For other settings see 
     // https://webpack.github.io/docs/webpack-dev-middleware 
    }) 
    const hotMiddleware = webpackHotMiddleware(bundler.compilers[0]) 

    let handleBundleComplete = async() => { 
     handleBundleComplete = (stats) => !stats.stats[1].compilation.errors.length && runServer() 

     const server = await runServer() 
     const bs = Browsersync.create() 

     bs.init({ 
     ...isDebug ? {} : { notify: false, ui: false }, 

     proxy: { 
      target: server.host, 
      middleware: [wpMiddleware, hotMiddleware], 
      proxyOptions: { 
      xfwd: true, 
      }, 
     }, 
     open: false, 
     files: ['build/content/**/*.*'], 
     }, resolve) 
    } 

    bundler.plugin('done', (stats) => handleBundleComplete(stats)) 
    }) 
} 

export default start 

ですしたがって、エントリロジックを処理する共通の機能があります。

import 'babel-polyfill' 
import React from 'react' 
import ReactDOM from 'react-dom' 
import FastClick from 'fastclick' 
import { Provider } from 'react-redux' 
import { setUrl } from 'actions' 
import Location from '../../libs/Location' 
import configureStore, { loadFromLocalStorage } from '../../configureStore' 
import { AppContainer } from 'react-hot-loader' 

const initialState = window.__INITIAL_STATE__ 

const store = configureStore(initialState) 

function runner (createBody) { 
    return function() { 
    // Make taps on links and buttons work fast on mobiles 
    FastClick.attach(document.body) 

    const component = (
    <AppContainer> 
     <Provider store={store}> 
     {createBody()} 
     </Provider> 
    </AppContainer> 
    ) 

    if (!initialState) { 
     store.dispatch(setUrl(`${Location.location.pathname}${Location.location.search}`)) 
    } 

    Location.listen((location) => { 
     store.dispatch(setUrl(`${location.pathname}${location.search}`)) 
    }) 

    ReactDOM.render(component, document.getElementById('app')) 

    // only apply stored state after first render 
    // this allows serverside and clientside rendering to agree on initial state 
    loadFromLocalStorage(store) 
    } 
} 

export default function run (createBody) { 
    if (['complete', 'loaded', 'interactive'].includes(document.readyState) && document.body) { 
    runner(createBody)() 
    } else { 
    document.addEventListener('DOMContentLoaded', runner(createBody), false) 
    } 
} 

これは、上記の一般的な機能は、

import run from '../util/run' 
import createBody from './body' 

run(createBody) 
if (module.hot) { 
    module.hot.accept('./body',() => run(createBody)) 
} 

ない私はまだ行方不明ですかわから呼ばれるバンドルのエントリポイントの一つであり、私はいくつかのブログの記事を追跡しようとしたホットローダーのドキュメントを反応させます私はそれを働かせることができませんでした。私はextract-text-webpack-pluginを使用していたよう

+0

私のバンドルエントリーポイントで、このビットを追加するとある程度問題が解決されました。 'const body = require( './ body')。default run(body)'。私はwebpack 2でこれはドキュメントごとに必要ではないと思った。私はまだCSSをホットリロードすることができません。 – Mah3ndra

答えて

0

if (module.hot) { 
    module.hot.accept('./body',() => { 
    const body = require('./body').default 
    run(body) 
    }) 
} 

、このようなものである必要があり、あなたのエントリポイントコードを動作するようにホットローダーを反応させるために、それもWebPACKの2で、セットアップの似たようなものを持っている人のために役立つだろうと思いましたCSSの変更をホットリロードすることはできません。すでにbrowser-syncを使用しているので、簡単に回避するには、cssファイルを書き込んでbrowser-syncに変更を聞かせるにはwrite-file-webpack-pluginを使用します。

関連する問題