亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Express結合Webpack的全棧自動刷新

2019-11-19 11:29:24
字體:
來源:轉載
供稿:網友

在以前的一篇文章自動刷新 從BrowserSync開始中,我介紹了BrowserSync這樣一個出色的開發工具。通過BrowserSync我感受到了這樣一個理念:如果在一次ctrl + s保存后可以自動刷新,然后立即看到新的頁面效果,那會是很棒的開發體驗。

現在,webpack可以說是最流行的模塊加載器(module bundler)。一方面,它為前端靜態資源的組織和管理提供了相對較完善的解決方案,另一方面,它也很大程度上改變了前端開發的工作流程。在應用了webpack的開發流程中,想要繼續“自動刷新”的爽快體驗,就可能得額外做一些事情。

webpack與自動刷新

本文并不打算介紹webpack,webpack要求靜態資源在被真正拿來訪問之前,都要先完成一次編譯,即運行完成一次webpack命令。因此,自動刷新需要調整到適當的時間點。也就是說,修改了css等源碼并保存后,應該先觸發一次webpack編譯,在編譯完成后,再通知瀏覽器去刷新。

開發Express項目的問題

現在有這樣的一個應用了webpack的Express項目,目錄結構如下:

 

其中,client內是前端的靜態資源文件,比如css、圖片以及瀏覽器內使用的javascript。server內是后端的文件,比如express的routes、views以及其他用node執行的javascript。根目錄的app.js,就是啟動express的入口文件了。

開發的時候我們會怎樣做呢?

先啟動Express服務器,然后在瀏覽器中打開某個頁面,接下來再編輯源文件。那么,問題就來了,比如我編輯.scss源文件,即使我只改了一小點,我也得在命令行里輸入webpack等它編譯完,然后再切到瀏覽器里按一下F5,才能看到修改后的效果。

再比如,我修改了routes里的.js文件想看看結果,我需要到命令行里重啟一次Express服務器,然后同樣切到瀏覽器里按一下F5。

這可真是太費事了。

所以,我們要讓開發過程愉快起來。

改進目標

我們希望的Express&Webpack項目的開發過程是:

  • 如果修改的是client里的css文件(包括.scss等),保存后,瀏覽器不會整頁刷新,新的樣式效果直接更新到頁面內。
  • 如果修改的是client里的javascript文件,保存后,瀏覽器會自動整頁刷新,得到更新后的效果。
  • 如果修改的是server里的文件,保存后,服務器將自動重啟,瀏覽器會在服務器重啟完畢后自動刷新。

經過多次嘗試,我最終得到了一個實現了以上這些目標的項目配置。接下來,本文將說明這個配置是如何做出來的。

從webpack-dev-server開始

首先,webpack已經想到了開發流程中的自動刷新,這就是webpack-dev-server。它是一個靜態資源服務器,只用于開發環境。

一般來說,對于純前端的項目(全部由靜態html文件組成),簡單地在項目根目錄運行webpack-dev-server,然后打開html,修改任意關聯的源文件并保存,webpack編譯就會運行,并在運行完成后通知瀏覽器刷新。

和直接在命令行里運行webpack不同的是,webpack-dev-server會把編譯后的靜態文件全部保存在內存里,而不會寫入到文件目錄內。這樣,少了那個每次都在變的webpack輸出目錄,會不會覺得更清爽呢?

如果在請求某個靜態資源的時候,webpack編譯還沒有運行完畢,webpack-dev-server不會讓這個請求失敗,而是會一直阻塞它,直到webpack編譯完畢。這個對應的效果是,如果你在不恰當的時候刷新了頁面,不會看到錯誤,而是會在等待一段時間后重新看到正常的頁面,就好像“網速很慢”。

webpack-dev-server的功能看上去就是我們需要的,但如何把它加入到包含后端服務器的Express項目里呢?

webpack-dev-middleware和webpack-hot-middleware

Express本質是一系列middleware的集合,因此,適合Express的webpack開發工具是webpack-dev-middlewarewebpack-hot-middleware。

webpack-dev-middleware是一個處理靜態資源的middleware。前面說的webpack-dev-server,實際上是一個小型Express服務器,它也是用webpack-dev-middleware來處理webpack編譯后的輸出。

