前端需要频繁的修改js和样式,且需要根据浏览器的页面效果不断的做调整;而且往往我们的开发目录和本地发布目录不是同一个,修改之后需要发布一下;另外一点就是并不是所有的效果都可以直接双击页面就能看到,我们常常需要在本地用nginx建一个站点来观察(自己电脑上ok了才放到测试环境去)。所以如果要用手工刷新浏览器和手动(或点击)发布,还要启动站点,确实是个不小的体力活。而这三点webpack可以帮我们做到。

webpack-dev-server

webpack是通过webpack-dev-server(WDS)来实现自动刷新。WDS是一个运行在内存中的开发服务器(一个express)。启动之后,它会检测文件是否发生改变并再自动编译一次。

1.安装

npm install webpack-dev-server --save-dev

先通过npm将其安装到开发目录。安装完成之后会在node_modules/bin下找到。

2.npm启动

然后修改package.json:(基于上一节)

 "scripts": {
"start": "webpack-dev-server --env development",
"build": "webpack --env production"
}

现在就可以通过npm run start 或者 npm start来启动了。

启动之后,可以看到Project is running at http://localhost:8080 上面。打开页面

说明WDS已经帮我们自动建了一个站点.我们修改component.js ,cmd中会出现编译,页面会自动刷新。

3.直接启动

官网介绍可以直接通过下面的命令启动WDS。

webpack-dev-server --env development

但会出现webpack-dev-server --env development 不是内部命令的提示,这种问题都是环境变量的问题,将你开发的bin目录设置到环境变量中即可,比如我的目录是‘E:\Html5\node_modules\.bin’,就加上分号写在后面。

C:\Users\Administrator.9BBOFZPACSCXLG2\AppData\Roaming\npm;C:\Program Files (x86)\Microsoft VS Code\bin;E:\Html5\node_modules\.bin

4.8080端口占用

如果默认的8080端口占用,WDS会换一个。比如用nginx先发布一个。

   server{
listen 8080;
location / {
root E:/Html5/build;
index index.html index.htm;
}
}

再启动WDS:

端口切到了8081。也可以手动配置端口:

 devServer:{
//...
port: 9000
}

nodemon 自动启动

WDS是监视开发文件的,webpack.config.js改变不会引起自动启动。所以我们需要nodemon去做这件事情。

npm install nodemon --save-dev

先安装在开发目录,然后修改package.json:

 "scripts": {
"start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --env development\"",
"build": "webpack --env production"
},

等于让nodemon去监视webpack.config.js,变化了就去启动它。

这样就你可以让你的双手专心的开发了。

代理

不过有一点疑问,就是WDS这个站点的替代性,因为我们自己部署的nginx有一些api的代理。如果挂在WDS的这个默认站点上自然是无法访问的。换句话说可否给WDS配置一个刷新路径。如果文件改变去刷新指定的地址,或者让我去配个代理。既然它本身是一个http服务器,肯定也有代理的功能。搜了下果然有:https://github.com/webpack/webpack-dev-server/tree/master/examples/proxy-advanced

module.exports = {
context: __dirname,
entry: "./app.js",
devServer: {
proxy: {
"/api": {
target: "http://jsonplaceholder.typicode.com/",
changeOrigin: true,
pathRewrite: {
"^/api": ""
},
bypass: function(req) {
if(req.url === "/api/nope") {
return "/bypass.html";
}
}
}
}
}
}

即将api这个字段替换成http://jsonplaceholder.typicode.com/,并将其从原地址中删掉,这样就可以自己实现代理了。皆大欢喜!WDS是通过 http-proxy-middleware 来实现代理。更多参考:http://webpack.github.io/docs/webpack-dev-server.html#bypass-the-proxy;https://github.com/chimurai/http-proxy-middleware#options

but,这种刷新是怎么实现的呢?因为页面上没有嵌入什么别的js,去翻原码 web-dev-server/server.js中有这么一段:

Server.prototype._watch = function(path) {
const watcher = chokidar.watch(path).on("change", function() {
this.sockWrite(this.sockets, "content-changed");
}.bind(this)) this.contentBaseWatchers.push(watcher);
}

chokidar来监视文件变化,server的内部维护的有一个socket集合:

