首頁  >  文章  >  web前端  >  webpack自動刷新使用詳解

webpack自動刷新使用詳解

php中世界最好的语言
php中世界最好的语言原創
2018-04-28 17:13:572106瀏覽

這次帶給大家webpack自動刷新使用詳解,webpack自動刷新使用的注意事項有哪些,下面就是實戰案例,一起來看一下。

前端需要頻繁的修改js和樣式,且需要根據瀏覽器的頁面效果不斷的做調整;而且往往我們的開發目錄和本地發布目錄不是同一個,修改之後需要發布一下;另外一點就是不是所有的效果都可以直接雙擊頁面就能看到,我們常常需要在本地用nginx建一個站點來觀察(自己電腦上ok了才放到測試環境去)。所以如果要用手工刷新瀏覽器和手動(或點擊)發布,還要啟動站點,確實是個不小的體力活。而這三點webpack可以幫我們做到。

webpack-dev-serverwebpack

是透過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##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;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:webpack-ch2_jb51.rar

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

proxyTable代理跨域使用详解

CSS Modules优雅模式使用

以上是webpack自動刷新使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn