3

現在、私はWebpack 2のセットアップでHMRを動作させるのに苦労しています。セットアップ全体について説明しますので、誰かが何が起こっているのかを理解するのに十分であることを願っています。Webpack 2 HMRを入手できません

私のプロジェクトの構造:私はオプションをしました。このファイルでそう

function buildConfig(env) { 
    return require('./config/' + env + '.js')(env) 
} 

module.exports = buildConfig; 

config 
    dev.js 
    prod.js 
dist 
    css 
    js 
    index.html 
node_modules 
src 
    components 
    // some JavaScript components 
    shared 
    stylesheets 
    index.js 
.babelrc 
package.json 
webpack.config.js 

これは私のプロジェクトのルートに配置された私のwebpack.config.jsファイルの内容は、あります異なる環境をbuildConfig関数に渡すことができます。このオプションを使用して、開発と生産に異なる設定ファイルを使用します。私はもちろん、私のpackage.jsonで複数のフィールドをしましたが、それらは無関係だので、私はそれらをここに示されていないだろう

{ 
    "main": "index.js", 
    "scripts": { 
    "build:dev": "node_modules/.bin/webpack-dev-server --env=dev", 
    "build:prod": "node_modules/.bin/webpack -p --env=prod" 
    }, 
    }, 
    "devDependencies": { 
    "autoprefixer-loader": "^3.2.0", 
    "babel-cli": "^6.18.0", 
    "babel-core": "^6.24.1", 
    "babel-loader": "^6.2.5", 
    "babel-preset-latest": "^6.16.0", 
    "babel-preset-react": "^6.16.0", 
    "babel-preset-stage-0": "^6.16.0", 
    "css-loader": "^0.25.0", 
    "extract-text-webpack-plugin": "^2.1.0", 
    "json-loader": "^0.5.4", 
    "node-sass": "^3.13.1", 
    "postcss-loader": "^1.3.3", 
    "postcss-scss": "^0.4.1", 
    "sass-loader": "^4.1.1", 
    "style-loader": "^0.13.1", 
    "webpack": "^2.4.1", 
    "webpack-dev-server": "^2.4.2" 
    }, 
    "dependencies": { 
    "babel-plugin-react-css-modules": "^2.6.0", 
    "react": "^15.3.2", 
    "react-dom": "^15.3.2", 
    "react-hot-loader": "^3.0.0-beta.6", 
    "react-icons": "^2.2.1" 
    } 
} 

:これは私のpackage.jsonファイル内のコンテンツです。

開発中に端末でnpm run build:devコマンドを実行します。これにより、configフォルダのファイルdev.jsが使用されます。

const webpack = require('webpack'); 
const { resolve } = require('path'); 
const context = resolve(__dirname, './../src'); 

module.exports = function(env) { 
    return { 
    context, 
    entry: { 
     app: [ 
     'react-hot-loader/patch', 
     // activate HMR for React 
     'webpack-dev-server/client?http://localhost:3000', 
     // bundle the client for webpack-dev-server 
     // and connect to the provided endpoint 
     'webpack/hot/only-dev-server', 
     // bundle the client for hot reloading 
     // only- means to only hot reload for successful updates 
     './index.js' 
     // the entry point of our app 
     ] 
    }, 
    output: { 
     path: resolve(__dirname, './../dist'), // `dist` is the destination 
     filename: '[name].js', 
     publicPath: '/js' 
    }, 
    devServer: { 
     hot: true, // enable HMR on the server 
     inline: true, 
     contentBase: resolve(__dirname, './../dist'), // `__dirname` is root of the project 
     publicPath: '/js', 
     port: 3000 
    }, 
    devtool: 'inline-source-map', 
    module: { 
     rules: [ 
     { 
      test: /\.js$/, // Check for all js files 
      exclude: /node_modules/, 
      use: [{ 
      loader: 'babel-loader', 
      query: { 
       presets: ['latest', 'react'], 
       plugins: [ 
       [ 
        "react-css-modules", 
        { 
        context: __dirname + '/../src', // `__dirname` is root of project and `src` is source 
        "generateScopedName": "[name]__[local]___[hash:base64]", 
        "filetypes": { 
         ".scss": "postcss-scss" 
        } 
        } 
       ] 
       ] 
      } 
      }] 
     }, 
     { 
      test: /\.scss$/, 
      use: [ 
      'style-loader', 
      { 
       loader: 'css-loader', 
       options: { 
       sourceMap: true, 
       modules: true, 
       importLoaders: 2, 
       localIdentName: '[name]__[local]___[hash:base64]' 
       } 
      }, 
      'sass-loader', 
      { 
       loader: 'postcss-loader', 
       options: { 
       plugins:() => { 
        return [ 
        require('autoprefixer') 
        ]; 
       } 
       } 
      } 
      ] 
     } 
     ] 
    }, 
    plugins: [ 
     new webpack.HotModuleReplacementPlugin(), 
     // enable HMR globally 
     new webpack.NamedModulesPlugin() 
     // prints more readable module names in the browser console on HMR updates 
    ] 
    } 
}; 

