搭建Typescript+React專案模板(4) — 專案打包

YDJFE發表於2018-09-27

相關文章和閱讀順序

1.專案初始化

2.提升開發體驗

3.整理專案和雜項

4.專案打包

5.團隊規範

專案地址

前言

經過前面的初始化,提升開發體驗和整合了一堆工具,調整了專案結構等等之後,我們是時候考慮進行專案打包了。
在這篇部落格中,我們不考慮開發環境和生產環境的配置分別,我們只看打包需要進行的配置項,所以我們需要做的如下:
0. 新增打包路徑工具

  1. 新增打包命令
  2. 進行css和js分離
  3. 修改html-webpack-plugin配置項
  4. 新增react-loadablereact-router,進行程式碼分離和按需載入
  5. 新增optimization,進行第三方庫程式碼分離
  6. 進行程式碼壓縮
  7. 關於externals

新增打包命令

我們先去webpack.config.js中觀察一下output這個配置項:

image.png

該配置項指定了打包路徑和打包後的js檔名,在webpack的配置項中,output是必須有的。
接著我們去到package.json中在script中新增打包命令build,該命令引用我們的webpack.config.js配置檔案:

image.png

之後試試執行npm run build,會發現已經將專案打包出來了:

image.png

新增打包路徑工具

在上一步中,我們已經知道打包出來的檔案位於根目錄下的dist資料夾中,所以這個路徑工具的新增指向dist資料夾:
我們去到build/utils.js檔案中,新增如下程式碼:

image.png

以後指定打包檔案存放路徑的時候就可以直接使用這個工具進行指定。

分離css檔案

在上面打包的結果中,我們會發現只有一個app.js檔案,而實際上我們是有寫css樣式的,但是現在的卻並沒有這個css檔案,這是因為webpack將所有的資源(包含js, css等等)都看成是chunk,然後一起打包進一個檔案中,這樣會導致打包出來的js檔案體積巨大,從而拖累頁面的載入速度。

  1. webpack 4+版本中,我們可以使用mini-css-extract-plugin進行css程式碼的分離,所以首先安裝它npm install -D mini-css-extract-plugin
  2. 然後我們到build/plugins.js中新增這個外掛:
    image.png
  3. 最後需要注意,之前在提升開發體驗這一章中有提到過一點,style-loader用於將css-loader編譯出來的程式碼轉為js程式碼並寫入js檔案中,所以在這裡,我們需要用mini-css-extract-plugin中的loader去替換掉style-loader,讓它寫入單獨的css檔案而不是js檔案中:
    我們去到build/rules/styleRules.js中,將原本的style-loader全都替換成mini-css-extract-plugin的loader(這一步可以進行開發環境和生產環境的區分,在文章中不進行區分):
    image.png
    image.png
  4. 經過上面的步驟,我們可以打包進行測試:
    執行npm run build可以發現打包結果中css檔案已經進行了分離:
    image.png

    而在打包出來的index.html中也可以發現這個css檔案被引入了:

    image.png
  5. 最後我們再在打包路徑中將打包出來的js檔案用js資料夾包裹起來即可:
    image.png
    image.png

修改html-webpack-plugin配置項

這一步主要用於壓縮打包出來的index.html檔案,但是單頁面應用的話html內容其實不多,所以做不做也差不多,在本文章中也只是做個介紹:

  1. 首先在html-webpack-plugin中利用的是html-minifier來做壓縮工作的,所以詳細配置點選進去看即可,常用的如下:
    image.png
  2. 第二個需要提一下則是inject這個配置項,該項指定資源如何注入,我們直接使用預設的true即可,他會將js資源注入到<body>標籤的底部,如果要注入到頭部填寫head即可

新增react-loadablereact-router,進行程式碼分離和按需載入

