項目webpack2.x遷移到4.x預研筆記

公司項目使用webpack2.x,搭建得比較早,沒有用vue-cli(沒啥影響),這是大背景。

本項目構建時主要的依賴包:

"dependencies": {
    "babel-core": "^6.26.0",
    "es6-promise": "^4.2.4",
    "eslint-config-vue": "^2.0.2",
    "vue": "^2.5.16",
    "vue-router": "^2.8.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-middleware": "^3.1.3",
    "webpack-hot-middleware": "^2.22.2"
  },
"devDependencies": {
    "babel-eslint": "^7.2.3",
    "babel-loader": "^7.1.4",
    "babel-polyfill": "^6.23.0",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-es2016": "^6.24.1",
    "babel-preset-stage-3": "^6.22.0",
    "copy-webpack-plugin": "^4.5.2",
    "css-loader": "^0.28.11",
    "ejs-loader": "^0.3.1",
    "eslint": "^3.18.0",
    "eslint-loader": "^2.0.0",
    "eslint-plugin-html": "^4.0.5",
    "eslint-plugin-vue": "^2.1.0",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "file-loader": "^1.1.11",
    "html-loader": "^1.0.0-alpha.0",
    "html-webpack-plugin": "^4.0.0-alpha",
    "less": "^3.0.4",
    "less-loader": "^4.1.0",
    "lodash": "^4.17.4",
    "node-sass": "^4.9.0",
    "sass-loader": "^6.0.7",
    "style-loader": "^0.21.0",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.2",
    "url-loader": "^1.0.1",
    "vue-loader": "^15.2.6",
    "vue-template-compiler": "^2.5.16",
    "webpack": "^4.16.2",
    "webpack-dev-server": "^3.1.1"
  },

這些只是依賴包的其中一部分,每一個點拿出來均可以是一個深刻研究的問題,所以這裏主要闡述一下各類包的主要邏輯與聯繫(其實就是各類坑)。css

vue、vue-loader、vue-template-compiler :

先看vue-template-compiler的官方說明:html

This package can be used to pre-compile Vue 2.0 templates into render functions to avoid runtime-compilation overhead and CSP restrictions.
You will only need it if you are writing build tools with very specific needs. In most cases you should be using vue-loader or vueify instead, both of which use this package internally.

通常狀況下,vue-loader與vueify自身會在內部使用此包,只有在比較特殊的狀況下才須要用到。單文件組件(.vue爲擴展名的文件)就是這種狀況的其中一種。前端

*在使用vue-template-compiler的時候,版本號要和vue版本號一致。vue

vue-router :

在這裏把vue-router拿出來講,是由於在這裏踩了一個坑。在此次預研任務裏,主要目標就是理解webpack打包構建的原理和過程。在網上看了諸多筆記和教程,沒有一篇提到過與vue-router發生衝突或者報錯的。可是項目在升級webpack4後頁面數據<router-view></router-view>的部分渲染不出來,報錯以下:
圖片描述
圖片描述
在網上搜索了不少,以及去github看了issue,沒有定向到問題所在。總結出大概方向應該是解析器版本沒對上,而後vue-loader什麼的,一個個版本都試過了也沒有用。
最後把vue-router從2.5.x升級到最新2.8.1,立馬解決。node

extract-text-webpack-plugin與mini-css-extract-plugin :

extract-text-webpack-plugin主要是爲了抽離css樣式,防止將樣式打包在js中引發頁面樣式加載錯亂的現象。
webpack升4以後,extract-text-webpack-plugin的做者一度沒有時間更新插件,這時比較多人推薦的是mini-css-extract-plugin,二者做用接近。
如今,extract-text-webpack-plugin的4.0beta版本已經出來了,與webpack4兼容性良好。由於項目用的是這個,因此繼續沿用。webpack

總結在升級依賴時有三個點:

1.更新工具/依賴的時候,第一步必定是儘量把全部核心的依賴所有都升到最新,通常能夠解決問題(其實已經作到)。
2.出現報錯,首先考慮更新有直接關係的依賴,而不是回想本身以前的更新是否不對。(我就是一直在想是否vue-loader/html-webpack-plugin...等版本不吻合,卡了好久,其實就是vue-router沒更新,固然這主要是本身的問題,被網上資料引導了,沒看到任何相關問題,就一直沒往這方面考慮)。
3.若是須要了解一個依賴包,第一選擇是上github,篩選對本身有用的問題;其次再去搜索網上的資源。不建議在沒有讀懂原理的時候就直接套用網上的配置,即便一時生效,日後可能也是個大坑。git

webpack4.x:SplitChunkPLugin是如何分包的?官方文檔

直接採用了官方文檔的example 1,以下:es6

splitChunks: {
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial',
          minChunks: 2
        }
      }
    }

而後打包(run build),運行成功,耗時從240s縮減爲110s,主要的vendor.js體積也從540k減少到了440k左右。github

run dev,能夠正常運行,可是過不了多久,就會報內存溢出:web

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

JavaScript堆內存不足,這裏說的 JavaScript 其實就是 Node,Node 是基於V8引擎的,在通常的後端開發語言中,在基本的內存使用上沒有什麼限制,可是實際上,在 Node 中經過 JavaScript 使用內存時只能使用部份內存(64位系統下約爲1.4 GB,32位系統下約爲0.7 GB)因此當前端項目龐大的話,webpack 編譯時就會佔用不少的系統資源,若是超出了V8對 Node 默認的內存限制大小就會出現這個錯誤,那怎麼解決呢?V8依然提供了選項讓咱們使用更多的內存。Node 在啓動時能夠傳遞 --max-old-space-size 或 --max-new-space-size 來調整內存大小的使用限制。

若是遇到 Node 沒法分配足夠內存給 JavaScript 的狀況,能夠用這個辦法來放寬V8默認的內存限制,避免在執行過程當中稍微多用了一些內存就輕易崩潰,既然知道了解決辦法那就好辦了,在 package.json 裏,咱們直接把上面v8提供的選項參數直接寫入scripts 字段的 node 命令後就行了,示例以下:

"scripts": {
    "dev": "node --max_old_space_size=4096 build/dev-server.js",
    "build": "node --max_old_space_size=4096 build/build.js"
  }

直接在 node 後面寫上 --max_old_space_size=4096 就行了,我這裏設置的內存大小是4G,這個具體的大小能夠根據本身的項目狀況來設置就行了。而後再從新運行 npm run dev/build 就能夠正常運行和打包了。

最後:打開F12,會發現一些頁面子組件尚未被渲染的時候,js方法會被預先加載出來。這裏初步推測與splitChunk的配置有關,從此有機會繼續研究一下,會在這裏續寫。

相關文章
相關標籤/搜索