koa2.0+webpack3.x实现React热更新
前言
最近在研究react同构,由于后端打算使用koa2.0,因此在开发环境想搭一套koa服务器代替webpack-dev-server,实现代码实时刷新。中间遇到过很多坑,好在最后还是跑通了这个流程,写下此文帮助后人爬坑- -。
PS:对于koa和webpack还不是很了解的同学,可以点击koa官网 webpack官网
大体流程
此教程仅限适用于开发环境。先介绍三个文件
webpack.config.dev.js webpack配置文件
server.dev.js server入口文件
app.js app启动文件。该文件在开发环境和生产环境都可以使用
通过npm的脚本命令,执行入口文件server.dev.js,该文件会载入webpack配置文件webpack.config.dev.js,再通过app.js启动一个koa服务器。
目录结构
为了简明易懂,只展示该教程中用到的文件,大体结构如下
project/ // root directory ├── build/ // webpack config directory │ └── webpack.config.dev.js // config for webpack when run development bundle ├── client/ // client directory │ ├── about/ // `about` module │ ├── common/ // `common` module │ ├── home/ // `home` module │ ├── index.js // client entry file │ └── routes.js // client route config ├── server/ // server directory │ ├── controllers/ // controllers in server │ ├── middlewares/ // custom middlewares in server │ ├── models/ // models in server │ ├── routes/ // routes in server │ ├── app.js // create koa instance in server │ └── server.dev.js // entry file in development mode └── package.json // npm entry file
webpack配置文件
安装相应的babel插件,可以把es6/es7、jsx语法编译成浏览器可以兼容的代码。
npm install --save-dev babel-loader babel-plugin-transform-runtime babel-preset-es2015 babel-preset-react babel-preset-react-hmre babel-preset-stage-2
其中babel-preset-react-hmre是热加载必需的
这边只留下了一些关键性配置。
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
devtool: 'eval-source-map',
entry: {
index: [
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=10000', // 这个是必需的
'./client/index.js',
],
vendor: [ // 将公用的框架库打成一个js
'react',
'react-dom',
]
},
output: {
path: path.resolve(__dirname, '../dist/client'),
filename: '[name].js',
chunkFilename: 'chunk.[name].js',
publicPath: '/'
},
module: {
// 加载器配置
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react', 'stage-2', 'react-hmre'],
plugins: ['transform-runtime'],
cacheDirectory: true
}
},
{
test: /\.json$/,
loader: 'json'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './client/index.html',
inject: true, // 如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body 元素的底部,'head' 将放置到 head 元素中。
hash: true, // 将添加一个唯一的 webpack 编译 hash 到所有包含的脚本和 CSS 文件,对于解除 cache 很有用
minify: {
removeComments: true,
collapseWhitespace: false
},
// 允许只添加某些块
chunks: [
'index', 'vendor', 'manifest'
],
filename: 'index.html'
}),
new webpack.optimize.OccurrenceOrderPlugin(), // 根据模块调用次数,给模块分配ids,常被调用的ids分配更短的id,使得ids可预测,降低文件大小
new webpack.HotModuleReplacementPlugin(), // 模块热替换
new webpack.NoEmitOnErrorsPlugin() // 在编译出现错误时,用于跳过输出阶段。这样可以确保输出资源不会包含错误。
]
};
module.exports = config
server入口文件
此处的babel-register是针对node还未支持的es6/es7进行兼容。
koa-webpack-dev-middleware:用于处理静态文件 koa-webpack-hot-middleware:用于实现无刷新更新
// Javascript require hook
require('babel-register')({
presets: ['es2015', 'react', 'stage-2'],
plugins: ['transform-runtime']
})
const app = require('./app.js').default
const webpack = require('webpack')
const devMiddleware = require('koa-webpack-dev-middleware')
const hotMiddleware = require('koa-webpack-hot-middleware')
const config = require('../build/webpack.config.dev')
const compile = webpack(config)
app.use(devMiddleware(compile, {
noInfo: true,
publicPath: config.output.publicPath
}))
app.use(hotMiddleware(compile))
app.listen(3000);
app启动文件
import Koa from 'koa'; ... const app = new Koa(); ... export default app;
执行
在package.json中添加脚本命令
"scripts": { "dev": node ./server/server.dev.js --watch server --watch build" }
最后通过在命令行执行
npm run dev
就大功告成啦!
本文只讲了关于热加载的必要配置,大家可以根据自己的项目进行相应修改即可。
常见问题
__webpack_hmr found 404
出现原因:koa-webpack-hot-middleware或koa-webpack-dev-middleware版本不对
解决方案:
npm install --save-dev [email protected] [email protected]
update check failed: error: manifest request to XXX
出现原因:个人认为是.json文件无法被识别
解决方案:
在webpack.config.js中增加
module: { rules: [ { test: /\.json$/, loader: 'json' } ] }
Comments