這一步和下一步都是在進行程式碼的拆分,考慮的是如果所有檔案都塞進一個js檔案中,會導致這個js檔案體積臃腫,而單頁面應用的所有構建又是依賴於這個js檔案,所以需要進行程式碼分離,只載入當前頁面需要構建的js檔案。
通常來說,我們會根據react-router分的頁面來進行程式碼分離,再用react-loadable進行分割出來的程式碼的非同步載入(當然你也可以將所有元件都進行程式碼分離然後非同步載入)。
所以在這裡我們先利用react-router分兩個頁面homepage出來:

  1. 首先我們安裝react-router:
    npm install -S react-router-dom,然後在src/containers/views中新建HomePage元件:
    image.png
    image.png
    image.png
  2. 接著安裝react-loadable:
    npm install -S react-loadable, 然後在src/containers/shared中新建App元件:
    image.png

    之後在裡面的index.tsx中引用react-routerreact-loadable進行元件按需載入:
    當然不要忘了使用react-hot-loader:

    image.png

    這一步需要注意的是,Loadable這個函式中的loading引數是必須有的,至於如何使用可以自行參考react-loadable的github連結。

  3. 這個時候去到頁面看一下:
    /路徑下,沒有載入page.js這個檔案,而切換到/page路徑則會載入page.js檔案,這個時候按需載入就完成了:
    image.png
    image.png
  4. 最後我們觀察一下打包後的js檔案可以發現已經進行了分離:
    image.png

會用optimization進行第三方庫程式碼分離

optimization是webpack4+版本中新出的配置項,這個配置項的功能主要是進行程式碼壓縮,優化。
在本節中,我們需要將用到的處於node_modules中的第三方程式碼進行分離,在這裡主要用到的是兩個配置項optimization.runtimeChunkoptimization.splitChunks,其中runtimeChunk用於生成維繫各各程式碼塊關係的程式碼,splitChunks則用於指定需要進行分塊的程式碼,和分塊後檔名。

  1. 我們去到build目錄下,新建optimization.js,並新增如下程式碼:
    image.png

    然後在webpack.config.js中引入這個配置:

    image.png
  2. 最後我們打包試試看可以發現第三方程式碼都被打包進vendor.js檔案中了:
    image.png

    你可以通過比對在新增optimization之前和之後打包出來的app.js檔案來看出效果。

進行程式碼壓縮

在這一步中,我們主要是做js和css的程式碼壓縮和優化

  1. 在上面階段中,我們打包出來的js程式碼是已經經過壓縮的:
    image.png

    所以在這個階段我們可以利用uglifyjs-webpack-plugin進行一些壓縮優化:
    首先我們需要安裝npm install -D uglifyjs-webpack-plugin,然後去到build/optimization.js中新增如下程式碼即可,具體的優化見程式碼:

    image.png

    PS: 這裡有一個點需要注意,在uglifyjs-webpack-plugin這個外掛中,如果是2.x版本的話是不支援es6規範的,所以建議安裝1.x版本,而我這裡的版本是:

    image.png
  2. 然後我們進行css程式碼的壓縮,這裡需要使用到optimize-css-assets-webpack-plugin外掛:npm install -D optimize-css-assets-webpack-plugin
    我們先去Home元件中隨意新增一個樣式並使用它:
    image.png
    image.png

    然後再去到build/optimization.js新增如下程式碼:

    image.png

    具體的外掛使用方式可以自行上github檢視該外掛。
    最後檢視打包出來後的css程式碼:

    image.png

到現在壓縮程式碼步驟也做完了,最後將介紹一下webpack.externals這個選項。

關於externals

webpack.externals配置項用於在構建過程中忽略一些常用包的整合,從而降低構建時間和打包後的包大小,它的配置也很簡單,在本章中只做簡單介紹:
在本專案中,我們可以將reactreact-dom新增進externals中,然後在html模板中引入它們的外部連結:

  1. 我們先去到webpack.config.js中,新增externals選項,並且把reactreact-dom新增進去:
    image.png

    這個配置項接收的是一個物件(其他形式請自行查閱webpack文件),物件的鍵是指webapck在獲取這個模組時候require時候的引數,而對應的值則是標明你打算將這個模組掛載的變數名,這裡是掛載在window物件中的。

  2. 去到build/tpl/index.html中,引入cdn中reactreact-dom的連結:
    image.png
  3. 重啟專案,可以發現在npm run dev中能夠正常使用,並且也已經引入了兩者的外部資源:
    image.png
  4. 最後我們來對比一下打包後模組佔用情況:
    不使用externals
    使用externals

    再來對比一下兩者打包出來的包體積大小:

    不使用externals
    使用externals

相關文章