Webpacket 已經到3了, 這裏添加更新說明,並說明結合babel-loader
使用的簡要步驟css
參考資料html
#0. 環境前端
node: v9.0.0 webpack: ^3.10.0 webpack-dev-server: ^2.10.1 react-hot-loader": ^3.1.3 babel-core: ^6.26.0 babel-loader: ^7.1.2 babel-plugin-import: ^1.6.3 babel-preset-env: ^1.6.1 babel-preset-react: ^6.24.1
#1. 在.babelrc
中添加 react-hot-loader
node
// .babelrc { "plugins": [ "react-hot-loader/babel" ] }
#2. webpacket.confg.js 中的設置react
const path = require('path'); const webpack = require('webpack'); const moment = require('moment') const HtmlWebpackPlugin = require('html-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const WriteFilePlugin = require('write-file-webpack-plugin'); const publish_date = moment().format("YYYYMMDD") let config = { devtool: 'eval-source-map', resolve: { extensions: ['.js', '.jsx', '.json'] }, entry: { app: [ 'react-hot-loader/patch', './src/index' ] }, module: { rules: [ { test: /\.jsx$/, exclude: /node_modules/, use: [{ loader: 'babel-loader' }] }, { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' } ] }, { test: /\.less$/, use: [ { loader: 'style-loader' }, { loader: "css-loader", }, { loader: "less-loader" } ] }, ] }, output: { path: path.resolve(__dirname, 'dist', publish_date), filename: '[name].[hash].js', sourceMapFilename: '[name].[hash].map', publicPath: '/' + publish_date }, plugins: [ new WriteFilePlugin(), new HtmlWebpackPlugin({ title: 'RBAC', inject: true, template: './index.html', filename: 'index.html', chunksSortMode: 'auto', minify: false, hash: false, xhtml: true, chunks: ['app'], cache: true, showErrors: true, }), new CopyWebpackPlugin([ { from: 'src/assets', to: 'assets' } ]), new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ], devServer: { contentBase: path.join(__dirname, 'dist', publish_date), hot: true, host: '0.0.0.0', port: 8000, publicPath: '/' + publish_date, } } module.exports = config;
devServer
的 hot
要設置爲true
webpack
#3. 要在你的應用程序入口以前添加 react-hot-loader/patch
, 以下:git
let config = { devtool: 'eval-source-map', resolve: { extensions: ['.js', '.jsx', '.json'] }, entry: { app: [ 'react-hot-loader/patch', './src/index' ] }, ... ... ... }
在 #2 有完整的配置github
#4. 入口文件要這樣web
// index.js import React from 'react' import ReactDOM from 'react-dom' // 導入HMR import { AppContainer } from 'react-hot-loader' import App from './containers/App' // 定義一個熱加載回調函數用於從新渲染入口組件 const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('root'), ) } // 啓動時調用 render(App) // 當發送熱加載時調用, Webpack打包的生產環境不會有 `module.hot`, 所以這塊代碼在開發環境 // 下面的if塊裏面的代碼不會執行 if (module.hot) { module.hot.accept('./containers/App', () => { render(App) }) }
#5. .babelrc
中的 modules
屬性express
modules
屬性必需要設置爲 false
, 不然HMR無效
{ "presets": [ ["env", { "modules": false }], "react" ], "plugins": [ ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }], "react-hot-loader/babel" ] }
#6. 最新若是你不用babel, 直接在配置文件中設置 react-hot-loader/webpack
加載器
// webpack.config.js module.exports = { module: { rules: [ { test: /\.jsx?$/, use: ['react-hot-loader/webpack'], }, ], }, }
命令行方式是最簡單的方式, 若是項目只是純Web前端, 使用這種方式是最便捷的. 只須要在package.json
文件中的scripts
裏面添加下面一行就能夠了.
直接命令行:
webpack-dev-server --content-base=www --inline --watch --hot --progress --config webpack.config.js
經過 npm run dev
或 yarn run dev
:
// package.json "scripts": { "dev": "webpack-dev-server --content-base=www --inline --watch --hot --progress --config webpack.config.js", ... },
參數說明:
--content-base
: 靜態資源的目錄, 爲output.path
設置的目錄.output: { path: path.resolve(__dirname, 'dist'), },
--watch
: 監視模式, Web執行完打包後不退出, 一直監聽文件變化,Ctrl + S
後自動構建變化的模塊, 及其依賴模塊.--hot
: 開啓模塊熱替換.--progress
: 顯示進度--config
: 指定配置文件webpack.config.js
爲默認文件名.
API的方式須要對webpack.config.js
配置文件進行修改, 增長HotModuleReplacementPlugin
插件.
Webpack 1.x
const path = require('path'); const webpack = require('webpack'); module.exports = { context: path.join(__dirname, 'js'), entry: [ './index.js', 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:8080/', ], output: { path: path.join(__dirname, 'www'), filename: 'bundle.js', publicPath: '/', }, plugins: [ new webpack.HotModuleReplacementPlugin(), ], };
Webpack 2.x
Webpack 2.x 須要一個額外配置 .babelrc
, 增長 react-hot-loader/babel
:
{ "presets": [ "es2015", "react", "stage-0" ], "plugins": [ "react-hot-loader/babel" ] }
webpack.config.js
模塊加載器的配置, 和Webpack 1.x是不一樣的:
rules: [ // Javascript模塊加載器 { test: /\.js|jsx$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { cacheDirectory : true, presets: [ ['es2015', {modules: false}] ], // ES7 plugins: [ // 模塊動態導入 'syntax-dynamic-import', 'transform-async-to-generator', 'transform-regenerator', // 運行時轉換 'transform-runtime' ] } } },
須要編寫一個Express服務器, 而且把 webpack-dev-middleware
集成到本身的服務器中. 多用於須要高度定製的場景, 實際上以前的webpack-dev-server
就是使用的 webpack-dev-middleware
來實現的, 這裏能夠證實.
const express = require('express'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); const webpack = require('webpack'); const webpackConfig = require('./webpack.config.js'); const app = express(); const compiler = webpack(webpackConfig); app.use(webpackDevMiddleware(compiler, { // 啓用熱更 hot: true, filename: 'bundle.js', publicPath: '/assets/', stats: { colors: true, }, // 路由須要的 historyApiFallback: true, })); app.use(webpackHotMiddleware(compiler, { log: console.log, path: '/__webpack_hmr', heartbeat: 10 * 1000, })); app.get('/', function(req, res) { res.send('<body>Hello World<script src=\'assets/bundle.js\'></script></body>'); }); const server = app.listen(3000, function() { const host = server.address().address; const port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); });
對於這種形式的熱更, 須要配合使用 webpack-hot-middleware
.
須要在入口文件裏面添加 module.hot.accept
配置, 下面給出入口文件的完整代碼:
import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router Route, Link } from 'react-router-dom'; // React Router v4 版本. import App from './App'; import { AppContainer } from 'react-hot-loader'; const render = (Component) => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('App') ); } render(App); if (module.hot) { module.hot.accept('./App', () => { render(App) }); }
原先直接掛載App
, 要使用HMR, 須要在外層包一個<AppContainer>
容器.
這個視頻, 是Chrome, Safari, Firefox 三端同步操做的示例.
對於須要支持全平臺(移動, 桌面, Web)的開發, 可使用 BrowerSync 這個神器. 它經過 Websocket 同步事件.
首先, 把模塊包含進來:
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
其次, 配置插件:
new BrowserSyncPlugin({ host: 'localhost', port: 3000, // server: { // 獨立服務器模式, 這裏我使用的代理模式, 註釋掉了 // baseDir: ['dist'] // 監視的目錄, 其中若是文件發生變化, 刷新頁面 // }, proxy: 'http://localhost:8080/' }, { name: 'dev', reload: false // 不讓 BrowerSync 刷新頁面, 讓 webpack-dev-server 管理頁面是否須要刷新. }),
這裏我使用代理模式, 由於除了 BrowerSync 的功能外, 我還要使用 webpack-dev-server
HMR功能. 具體配置參考: https://github.com/Va1/browse...
https://github.com/search?utf...
https://github.com/webpack/we...
https://github.com/glenjamin/...
http://acgtofe.com/posts/2016...
https://github.com/Va1/browse...