您好,登錄后才能下訂單哦!
前端需要頻繁的修改js和樣式,且需要根據(jù)瀏覽器的頁面效果不斷的做調(diào)整;而且往往我們的開發(fā)目錄和本地發(fā)布目錄不是同一個,修改之后需要發(fā)布一下;另外一點(diǎn)就是并不是所有的效果都可以直接雙擊頁面就能看到,我們常常需要在本地用nginx建一個站點(diǎn)來觀察(自己電腦上ok了才放到測試環(huán)境去)。所以如果要用手工刷新瀏覽器和手動(或點(diǎn)擊)發(fā)布,還要啟動站點(diǎn),確實(shí)是個不小的體力活。而這三點(diǎn)webpack可以幫我們做到。
webpack-dev-serverwebpack
是通過webpack-dev-server(WDS)來實(shí)現(xiàn)自動刷新。WDS是一個運(yùn)行在內(nèi)存中的開發(fā)服務(wù)器(一個express)。啟動之后,它會檢測文件是否發(fā)生改變并再自動編譯一次。
1.安裝
npm install webpack-dev-server --save-dev
先通過npm將其安裝到開發(fā)目錄。安裝完成之后會在node_modules/bin下找到。
2.npm啟動
然后修改package.json:(基于上一節(jié))
"scripts": { "start": "webpack-dev-server --env development", "build": "webpack --env production" }
現(xiàn)在就可以通過npm run start 或者 npm start來啟動了。
啟動之后,可以看到Project is running at http://localhost:8080 上面。打開頁面
說明WDS已經(jīng)幫我們自動建了一個站點(diǎn).我們修改component.js ,cmd中會出現(xiàn)編譯,頁面會自動刷新。
3.直接啟動
官網(wǎng)介紹可以直接通過下面的命令啟動WDS。
webpack-dev-server --env development
但會出現(xiàn)webpack-dev-server --env development 不是內(nèi)部命令的提示,這種問題都是環(huán)境變量的問題,將你開發(fā)的bin目錄設(shè)置到環(huán)境變量中即可,比如我的目錄是‘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端口占用
如果默認(rèn)的8080端口占用,WDS會換一個。比如用nginx先發(fā)布一個。
server{ listen 8080; location / { root E:/Html5/build; index index.html index.htm; } }
再啟動WDS:
端口切到了8081。也可以手動配置端口:
devServer:{ //... port: 9000 }
nodemon 自動啟動
WDS是監(jiān)視開發(fā)文件的,webpack.config.js改變不會引起自動啟動。所以我們需要nodemon去做這件事情。
npm install nodemon --save-dev
先安裝在開發(fā)目錄,然后修改package.json:
"scripts": { "start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --env development\"", "build": "webpack --env production" },
等于讓nodemon去監(jiān)視webpack.config.js,變化了就去啟動它。
這樣就你可以讓你的雙手專心的開發(fā)了。
代理
不過有一點(diǎn)疑問,就是WDS這個站點(diǎn)的替代性,因為我們自己部署的nginx有一些api的代理。如果掛在WDS的這個默認(rèn)站點(diǎn)上自然是無法訪問的。換句話說可否給WDS配置一個刷新路徑。如果文件改變?nèi)ニ⑿轮付ǖ牡刂?,或者讓我去配個代理。既然它本身是一個http服務(wù)器,肯定也有代理的功能。搜了下果然有: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/,并將其從原地址中刪掉,這樣就可以自己實(shí)現(xiàn)代理了。皆大歡喜!WDS是通過http-proxy-middleware來實(shí)現(xiàn)代理。更多參考:http://webpack.github.io/docs/webpack-dev-server.html;https://github.com/chimurai/http-proxy-middleware#options
but,這種刷新是怎么實(shí)現(xiàn)的呢?因為頁面上沒有嵌入什么別的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來監(jiān)視文件變化,server的內(nèi)部維護(hù)的有一個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的時候觸發(fā)一個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通知到客戶端,這樣就實(shí)現(xiàn)了刷新。之前WebSocket的第三方只用過socket.io,看起來sockjs也蠻好用的。不必外帶一個js,在主js里面就可以寫了。
小結(jié):效率提高的一方面是將一些機(jī)械的重復(fù)性流程或動作自動化起來。WDS和nodemon就是兩個為你干活的小弟。
demo:webpack-ch3_jb51.rar
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。