webpack-hot-middleware是一個結合webpack-dev-middleware使用的middleware,它可以實現瀏覽器的無刷新更新(hot reload)。這也是webpack文檔里常說的HMR(Hot Module Replacement)。

參考webpack-hot-middleware的文檔示例,我們把這2個middleware添加到Express中。

webpack配置文件部分

首先,修改webpack的配置文件(為了方便查看,這里貼出了webpack.config.js的全部代碼):

var webpack = require('webpack');var path = require('path');var publicPath = 'http://localhost:3000/';var hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true';var devConfig = { entry: { page1: ['./client/page1', hotMiddlewareScript], page2: ['./client/page2', hotMiddlewareScript] }, output: { filename: './[name]/bundle.js', path: path.resolve('./public'), publicPath: publicPath }, devtool: 'source-map', module: { loaders: [{  test: //.(png|jpg)$/,  loader: 'url?limit=8192&context=client&name=[path][name].[ext]' }, {  test: //.scss$/,  loader: 'style!css?sourceMap!resolve-url!sass?sourceMap' }] }, plugins: [ new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ]};module.exports = devConfig;

這是一個包含多個entry的較復雜的例子。其中和webpack-hot-middleware有關的有兩處。一是plugins的位置,增加3個插件,二是entry的位置,每一個entry后都增加一個hotMiddlewareScript。

hotMiddlewareScript的值是webpack-hot-middleware/client?reload=true,其中?后的內容相當于為webpack-hot-middleware設置參數,這里reload=true的意思是,如果碰到不能hot reload的情況,就整頁刷新。

在這個配置文件中,還有一個要點是publicPath不是/這樣的值,而是http://localhost:3000/這樣的絕對地址。這是因為,在使用?sourceMap的時候,style-loader會把css的引入做成這樣:

這種blob的形式可能會使得css里的url()引用的圖片失效,因此建議用帶http的絕對地址(這也只有開發環境會用到)。有關這個問題的詳情,你可以查看github上的issue。

Express啟動文件部分

接下來是Express啟動文件內添加以下代碼:

var webpack = require('webpack'), webpackDevMiddleware = require('webpack-dev-middleware'), webpackHotMiddleware = require('webpack-hot-middleware'), webpackDevConfig = require('./webpack.config.js');var compiler = webpack(webpackDevConfig);// attach to the compiler & the serverapp.use(webpackDevMiddleware(compiler, { // public path should be the same with webpack config publicPath: webpackDevConfig.output.publicPath, noInfo: true, stats: { colors: true }}));app.use(webpackHotMiddleware(compiler));

以上這段代碼應該位于Express的routes代碼之前。其中,webpack-dev-middleware配置的publicPath應該和webpack配置文件里的一致。

webpack-dev-middleware和webpack-hot-middleware的靜態資源服務只用于開發環境。到了線上環境,應該使用express.static()。

到此,client部分的目標就完成了?,F在到網頁里打開控制臺,應該可以看到[HMR] connected的提示。這個項目中我只要求css使用HMR,如果你希望javascript也使用HMR,一個簡單的做法是在entry文件內添加以下代碼:

if(module.hot) { module.hot.accept();}

這樣,與這個entry相關的所有.js文件都會使用hot reload的形式。關于這一點的更多詳情,請參考hot module replacement。

接下來是server部分。

reload和supervisor

server部分的自動刷新,會面臨一個問題:自動刷新的消息通知依靠的是瀏覽器和服務器之間的web socket連接,但在server部分修改代碼的話,一般都要重啟服務器來使變更生效(比如修改routes),這就會斷開web socket連接。

所以,這需要一個變通的策略:瀏覽器這邊增加一個對web socket斷開的處理,如果web socket斷開,則開啟一個稍長于服務器重啟時間的定時任務(setTimeout),相當于等到服務器重啟完畢后,再進行一次整頁刷新。

reload是一個應用此策略的組件,它可以幫我們處理服務器重啟時的瀏覽器刷新。

現在,還差一個監聽server文件,如果有變更就重啟服務器的組件。參考reload的推薦,我們選用supervisor。

