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...