そして最後にではなく、少なくとも、私のHMRのセットアップ:これはdev.jsファイルの内容です。私は私のブラウザで私のnpm start build:devを実行し、予想通り、私は自分のサイトが働い見http://localhost:3000に行くとき、

ので
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { AppContainer } from 'react-hot-loader'; 
import TodoApp from './components/TodoApp'; 
import './stylesheets/Stylesheets.scss'; 

const render = (Component) => { 
    ReactDOM.render(
     <AppContainer> 
     <Component /> 
     </AppContainer>, 
     document.querySelector('#main') 
); 
}; 

render(TodoApp); 

// Hot Module Replacement API 
if (module.hot) { 
    module.hot.accept('./components/TodoApp',() => { 
    render(TodoApp) 
    }); 
} 

:私は私のindex.jsファイルにこの設定をしました。

dev-server.js:49 [HMR] Waiting for update signal from WDS... 
only-dev-server.js:66 [HMR] Waiting for update signal from WDS... 
TodoApp.js:102 test 
client?344c:41 [WDS] Hot Module Replacement enabled. 

testテキストは私のTodoAppコンポーネントでレンダリング機能から来ている:これは、コンソールで出力されます。この機能は次のようになります。

render() { 
    console.log('test'); 
    return(
     <div styleName="TodoApp"> 
     <TodoForm addTodo={this.addTodo} /> 
     <TodoList todos={this.state.todos} deleteTodo={this.deleteTodo} toggleDone={this.toggleDone} updateTodo={this.updateTodo} /> 
     </div> 
); 
} 

これで重要なものになりました。このレンダリング関数の戻り値を更新します。この関数は、HMRを起動させるはずです。render関数をこれに変更します。

render() { 
    console.log('test'); 
    return(
     <div styleName="TodoApp"> 
     <p>Hi Stackoverflow</p> 
     <TodoForm addTodo={this.addTodo} /> 
     <TodoList todos={this.state.todos} deleteTodo={this.deleteTodo} toggleDone={this.toggleDone} updateTodo={this.updateTodo} /> 
     </div> 
); 
} 

これは私がコンソールに出力され得る:

client?344c:41 [WDS] App updated. Recompiling... 
client?344c:41 [WDS] App hot update... 
dev-server.js:45 [HMR] Checking for updates on the server... 
TodoApp.js:102 test 
log-apply-result.js:20 [HMR] Updated modules: 
log-apply-result.js:22 [HMR] - ./components/TodoApp.js 
dev-server.js:27 [HMR] App is up to date. 

あなたはこれが良いと思います。 しかし私のサイトは何も更新しません。

は、その後、私はこれまでの私のindex.jsでHMRコード変更:

// Hot Module Replacement API 
if (module.hot) { 
    module.hot.accept(); 
} 

をそして、それは動作します。私はそれを得ていない。

// Hot Module Replacement API 
if (module.hot) { 
    module.hot.accept('./components/TodoApp',() => { 
    render(TodoApp) 
    }); 
} 

ところで、この設定は、私は誰も私を助けることができることを願っていますhttps://webpack.js.org/guides/hmr-react/

からの設定に基づいています。これは私のHMRコードであれば、なぜそれが動作しません。誰かがもっと情報を必要とするなら、躊躇しないでください。前もって感謝します!

UPDATE

.babelrcファイルを投稿する忘れました。これは、次のとおりです。