下面將reload和supervisor引入到Express項目內。

監聽文件以重啟服務器

通過以下代碼安裝supervisor(是的,必須-g):

npm install supervisor -g

然后,在package.json里設置新的scripts:

"scripts": { "start": "cross-env NODE_ENV=dev supervisor -i client app"}

這里的主要變化是從node app改為supervisor -i client app。其中-i等于--ignore,這里表示忽略client,顯然,我們可不希望在改前端代碼的時候服務器也重啟。

這里的cross-env也是一個npm組件,它可以處理windows和其他Unix系統在設置環境變量的寫法上不一致的問題。

把會重啟的服務器和瀏覽器關聯起來

把Express啟動文件最后的部分做這樣的修改:

var reload = require('reload');var http = require('http');var server = http.createServer(app);reload(server, app);server.listen(3000, function(){ console.log('App (dev) is now running on port 3000!');});

Express啟動文件的最后一般是app.listen()。參照reload的說明,需要這樣用http再增加一層服務。

然后,再到Express的視圖文件views里,在底部增加一個<script>:

<% if (env !== "production") { %> <script src="/reload/reload.js"></script><% } %>

所有的views都需要這樣一段代碼,因此最好借助模板引擎用include或extends的方式添加到公共位置。

這里的reload.js和前面webpack的開發環境bundle.js并不沖突,它們一個負責前端源文件變更后進行編譯和刷新,另一個負責在服務器發生重啟時觸發延時刷新。

到此,server也完成了?,F在,修改項目內的任意源文件,按下ctrl + s,瀏覽器里的頁面都會對應地做一次“適當”的刷新。

完整示例

完整示例已經提交到github:express-webpack-full-live-reload-example

效果如下:

附加的可選方案

前面說的server部分,分為views和routes,如果只修改views,那么服務器并不需要重啟,直接刷新瀏覽器就可以了。

針對這樣的開發情景,可以把views文件的修改刷新變得更快。這時候我們不用reload和supervisor,改為用browsersync,在Express的啟動文件內做如下修改:

var bs = require('browser-sync').create();app.listen(3000, function(){ bs.init({ open: false, ui: false, notify: false, proxy: 'localhost:3000', files: ['./server/views/**'], port: 8080 }); console.log('App (dev) is going to be running on port 8080 (by browsersync).');});

然后,使用browsersync提供的新的訪問地址就可以了。這樣,修改views(html)的時候,由browsersync幫忙直接刷新,修改css和javascript的時候繼續由webpack的middleware來執行編譯和刷新。

結語

有了webpack后,沒有自動刷新怎么干活?

