摘要:在前后端分离的前端项目开发中经常用到。是的一个中间件。即是一个重要的功能。配置先来在配置文件中引入添加一个和通信的客户端添加应用入口文件在插件中引入在我们的开发环境中是这样配置的。
原文链接
此文是我同事写的,搭建Express结合Webpack。以下是正文,后面我会附上我的解读
本篇文件主要讲结合 Webpack 和 Express 实现前后端热更新开发,如果你还不太了解webpack推荐阅读
webpack 官网文档
Webpack dev server 是一个轻量的node.js express服务器,实现了 webpack 编译代码实时输出更新。在前后端分离的前端项目开发中经常用到。不过这篇文章应该不会讲到它。
webpack dev middlewareWebpack dev middleware 是 WebPack 的一个中间件。它用于在 Express 中分发需要通过 WebPack 编译的文件。多带带使用它就可以完成代码的热重载(hot reloading)功能。
特性:
不会在硬盘中写入文件,完全基于内存实现。
如果使用 watch 模式监听代码修改,Webpack 会自动编译,如果在 Webpack 编译过程中请求文件,Webpack dev middleware 会延迟请求,直到编译完成之后再开始发送编译完成的文件。
webpack hot middlewareWebpack hot middleware 它通过订阅 Webpack 的编译更新,之后通过执行 webpack 的 HMR api 将这些代码模块的更新推送给浏览器端。
HMRHMR 即 Hot Module Replacement 是 Webpack 一个重要的功能。它可以使我们不用通过手动地刷新浏览器页面实现将我们的更新代码实时应用到当前页面中。
HMR 的实现原理是在我们的开发中的应用代码中加入了 HMR Runtime,它是 HMR 的客户端(浏览器端 client)用于和开发服务器通信,接收更新的模块。服务端工作就是前面提到的 Webpack hot middleware 的,它会在代码更新编译完成之后通过以 json 格式输出给HMR Runtime 就会更具 json 中描述来动态更新相应的代码。
先来在webpack配置文件中引入
var webpack = require("webpack"); var HotMiddleWareConfig = "webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000" module.exports = { context: __dirname, entry: [ // 添加一个和HotMiddleWare通信的客户端 HotMiddleWareConfig, // 添加web应用入口文件 "./client.js" ], output: { path: __dirname, publicPath: "/", filename: "bundle.js" }, devtool: "#source-map", plugins: [ new webpack.optimize.OccurenceOrderPlugin(), // 在 webpack 插件中引入 webpack.HotModuleReplacementPlugin new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ], };
webpack-hot-middleware example webpack.config.js
在我们的开发环境中是这样配置的。getEntries 是自动根据我们规则获取到入口文件并加上 webpack hot middle 配置。
var webpack = require("webpack"); var path = require("path") var merge = require("webpack-merge") var baseConfig = require("./webpack.base") var getEntries = require("./getEntries") var publicPath = "http://0.0.0.0:7799/dist/"; var hotMiddlewareScript = "webpack-hot-middleware/client?reload=true"; var assetsInsert = require("./assetsInsert") module.exports = merge(baseConfig, { entry: getEntries(hotMiddlewareScript), devtool: "#eval-source-map", output: { filename: "./[name].[hash].js", path: path.resolve("./public/dist"), publicPath: publicPath }, plugins: [ new webpack.DefinePlugin({ "process.env": { NODE_ENV: ""development"" } }), new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin(), new assetsInsert() ] })Express 中的配置
在 Express 的配置主要就4个步骤:
引入 webpack 的配置文件和 生成 webpack 的编译器
将编译器连接至 webpack dev middleware
将编译器连接至 webpack hot middleware
定义 express 配置
var http = require("http"); var express = require("express"); var app = express(); app.use(require("morgan")("short")); // ************************************ // This is the real meat of the example // ************************************ (function() { // Step 1: 引入 webpack 的配置文件和 生成 webpack 的编译器 var webpack = require("webpack"); var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : "./webpack.config"); var compiler = webpack(webpackConfig); // Step 2: 将编译器挂载给 webpack dev middleware app.use(require("webpack-dev-middleware")(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath })); // Step 3: 将编译器挂载给 webpack hot middleware app.use(require("webpack-hot-middleware")(compiler, { log: console.log, path: "/__webpack_hmr", heartbeat: 10 * 1000 })); })(); // 定义 express 配置 app.get("/", function(req, res) { res.sendFile(__dirname + "/index.html"); }); app.get("/multientry", function(req, res) { res.sendFile(__dirname + "/index-multientry.html"); }); if (require.main === module) { var server = http.createServer(app); server.listen(process.env.PORT || 1616, function() { console.log("Listening on %j", server.address()); }); }
webpack-hot-middleware example server.js
区分开发和生产环境要注意的是一定要在定义 express router 前定义 webpack 相关的中间件。还有一点是这里server.js 只是开发环境中使用,在生成环境中我们就不需要再用到它们了。所以在我们实际的使用中需要通过定义环境变量来区分开发和生产环境
var NODE_ENV = process.env.NODE_ENV || "production"; var isDev = NODE_ENV === "development"; if (isDev) { var webpack = require("webpack"), webpackDevMiddleware = require("webpack-dev-middleware"), webpackHotMiddleware = require("webpack-hot-middleware"), webpackDevConfig = require("./build/webpack.config.js"); var compiler = webpack(webpackDevConfig); app.use(webpackDevMiddleware(compiler, { publicPath: webpackDevConfig.output.publicPath, noInfo: true, stats: { colors: true } })); app.use(webpackHotMiddleware(compiler)); routerConfig(app, { dirPath: __dirname + "/server/routes/", map: { "index": "/", "api": "/api/*", "proxy": "/proxy/*" } }); var reload = require("reload"); var http = require("http"); var server = http.createServer(app); reload(server, app); app.use(express.static(path.join(__dirname, "public"))); server.listen(port, function() { console.log("App (dev) is now running on port " + port + "!"); }); } else { routerConfig(app, { dirPath: __dirname + "/server/routes/", map: { "index": "/", "api": "/api/*", "proxy": "/proxy/*" } }); app.use(express.static(path.join(__dirname, "public"))); app.listen(port, function() { console.log("App (dev) is now running on port " + port + "!"); }); }supervisor
以上在前端我们实现了前端文件的热更新,但是我们在修改服务端文件的时候,并不会使Node自动重启,所以我们使用 supervisor 来作为监听文件修改事件来自动重启 Node服务。
supervisor 需要 全局安装
npm install supervisor -g
安装完成之后我们就可以在命令行中使用
我们在 package.json 的 scripts 中写好常用的命令,之后只用 npm run xxx 即可使用
"scripts": { "dev": "export NODE_ENV=development && supervisor -w server,app.js app", "build": "node build/build.js", "start": "node app" },
node-supervisor
supervisor [options]supervisor -w server,app.js app
-w 就是一个 options 配置项,它用于监听指定目录或者文件的变更,可以使用,
分隔,监听多个目录或者文件,这就是监听了 server 目录和根目录的 app.js 到变更之后就会重启我们的 Express 入口文件 app。
getEntries 这个是我们自己的载入入口文件的统一方法,具体内容其实我前面的文章提到过,就是规定好了的,文件夹目录下的main.js就是我们的入口文件,其他全部忽略,原因也说过,这里再说一次,规定死了,简单,方便,利于合作。
var publicPath = "http://0.0.0.0:7799/dist/"; 这里publicPath和大家平时配置Webpack的publicPath 不太一样的原因,是需要Express能够认出绝对地址来,因为你项目是Express大于Webpack的。
routerConfig 这个方法是我们自己的一个方法,内容前面文章提到过,就是我写的一个用来加载所有路由的方法,免得重复写各种引用。npm地址
export NODE_ENV=development 注意这里,windows的环境可能会失败,可以替换成 cross-env NODE_ENV=development
其次说下这么做的原因前面文章也提到了,我司目前前端的整体架构是使用Node做中间层,那么问题就是Node渲染层会高于Webpack层,而且很多时候,不一定使用SPA的方式,要兼容这个架构,所以才需要这些配置。
这个配置也很好解决了我们开发中的几个痛点,一个Node自动重新,一个文件热更新,结合起来,基本不需要自己不停的手动刷新浏览器,而且能保存当前状态,这点很关键,能节省不少时间,提升开发效率。
当然也有痛点,例如要多一个模板文件,而且文件目录要根据规范来,要不是不会渲染的。
最后记得这是一个连续的文章系列,只看这里你不一定能配置成功!!!!文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/80769.html
摘要:在前后端分离的前端项目开发中经常用到。是的一个中间件。即是一个重要的功能。配置先来在配置文件中引入添加一个和通信的客户端添加应用入口文件在插件中引入在我们的开发环境中是这样配置的。 原文链接此文是我同事写的,搭建Express结合Webpack。以下是正文,后面我会附上我的解读 Express 结合 Webpack 实现HMR 本篇文件主要讲结合 Webpack 和 Express 实...
摘要:解析不同文件使用哪些,这个比较简单,很多文章都有,就不多说了,注意的是,这里的可以换成你自己的预编译器,例如等,或者直接用都行,当然还可以用一种通用方法,后面补上。 前情提要 上一篇文章介绍了目前前端比较流行的各种编辑器,以及各种流行的打包方式,最后给了一个Gulp的例子,这个例子还是14年的时候写的,还有一些可以优化的空间,就不讨论了,这篇文章主要讲目前火热的打包构建方式--Webp...
摘要:解析不同文件使用哪些,这个比较简单,很多文章都有,就不多说了,注意的是,这里的可以换成你自己的预编译器,例如等,或者直接用都行,当然还可以用一种通用方法,后面补上。 前情提要 上一篇文章介绍了目前前端比较流行的各种编辑器,以及各种流行的打包方式,最后给了一个Gulp的例子,这个例子还是14年的时候写的,还有一些可以优化的空间,就不讨论了,这篇文章主要讲目前火热的打包构建方式--Webp...
摘要:的最后一个大招就是替换一些传统的服务端语言,例如,,等,在业务层上面使用来开发服务端完全不成问题。更多的的使用细节和技巧建议关注美团博客大搜车论坛下一篇我们开启如何结合和搭建一个开发环境和项目目录 往期回顾 前面2期都讲得是浏览器端的东西比较多,包括Webpack,虽然是Node处理的,但是还是浏览器端用的多,对于现在的前端开发来说,不懂一点服务端的东西,简直没办法活,一般的招聘要求都...
摘要:我觉得这方面的原因是当时对和的依赖,导致大家对的兴趣不弄,错过了最佳时机,这个其实跟百度自己的的技术栈有很大关系。这个阮一峰对于前端构建的变化吐槽过,说新的构建工具就是的构建工具。 文章来源 最近几年,前端发展越来越迅速,各种萌新加入了前端这个大家庭,大有赶IOS、超Android的趋势呀!同时,萌新们提出了各种前端工作问题,除了最基础的html、css、js三板斧之外,最让人头疼的应...
阅读 1609·2021-09-02 15:11
阅读 1954·2019-08-30 14:04
阅读 2537·2019-08-27 10:52
阅读 1556·2019-08-26 11:52
阅读 1156·2019-08-23 15:26
阅读 2586·2019-08-23 15:09
阅读 2571·2019-08-23 12:07
阅读 2203·2019-08-22 18:41