前端自動化構建是當下的熱門,我記得2014年的時候,前端的自動化構建,大可能是用在javascript的合併、壓縮、語法檢查、coffeescript,Sass,LESS轉換上,構建工具也有不少,好比ant,grunt,gulp等,二次封裝的工具也有不少,好比百度的FIS,國外的Yeoman。2016年之後,隨着es6,es7,Node的興起,前端又發生了翻天覆的變化,特別是移動端的H5最爲明顯,之前切個圖,在PC上預覽測試就能夠發佈的時代,在移動端就不靈驗了,在手機端預覽至少要搭建一個http服務器,好比http://192.168.0.2/index.html。在手機端輸入網址不方全,一般會將網址作成一個二維碼,而後用手機掃一下就能夠打開預覽。咱們每改一下樣式,就在手機上點一下刷新或電腦上按一下F5,這在最初的時候,也不以爲有什麼問題,由於拿到我手上的靜態頁,一般由切片的同事作好了兼容性測試,須要一邊刷新瀏覽器,一邊改樣式的機會很少。隨着咱們嘗試用Less,stylus,這樣的css工具,一方面,須要用到gulp這樣的工具在後臺自動監聽咱們的樣式改動,另外一方面,手動刷新的時候,gulp的腳本未必轉換完了。這時候迫切須要瀏覽器自動刷新。javascript
總的來講,需求就兩點,一是須要一個http服務器,來供手機訪問靜態資源,另外一個是監聽代碼的改動並自動刷新瀏覽器。要知足這兩個需求的第三方工具,應當不難找,事實上像fis,yeoman,vuecli這樣的工具應當均可以作到。但是我以爲它們都太複雜了,雖然我只用到其中一點點功能,可是我不得不仔細的通讀他們的文檔,找到本身須要的功能。有時候,官方說三分鐘入門,但是我花三十分鐘了尚未入門。或許我幾天以後,我好不容易入門了,結果周圍同事又給我推薦另外一個工具,說比我手上這好一千倍,因而我又去學另外一個工具。如此,很容易陷入不一樣工具之間的學習。更要命的是,轉了一圈回來,其實我用的那一點功能,用哪個工具都差很少,既不像A同窗說的那麼差勁,也不像B同窗說的那麼好。php
2015年6月份的時候,咱們的項目開始用express+React.js作服務端渲染,Redux作狀態管理。咱們搭建了一套開發框架,之前那些自動化的工具,都不能徹底知足個人需求了。js和css的改動愈來愈頻繁,並且node不像php代碼那樣,改動以後,服務器會自動更新,它須要手動重啓node進程,另外一方面,自動刷新瀏覽器,會致使redux的action日誌看不到。這個時候,瀏覽器的自動刷新已經知足不了咱們的需求。咱們須要瀏覽器在不刷新的狀況下,局部更新我改過的代碼。這也就是「熱替換」(HMR)這個概念的來由。不少新同事搞不清什麼是自動刷新,什麼是熱替換。熱替換聽起來,有點像是ajax的效果,不過,ajax是點擊某個動做或觸發某個事件以後由js腳本觸發,而「熱替換"是在咱們改動了代碼的時候觸發(也就是CTRL+S保存的時候). 自動刷新就是指不用手動去按F5. css
要實現自動刷新和靜態服務器,最簡的就是用webpack-dev-server . 若是以前用過webpack,那麼webpack-dev-server則很容易接受,若是尚未用過webpack,那麼我以爲頗有必要去看看。網上有不少介紹webpack及webpack-dev-server的文章,我以爲要這實現這個需求,只要兩步就能夠:html
1.安裝webpack-dev-server前端
2. 運行webpack-dev-server --inline --hotvue
webpack.config.js的配置:java
var path = require("path"); var webpack = require('webpack'); //var ExtractTextPlugin = require("extract-text-webpack-plugin"); var node_modules_dir = path.resolve(__dirname, 'node_modules'); module.exports = { entry:[ //'webpack-dev-server/client?http://localhost:8081', //'webpack/hot/dev-server', './src/app.jsx','./src/app.css' ], module: { loaders: [{ test: /\.es6|jsx$/, exclude: [node_modules_dir], loaders: ['react-hot','babel-loader'], }, { test:/\.css$/, loaders:['style', 'css'] }] }, output: { path: path.resolve(__dirname, "dist"), publicPath:"/assets/", filename: 'bundle.js' }, resolve: { extensions: ['', '.js','.es6','.jsx'] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }), //new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ] }
經過命令行的方式執行webpack-dev-server , 重點要說的是--hot這個參數,它就是啓動熱替換用的。它會自動給plugins插入new webpack.HotModuleReplacementPlugin() 所以不須要人爲的再配置這個插件了。因此我在webpack.config.js中註釋掉了這一行。 而後entry中也不須要加webpack/hot/dev-server和webpack-dev-server/client,記住:命令行方式運行webpack-dev-server會自動替你完成這些工做。不要人云亦云的去添加這些註釋的內容,我看到甚至還有用express配合webpack-hot-middleware,webpack-dev-middleware 之類的用法,那更加複雜了,對於只想要實現自動刷新和熱替換來講,命令行方式運行,配合 --hot --inline 這兩個參數是最簡單有效的作法。其它複雜的配置和用法,有它的特殊的適用場景,好比同時須要兩個服務器,一個充當數據接口,一個充當靜態文件服務器, 咱們但願webpack-dev-server經過node API的方式運行。這個有點複雜,用到這麼複雜的情形的,通常都是能本身搞定這個配置的。有這方面需求的,參考demo8的代碼。 node
extract-text-webpack-plugin這個插件,它能夠將模塊中的樣式部分提出來,單獨打包成文件,可是它只適用於生產模式。開始我也沒有注意,在開發模式下也用了,還以爲很爽,直到有一次,我發現更改樣式的時候,瀏覽器竟然自動刷新了,而我指望是熱替換。這時我才理解,只適用於生產模式,不是說它在開發模式下,就不生效了,而是它配合 --hot參數的時候,不會有熱替換的效果。react
簡單的一行小字,沒有細看,結果走了不少彎路。俗話說,方向反了,中止就是進步。 對於普通的js模塊來講,熱替換須要本身寫loader插件,若是是react,vue則官方會提供熱替換的loader,好比react的 react-hot-loader 。若是沒有用這些能夠支持熱替換的插件,那麼默認的就是瀏覽器的自動刷新效果。css的話,只要加上css-loader,style-loader就能夠了。最後再補一刀,output:中要配publicPathwebpack
output: { path: path.resolve(__dirname, "dist"), publicPath:"/assets/", filename: 'bundle.js' },
在html中也要寫publickPath的地址:
/assets/這個虛擬目錄中的文件其實是保存在內存中的,這樣就爲模塊的熱替換提供了可能。若是寫成實際的產出目錄,是怎麼也不會看到熱替換的效果的,甚至連自動刷新都不會出現.
源碼地址:https://github.com/bjtqti/how_to_use_webpack/tree/master/demo18
首先看控制檯的提示:
出現這個HMR說明配置方面是對的,可是光有這個還不行,若是模塊沒有熱替換的loader,那麼就會觸發失敗,失敗的結果就是致使瀏覽器刷新。這也是爲何有時候明明出現這個熱替換的標誌了,仍是會出現瀏覽器刷新。若是添加了支持熱替換的loader,那麼當咱們保存更改的時候,瀏覽器只會默默的更新變化區域,而不會產生刷新。同時,控制檯的log也會累積,不會被清空。
辛苦作出來的H5頁面,在電腦上模擬顯示的效果,都未必可靠,最後都須要放到手機上進行真機檢測。經過webpack-dev-server生成的http服務器,能夠實現經過手機訪問。好比電腦的ip是192.168.1.122, 默認狀況下,那麼經過http://191.168.1.122:8080就能夠在手機上打開咱們的H5頁面。若是打不開,請檢查兩個地方:
1. webpack-dev-server 添加 --host 0.0.0.0 參數
2. 保證電腦和手機處於同一個無線網絡,即電腦能夠ping通手機。
在手機上檢測無缺以後,就須要把代碼進行合併,壓縮,添加hash標記,小圖片,字體文件轉base64,提取共公代碼等等. 一方面能夠簡單的使用
webpack -p 也可自行配置webpack.config.js,演示:
plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }), new ExtractTextPlugin('css/[name].css'), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, output: { comments: false }, sourceMap: false }), new webpack.optimize.CommonsChunkPlugin('vendor','js/vendor.js'), new webpack.optimize.OccurenceOrderPlugin(true), new webpack.NoErrorsPlugin() ]
到此,整個構建工做就完成了。
關於webpack及webpack-der-server的教程不少,可是不少文章發佈的較早,不必定適用你如今用的版本。遇到問題的時候,我建議先看看錯誤提示,而後查看官方文檔。先從簡單的用法開始去動手嘗試,必定要嘗試,不要以爲很簡單,只在腦海裏想固然的運行一遍就覺得學會了,俗話說,實踐出真知,一樣的問題,不一樣的環境(windows/mac/node版本...),會有不一樣的狀況,只有本身一一去試過了,遇到問題心中有數,纔不會慌。最後,要把學到的內容結合實際的項目去運用看看,有哪些功能對目前的開發有幫助,哪些功能還不是很瞭解,須要更深刻的學習。遇到實在有本身找不到解決辦法的問題,再去網上查,我的以爲stockoverflow還算比較靠譜。最後,要記得把本身遇到的坑整理成章,分享是一種美德。