Server.prototype.sockWrite = function(sockets, type, data) {
sockets.forEach(function(sock) {
sock.write(JSON.stringify({
type: type,
data: data
}));
});
}

sock是一个sockjs对象。https://github.com/sockjs/sockjs-client,从http://localhost:8080/webpack-dev-server/页面来看,sockjs是用来通信记录日志的。

var onSocketMsg = {
hot: function() {
hot = true;
log("info", "[WDS] Hot Module Replacement enabled.");
},
invalid: function() {
log("info", "[WDS] App updated. Recompiling...");
sendMsg("Invalid");
},
hash: function(hash) {
currentHash = hash;
},
...
}

我们在看app.js,其中有一个OnSocketMsg 对象。

var onSocketMsg = {
hot: function() {
hot = true;
log("info", "[WDS] Hot Module Replacement enabled.");
},
invalid: function() {
log("info", "[WDS] App updated. Recompiling...");
sendMsg("Invalid");
},
hash: function(hash) {
currentHash = hash;
},
"still-ok": function() {
log("info", "[WDS] Nothing changed.")
if(useWarningOverlay || useErrorOverlay) overlay.clear();
sendMsg("StillOk");
},
"log-level": function(level) {
logLevel = level;
},
"overlay": function(overlay) {
if(typeof document !== "undefined") {
if(typeof(overlay) === "boolean") {
useWarningOverlay = overlay;
useErrorOverlay = overlay;
} else if(overlay) {
useWarningOverlay = overlay.warnings;
useErrorOverlay = overlay.errors;
}
}
},
ok: function() {
sendMsg("Ok");
if(useWarningOverlay || useErrorOverlay) overlay.clear();
if(initial) return initial = false;
reloadApp();
},
"content-changed": function() {
log("info", "[WDS] Content base changed. Reloading...")
self.location.reload();
},
warnings: function(warnings) {
log("info", "[WDS] Warnings while compiling.");
var strippedWarnings = warnings.map(function(warning) {
return stripAnsi(warning);
});
sendMsg("Warnings", strippedWarnings);
for(var i = 0; i < strippedWarnings.length; i++)
console.warn(strippedWarnings[i]);
if(useWarningOverlay) overlay.showMessage(warnings); if(initial) return initial = false;
reloadApp();
},
errors: function(errors) {
log("info", "[WDS] Errors while compiling. Reload prevented.");
var strippedErrors = errors.map(function(error) {
return stripAnsi(error);
});
sendMsg("Errors", strippedErrors);
for(var i = 0; i < strippedErrors.length; i++)
console.error(strippedErrors[i]);
if(useErrorOverlay) overlay.showMessage(errors);
},
close: function() {
log("error", "[WDS] Disconnected!");
sendMsg("Close");
}
};

ok的时候触发一个reloadApp

function reloadApp() {
if(hot) {
log("info", "[WDS] App hot update...");
var hotEmitter = __webpack_require__("./node_modules/webpack/hot/emitter.js");
hotEmitter.emit("webpackHotUpdate", currentHash);
if(typeof self !== "undefined") {
// broadcast update to window
self.postMessage("webpackHotUpdate" + currentHash, "*");
}
} else {
log("info", "[WDS] App updated. Reloading...");
self.location.reload();
}
}

也就是说WDS先检测文件是否变化,然后通过sockjs通知到客户端,这样就实现了刷新。之前WebSocket的第三方只用过socket.io,看起来sockjs也蛮好用的。不必外带一个js,在主js里面就可以写了。

小结:效率提高的一方面是将一些机械的重复性流程或动作自动化起来。WDS和nodemon就是两个为你干活的小弟。

demo:http://files.cnblogs.com/files/stoneniqiu/webpack-ch2.zip

