咱們的目標是利用webpack搭建一個基於react + react-router +dva + es6 + less + antd用於中後臺開發的腳手架,同窗們可能會說社區裏那麼多優秀的腳手架爲何還要本身搭,並且網絡上這類文章也很是的多,沒有再重複寫的必要,可是對我而言,分享也是再次學習的過程,只有本身動手實現一遍纔會使印象更加深入,總的來講基本秉持一個理念:在學習中分享,在分享中學習。javascript
新建index.js和index.html文件:css
安裝webpackhtml
新建一個build文件夾存放wbepack配置文件java
webpack.dev.js,並書寫基本的配置(https://github.com/LuoShengMen/React-Whole-barrels/commit/c39b7e9fb67326d0afdda408a600f0a88beca946)react
package.json更改webpack
既然要使用react和es6,babel的配置是必不可少的git
擴展:若是是開發工具庫,想要實現按需替換,可使用下面下面兩個工具來實現
@babel/plugin-transform-runtime避免 polyfill 污染全局變量,減少打包體積,所以更適合做爲開發工具庫
@babel/runtime-corejs2做爲生產環境依賴,約等於@babel/runtime + babel-polyfill,使用了@babel/runtime-corejs2,就無需再使用@babel/runtime了es6
.babelrc文件github
1.解決:Support for the experimental syntax 'classProperties' isn't currently enabled 問題,
npm i -D @babel/plugin-proposal-class-properties,並在plugins中配置。
2.useBuiltIns 和 transform-runtime 不能同時使用,若是使用transform-runtime就不要配useBuiltInsor,通常獨立的類庫項目才用transform-runtime,出處(https://segmentfault.com/q/1010000018937075/)web
更改webpack.dev.js
安裝react、react-dom、react-router,並書寫代碼
這部分代碼較多,能夠在github上查看src的代碼(https://github.com/LuoShengMen/React-Whole-barrels/commit/55a0a0efdf5f581886a303326259fa9b2ff88444)
書寫完成上述代碼運行npm start後,打開index.html你會發現沒有任何內容,此時咱們須要配置一個簡單的WEB服務器,指向index.html。
運行npm start命令,既能夠看到咱們的代碼內容。dev更多配置請看這裏(https://github.com/LuoShengMen/StudyNotes/issues/535)
到目前爲止,咱們會發現都須要手動都將index.html放到dist文件夾中,並手動引入bundle.js.這個問題能夠經過html-webpack-plugin解決。
引入html-webpack-plugin後,在plugins生成一個實例,HtmlWebpackPlugin能夠接受一個參數做爲模版文件,打包結束後自動生成一個以參數爲模版的html文件。並把打包生成的js文件自動引入到html文件中。clean-webpack-plugin能夠實如今每次打包以前都把上一次的打包文件清空,這樣避免了冗餘文件的存在,用法也是直接在plugins裏面生成一個實例.
更改webpack.dev.js
樣式使用less預處理器,那麼就須要使用less,less-loader,css-loader,style-loader等
更改webpack.dev.js配置
postcss.config.js
安裝file-loader和url-loader
filr-loader幫助咱們作兩件事情:
1.當遇到圖片文件時會將其打包移動到dist目錄下
2.接下來會得到圖片模塊的地址,並將地址返回到引入模塊到變量之中
url-loader基本上能夠實現file-loader的功能,可是有一區別就是通過url-laoder打包後的dist文件下是不存在image文件的,這是由於url-loader會把圖片轉換成base64的字符串直接放在bundle.js裏面。
好處:直接將圖片打包到js裏,不用額外到請求圖片,省了http請求
壞處:若是遇到打包到文件很是大,那麼加載會加載很長時間,影響體驗
所以咱們能夠這樣配置webpack.dev.js
模塊熱替換也稱爲HMR,代碼更新時只會更新被修改部分都顯示。有以下有點
針對於樣式調試更加方便
只會更新被修改代碼的那部分顯示,提高開發效率
保留在徹底從新加載頁面時丟失的應用程序狀態。
HMR配置有兩種方式,一種cli方式,一種Node.js API方式,咱們這裏採用第二種方式,若是想了解兩種HMR的實現以及HMR實現原理能夠看這裏((https://github.com/LuoShengMen/StudyNotes/issues/492))。
咱們經過在自定義開發服務下,使用插件webpack-dev-middleware和webpack-hot-middleware配合實現HMR
新建dev-server.js
更改webpack.dev.js,添加以下內容:
webpack-hot-middleware更多配置在這裏(https://github.com/LuoShengMen/StudyNotes/issues/492)
修改啓動命令:
安裝antd後便可使用and-design裏面的ui組件。使用babel-plugin-import來實現按需加載的效果
.babelrc
成功安裝後改寫index.js和並新建router.js
這裏的代碼量有點多就不一一列出,能夠在github上面查看(https://github.com/LuoShengMen/React-Whole-barrels/commit/4dd8a5866760a2727acc95854cc6ab80b48d845d)
在使用react-router的過程當中你可能會出現這樣的問題,點擊刷新後報錯 or Cannot GET,解決方案有兩個。
1.用的 BrowserRouter 改成 HashRouter 便可。2.devServer 中必須設置 historyApiFallback: true
因爲咱們使用的自定義服務,那麼咱們可使用connect-history-api-fallback來實現和historyApiFallback相同的功能。具體實現看代碼(https://github.com/LuoShengMen/React-Whole-barrels/commit/5b3c332136b852ac836dfe2da2c647bf96315911)
CDN經過將資源部署到世界各地,使得用戶能夠就近訪問資源,加快訪問速度。若是咱們把網頁的靜態資源上傳到CDN服務上,在訪問這些資源時,publicPath填寫的就是CDN提供URL
咱們當前用/,相對於當前路徑,是由於咱們的資源在同一文件夾下。》》
webpack.dev.js
sourceMap本質上是一種映射關係,打包出來的js文件中的代碼能夠映射到代碼文件的具體位置,這種映射關係會幫助咱們直接找到在源代碼中的錯誤。能夠直接在devtool中使用.合理的使用source-map能夠幫助咱們提升開發效率,更快的定位到錯誤位置。
生產環境和開發環境的devtool配置是不一樣的。咱們能夠在webpack.dev.js中添加devtool。
到目前爲止咱們配置的都是開發環境的webpack,開發環境(development)和生產環境(production)的構建目標差別很大,而在生產環境中,咱們的目標則轉向於關注更小的 bundle,更輕量的 source map,以及更優化的資源,以改善加載時間.
新建webpack.prod.js
添加打包腳本,
執行npm run build後,你會發現dist文件夾下已經生成一系列文件。你會發現生產環境下的配置和開發環境下的配置有不少相同,接下來咱們會對webpack配置進行優化。
webpack.dev.js和webpack.prod.js中有不少相同對配置,咱們能夠將公共配置提取出來,再使用webpack-merge來將不一樣環境下的配置合併起來。
webpack配置文件更改
webpack.dev.js
webpack.prod.js
webpack.common.js
具體的能夠看這裏。(https://github.com/LuoShengMen/React-Whole-barrels/commit/b1412d2debdcbd6f61819f33b2969e39014c5bb2)
想要分開打包咱們的css文件,須要使用mini-css-extract-plugin這個插件,可是這個插件目前還不支持HMR,爲了避免影響開發效率,所以就在生成環境下使用該插件。
optimize-css-assets-webpack-plugin 這個插件能夠幫助咱們把相同的樣式合併。
css-split-webpack-plugin插件能夠幫咱們把過大的css文件拆分
修改webpack.prod.js,並同步修改webpack.common.js、webpack.dev.js 看這裏
爲了解決瀏覽器文件緩存問題,例如:代碼更新後,文件名稱未改變,瀏覽器非強制刷新後,瀏覽器去請求文件時認爲文件名稱未改變而直接從緩存中讀取不去從新請求。咱們能夠在webpack.prod.js輸出文件名稱中添加hash值.
使用HashedModuleIdsPlugin的緣由是能夠當更改某一個文件時,只改變這一個文件的hash值,而不是全部的文件都改變。
運行npm run build命令後,會發現dist文件中js文件名中已經有了hash值
記得同步修改webpack.common.js、webpack.dev.js,若是你不知道如何修改,請看這裏(https://github.com/LuoShengMen/React-Whole-barrels/commit/e846c1380d142332e7859a0bb1120ad6a053fd17)
extension配置以後能夠不用在require或是import的時候加文件擴展名,會依次嘗試添加擴展名進行匹配
mainFiles配置後不用加入文件名,會依次嘗試添加的文件名進行匹配
alias經過配置別名能夠加快webpack查找模塊的速度。
webpack.common.js更改:
Tree Shaking能夠剔除掉一個文件中未被引用掉部分,而且只支持ES Modules模塊的引入方式,不支持CommonJS的引入方式。緣由:ES Modules是靜態引入的方式,CommonJS是動態的引入方式,Tree Shaking只支持靜態引入方式。
注意:mode 選項設置爲 production,能夠自動啓用 minification(代碼壓縮) 和 tree shaking
不論是同步代碼的分割仍是異步的代碼分割均可以使用SplitChunksPlugin這個插件,能夠將第三方庫從業務代碼中分割出來.
webpack.prod.js
對於第三方庫,這些庫在很長的一段時間內,基本不會更新,打包的時候分開打包來提高打包速度, DllPlugin動態連接庫插件,其原理就是把網頁依賴的基礎模塊抽離出來打包到dll文件中,當須要導入的模塊存在於某個dll中時,這個模塊再也不被打包,而是去dll中獲取。
新建webpack.dll.js
webpack.common.js更改
package.json
PWA全稱progressive Web Application,PWA實現的功能是即使服務器掛掉,仍是能夠經過在本地的緩存來訪問到頁面。首先安裝workbox-webpack-plugin插件,而後在webpack.prod.js中Plugins中配置,由於該功能只在線上使用。
webpack.prod.js更改
運行命令打包後會多處兩個文件precache-manifest.js和service-worker.js, service-worker這個文件就可讓咱們的頁面被緩存住
能夠經過指定環境,來使webpack進行選擇性編譯,擇性編譯是指根據打包是環境的不一樣,選擇性地讓特定的語句有效,讓特定的語句無效。這樣能夠對具體用戶的環境進行代碼優化,從而刪除或添加一些重要代碼。
最簡單的例子,在開發環境中,咱們打印日誌,但在生產環境中,咱們讓全部打印日誌的語句無效(讓程序不運行打印的語句,甚至讓打包出來的文件根本就不包含打印日誌的語句)
咱們可使用 webpack 內置的 DefinePlugin 來實現。
寫到這裏,這樣一個基本的腳手架也就搭起來了,本文全部代碼React-Whole-barrels(https://github.com/LuoShengMen/React-Whole-barrels)都在這裏了。你們能夠跟着代碼進行配置,每一步基本都有commit,若是不清楚能夠看commit。固然本文也有許多不完善的地方,例如mock、eslint、styleLint、ts等等都沒有添加上去,並且也還有許多優化點,因爲篇幅關係我也就不一一寫了,後續我會加上以及不斷完善優化該項目,感興趣的同窗能夠持續關注哦!但願能夠經過本文讓您對webpack工具備一個更加深刻和全面的認識,以便於應對之後項目中配置更改。若是要使用項目框架的話當熱是推薦creat-react-app或者umi了。本文若是有錯誤的地方,您發現了,歡迎告訴我!!謝謝!!若是以爲對您有幫助,歡迎給我一個star! ! 謝謝!!