{ 
    "presets": [ 
    ["es2015", {"modules": false}], 
    // webpack understands the native import syntax, and uses it for tree shaking 

    "react" 
    // Transpile React components to JavaScript 
    ], 
    "plugins": [ 
    "react-hot-loader/babel" 
    // EnablesReact code to work with HMR. 
    ] 
} 
+0

はあなた '.babelrc'ファイルでes2015モジュールを無効にしましたか? https://webpack.js.org/guides/hmr-react/#babel-config –

+0

申し訳ありません私の '.babelrc'ファイルの内容を投稿するのを忘れていました。今これを行うでしょう。 – DavidWorldpeace

答えて

5

輸入は静的であり、更新がmodule.hot.acceptに同定された後に「TodoAppはまだあなたのモジュールの古いバージョンを保持し、HMRはそれとdoesnのを実現として、あなたは、再び、全く同じコンポーネントをレンダリングアプリで何かをリフレッシュしたり変更したりしないでください。

Dynamic import: import()を使用します。 babelで動作させるには、babel-plugin-syntax-dynamic-importを追加する必要があります。そうしないと、importが関数として使用されるとは考えられないため、構文エラーが報告されます。あなたのWebPACKの設定でreact-hot-loader/patchを使用している場合react-hot-loader/babelが必要とされていないので、あなたの.babelrcであなたのプラグインは次のようになります。

"plugins": [ 
    "syntax-dynamic-import" 
] 

をごrender()機能では、あなたが今TodoAppをインポートし、それをレンダリングすることができます。

const render =() => { 
    import('./components/TodoApp').then(({ default: Component }) => { 
    ReactDOM.render(
     <AppContainer> 
     <Component /> 
     </AppContainer>, 
     document.querySelector('#main') 
    ); 
    }); 
}; 

render(); 

// Hot Module Replacement API 
if (module.hot) { 
    module.hot.accept('./components/TodoApp', render); 
} 

import()モジュールで解決される約束である、とあなたはdefaultエクスポートを使用します。


上記事実であるにもかかわらず、WebPACKのもreact-hot-loader docs - Webpack 2で説明した箱、外のESモジュールを処理するためのWebPACKのドキュメントでは、動的な輸入品を使用する必要はありません、とのWebPACKもHMR処理しているので、その場合、何をすべきかを知るでしょう。これが機能するには、モジュールをcommonjに変換してはいけません。 ["es2015", {"modules": false}]でこれを行いましたが、webpack configにはlatestのプリセットが設定されており、モジュールも変わります。混乱を避けるために、いくつかをローダーオプションに分割するのではなく、すべてのバベル構成を.babelrcにする必要があります。

のプリセットをウェブパックの設定から完全に削除すると、すでに.babelrcに必要なプリセットがあるように機能します。 babel-preset-latestは推奨されておらず、これらの機能を使用する場合はbabel-preset-envを使用して開始し、es2015に置き換えてください。だから、.babelrcであなたのプリセットは、次のようになります。

"presets": [ 
    ["env", {"modules": false}], 
    "react" 
], 
+0

ありがとう、これは本当に問題でした!私の '.babelrc'ファイルの設定は' webpack.config'ファイルで上書きされていました。 – DavidWorldpeace

+0

webpack.configより.babelrcを使用する理由は何ですか?なぜwebpack.configを使用しないのですか? –

+1

@JohnLeidegren '.babelrc'は、Babelを使用するすべてに適用されます。 webpackの設定でそれを設定すると、webpackのためだけに機能します。 webpackの外でBabelには多くの用途があります。 1つの例はテストです。[Unexpected Token - 既存のReact + Web-packアプリケーションのJest](https://stackoverflow.com/questions/45372145/unexpected-token-jest-for-existing-react-web- pack-app)が示した。 –

1

このissue GitHubの上またはちょうどあなたのindex.jsでこれを使用チェック:

import React from 'react' 
import ReactDOM from 'react-dom' 
import { AppContainer } from 'react-hot-loader' 

import App from './components/App' 

const render = Component => { 
    ReactDOM.render(
     <AppContainer> 
      <Component/> 
     </AppContainer>, 
     document.getElementById('react-root') 
    ) 
} 

render(App) 

if(module.hot) { 
    module.hot.accept(); 
} 
関連する問題