說起來,能做出像這樣的全棧刷新,大概也是得益于Express和Webpack都是javascript,可以很容易地結合、協作的緣故吧。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久好看免费视频| 91久久精品在线| 色婷婷综合成人| 亚洲精品免费在线视频| 欧美中文在线观看国产| 国产精品久久久久福利| 亚洲xxxx妇黄裸体| 久久精品91久久久久久再现| 欧美裸体xxxx极品少妇软件| 欧美极品少妇xxxxx| 精品视频在线播放| 国产一区二区三区在线观看视频| 国产在线视频2019最新视频| 国产成人精品网站| 亚洲综合大片69999| 在线看欧美日韩| 亚洲最大的网站| 92福利视频午夜1000合集在线观看| 久久99久久久久久久噜噜| 久久亚洲影音av资源网| 日韩欧美国产网站| 在线播放亚洲激情| 久久精品99国产精品酒店日本| 国产精品白丝av嫩草影院| 色妞色视频一区二区三区四区| 国产日韩欧美在线看| 成人精品视频久久久久| 久久精品一偷一偷国产| 亚洲国产精品推荐| 欧美性xxxx极品高清hd直播| 亚洲开心激情网| 国产成人精品日本亚洲专区61| 欧美多人爱爱视频网站| 亚洲aa在线观看| 国内精品模特av私拍在线观看| 欧美精品久久久久久久免费观看| 久久男人资源视频| 国产一区二区av| 亚洲精品成人免费| 亚洲成人久久电影| 91在线免费观看网站| 亚洲精品日韩在线| 国产成人一区二区三区小说| 最好看的2019年中文视频| 伊人伊成久久人综合网小说| 亚洲精品美女网站| 国产在线播放91| 中文字幕亚洲综合久久| 日本精品免费观看| 精品视频久久久| 国产精品一区二区三区在线播放| 久久精品美女视频网站| 国产欧美日韩中文字幕| 成人午夜在线视频一区| 国产亚洲精品一区二区| 精品福利视频导航| 日韩av免费在线观看| 91精品久久久久久久久久入口| 久久久精品久久久| 久久亚洲综合国产精品99麻豆精品福利| 久久免费视频这里只有精品| 亚洲一级一级97网| 亚洲欧洲成视频免费观看| 97精品久久久| 国产精品久久婷婷六月丁香| 国产精品久久久精品| 欧美精品性视频| 国产精品va在线播放我和闺蜜| 久久精品99久久久久久久久| 亚洲视频视频在线| 久久中国妇女中文字幕| 美日韩精品视频免费看| 亚洲天堂第一页| 第一福利永久视频精品| 成人福利视频在线观看| 欧美专区在线观看| 日韩欧美成人区| 欧美国产日韩一区二区| 一个人www欧美| 91亚洲国产成人精品性色| 欧美怡红院视频一区二区三区| 国产综合在线视频| 狠狠躁夜夜躁人人躁婷婷91| 亚洲自拍高清视频网站| 欧美色视频日本高清在线观看| 国产精品视频男人的天堂| 疯狂做受xxxx欧美肥白少妇| 成人免费午夜电影| 国产成人av网| 欧美日韩在线视频首页| 国模精品系列视频| 日韩中文字幕在线精品| 久久国产精品影视| 亚洲第一二三四五区| 性欧美xxxx视频在线观看| 久久综合国产精品台湾中文娱乐网| 久久香蕉频线观| 国产欧美精品xxxx另类| 国产精品视频久久久久| 不用播放器成人网| 亚洲伦理中文字幕| 91精品国产一区| 久久精品国产精品| 欧美在线观看一区二区三区| 国产精品男人爽免费视频1| 欧美日韩另类字幕中文| 国产丝袜一区二区三区| 午夜精品一区二区三区av| 国产精品xxx视频| 欧美日韩在线视频一区| 亚洲a级在线播放观看| 国产香蕉精品视频一区二区三区| 国产亚洲在线播放| 国产精品美女久久久免费| 国产欧美日韩免费| 亚洲国产欧美精品| 国产精品美乳在线观看| 亚洲色图欧美制服丝袜另类第一页| 国产精品视频一| 亚洲深夜福利在线| 人人做人人澡人人爽欧美| 中文字幕亚洲字幕| 亚洲福利视频在线| 亚洲毛片在线观看.| 成人久久久久久久| 91国产高清在线| 色青青草原桃花久久综合| 欧美裸体男粗大视频在线观看| 久久久欧美一区二区| 日本免费久久高清视频| 久久精品视频在线观看| 91九色精品视频| 国模精品视频一区二区三区| 欧美在线观看一区二区三区| 亚洲综合日韩在线| 国产精品狠色婷| 国产精品伦子伦免费视频| 欧美午夜精品久久久久久久| 国产精品久久电影观看| 国产精品∨欧美精品v日韩精品| 久久精品青青大伊人av| 午夜精品蜜臀一区二区三区免费| 亚洲激情国产精品| 18一19gay欧美视频网站| 国产精品三级久久久久久电影| 欲色天天网综合久久| 欧美极品美女视频网站在线观看免费| 中文字幕日韩在线播放| 国产精品久久久久久久久久久久久久| 91免费欧美精品| 国产一区二区三区精品久久久| 亚洲成人激情图| 日本免费久久高清视频| 久久亚洲精品网站| 国产不卡一区二区在线播放| 欧美在线一级视频| 欧美视频在线看| 亚洲最大福利网| 欧美大片va欧美在线播放| 欧美精品手机在线| 欧美性猛交xxxx乱大交极品| 欧美xxxx18性欧美| 欧美一区二区三区免费视| 日本久久久久久久久久久|