前言
最近在研究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服务器。
目录结构
为了简明易懂,只展示该教程中用到的文件,大体结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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
是热加载必需的
这边只留下了一些关键性配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| 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
:用于实现无刷新更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 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启动文件
1 2 3 4 5
| 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' } ] }