Egg 和 Webpack 项目搭建实践
2019-03-30 · 726 chars · 4 min read
最近的项目技术栈使用 Egg + React,因为本身有 Egg,所以不希望在单独启动类似 webpack-dev-server 的工具来运行前端,而是在开发模式下,前端直接基于 Egg 运行起来。想法是好的,可是实现起来颇费了一番周折。最终的效果在 Egg-Webpack-Starter,有同样需求的朋友可以看看。下面详细讲讲配置和使用方法:
我们主要的目的是使用 Egg + Webpack 搭建一套前后端统一的开发环境,主要包括:
- 后端 Node.js 使用 Egg 框架
- 前端使用基于 webpack 的工作流,与具体框架无关(使用 react 做演示)
- 开发过程中无需分别启动前端与后端应用(基于 egg-webpack)
快速使用#
clone 项目
git clone https://github.com/keenwon/Egg-Webpack-Starter.git
本地开发
npm run dev
执行测试 & lint
npm test
应用部署
# 构建前端静态资源 npm run build # 启动应用 npm start # 停止应用 npm stop
目录结构#
. ├── app # 服务端代码 │ ├── controller # egg controller │ ├── public # 静态资源目录 │ │ └── static # 前端 build 输出 │ └── view # egg view ├── client # 客户端代码 │ ├── build # webpack config │ └── src # 客户端源码 │ └── views ├── config # egg config
Egg + Webpack#
详细讲述整个搭建过程,如果你只是想简单使用,直接看前面的“快速使用”就好了
Egg#
首先,你得有个一 egg 应用,具体可以查看官方文档,此处不再赘述。
添加 Webpack#
我们使用 egg-webpack 实现基于 egg 的 webpack 编译和热更新。关于 egg-webpack 的更多内容可以看这里。
安装和配置 egg-webpack#
npm install egg-webpack --save-dev
配置 egg
启用 plugin:
// 仅需 local 环境 // {root}/config/plugin.local.js exports.webpack = { enable: true, package: 'egg-webpack', }
配置端口和 webpack config file:
// {root}/config/config.local.js exports.webpack = { port: 9000, webpackConfigList: [require('../webpack.config')], }
这里指定 9000 端口,后面会用到。
配置热更新#
安装 webpack-hot-middleware:
npm i webpack-hot-middleware --save-dev
配置 webpack.dev.js:
module.exports = { // ... entry: { app: [ // 注意端口和前面设置的一致 'webpack-hot-middleware/client?path=http://127.0.0.1:9000/__webpack_hmr&reload=true', '../src/index.js', ], }, plugins: [new webpack.HotModuleReplacementPlugin()], // ... }
添加 react-hot-loader(其他框架同理):
// babel.config.js module.exports = { // ... plugins: ['react-hot-loader/babel'], // ... }
修改入口组件,使用 react-hot-loader 提供的 hoc:
import React from 'react' import { hot } from 'react-hot-loader/root' const App = () => <div>App</div> export default hot(App)
前后端对接#
这里使用 handlebar 模板,开发模式写死就好了, 生产环境读取 manifest:
{{#if isDev}} <script type="text/javascript" src="public/static/app.js"></script> {{else}} <script type="text/javascript" src="{{manifest.[runtime.js]}}"></script> <script type="text/javascript" src="{{manifest.[vendors.js]}}"></script> <script type="text/javascript" src="{{manifest.[app.js]}}"></script> {{/if}}
最后的说明#
为什么 package.json 会有 acorn 相关的依赖?eslint 和其他包都可能依赖 acorn,会造成冲突,具体查看 https://github.com/eslint/espree/issues/393