【webpack】-- 自动刷新的更多相关文章

  1. 简单配置webpack自动刷新浏览器

    文档地址  http://webpack.github.io/docs/usage.html 首先全局安装webpack(我这里使用的是淘宝的cnpm) cnpm install webpack 检查 ...

  2. 修复webpack自动刷新页面慢的问题

    新建.babelrc文件,配置如下 { "presets": [ "es2015" ], "ignore":[ "react-ro ...

  3. webpack学习(三)之web-dev-server不能自动刷新问题

    使用webpack-dev-server中遇到不能浏览器无法自动刷新的问题:寻找多方答案后明白了一些: 下面有一些需要注意的点: 1.webpack-dev-server并不能读取你的webpack. ...

  4. 【webpack】-- 自动刷新与解析

    前端需要频繁的修改js和样式,且需要根据浏览器的页面效果不断的做调整:而且往往我们的开发目录和本地发布目录不是同一个,修改之后需要发布一下:另外一点就是并不是所有的效果都可以直接双击页面就能看到,我们 ...

  5. webpack热加载:修改文件自动刷新浏览器并更新

    概述 之前用react脚手架,觉得那种修改了能立即自动刷新浏览器并更新的功能实在非常人性化,所以想在开发其它项目的时候能用上.于是查了一些资料记录在此,供以后开发时参考,相信对其他人也有用. 其实代码 ...

  6. Webpack 2 视频教程 007 - 配置 WDS 进行浏览器自动刷新

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  7. webpack 实现自动刷新,复制文件,实现开发环境和发布环境

    webpack例子:https://github.com/Aquarius1993/webpackDemo 安装: webpack , webpack-dev-server 1.如何在使用webpac ...

  8. webpack 之 webpack-dev-server自动刷新

    watch 首先介绍watch选项,参考这里.可实现相关源文件改变后自动更新bundle.js文件的功能.在配置文件中添加 watch:true 或执行 webpack -w,即可开启watch功能: ...

  9. 解决 webpack-dev-server 不能自动刷新的问题

    原文发表于我的技术博客 此文主要帮助大家解决 webpack-dev-server 启动后修改源文件浏览器不能自动刷新的问题. 原文发表于我的技术博客 1. webpack 不能热加载的问题 主要的问 ...

随机推荐

  1. 3.IP协议,ARP协议,RARP协议

    1.IP协议 IP协议是TCP/IP协议的核心,所有的TCP,UDP,IMCP,IGCP的数据都以IP数据格式传输.要注意的是,IP不是可靠的协议,这是说,IP协议没有提供一种数据未传达以后的处理机制 ...

  2. robotium从入门到放弃 一 测试开发环境搭建

    1.JDK的安装及环境变量的配置    配置JAVA的运行环境,添加完环境变量后,可以打开Windows命令处理程序窗口,通过执行命令java -version验证环境变量是否添加成功.如果添加成功会 ...

  3. C#子窗口与父窗口交互(使用委托和事件)

    目标:在子窗口Form2上单击按钮时向Form1传递一组自定义参数,并显示在父窗口Form1上. 方法:有很多方法,这里只介绍委托和事件的实现方式. 思路:Form2中定义事件,Form1创建Form ...

  4. xml文档PHP查询代码(学习使用)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " http://www.w3.org ...

  5. ViewSwitcher的功能与用法

    ViewSwtcher代表了视图切换组件,它本身继承了FrameLayout,因此可以将多个View层叠在一起,每次只显示一个组件.当程序控制从一个View切换到另一个View时,ViewSwitch ...

  6. RAC 开启gsd和oc4j服务

    Oracle 11g RAC中,发现oc4j以及gsd服务都处于offline状态,这是Oracle 11g RAC默认情形.即便如此,并不影响数据库的使用,因为 oc4j 是用于WLM 的一个资源, ...

  7. 对于python的__name__="__main__"的含义的理解

    学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码,可能很多新手一开始学习的时候都比较疑惑,python 中__name__ = '__main ...

  8. [2017.02.04] C++学习记录(1)

    编编程语言的目的是帮助程序员以代码的形式表述ideas.编程语言一方面为程序员提供一组关于可以做什么的抽象,另一方面为程序员提供可以被机器执行的轮子.C++编程语言,支持4种编程范式:过程式(Proc ...

  9. [转载] ping和telnet的区别

    转载自:http://www.cnblogs.com/Jtianlin/p/4045021.html windown7下打开telnet功能: 控制面板 --- > 程序(小图标下直接到[程序和 ...

  10. WebForm 全局对象、commend

    Repeater的增删改 内置对象:页面之间的数据交互为什么要用这些玩意? HTTP的无状态性 Response:响应请求 Request:获取请求 Cookies:保存登录状态----------- ...