搭建Typescript+React項目模板(4) --- 項目打包

相關(guān)文章和閱讀順序

搭建Typescript+React項目模板(1) --- 項目初始化
搭建 Typescript+React 項目模板 (2) --- 提升開發(fā)體驗
搭建 Typescript+React 項目模板 (3) --- 整理項目和雜項
搭建 Typescript+React 項目模板 (4) --- 項目打包
搭建 Typescript+React 項目模板 (5) --- 團(tuán)隊規(guī)范

文章已同步更新到掘金專欄(https://juejin.im/user/5a77c815f265da4e9518bebc/posts)

項目地址

前言

經(jīng)過前面的初始化,提升開發(fā)體驗和集成了一堆工具,調(diào)整了項目結(jié)構(gòu)等等之后,我們是時候考慮進(jìn)行項目打包了。
在這篇博客中,我們不考慮開發(fā)環(huán)境和生產(chǎn)環(huán)境的配置分別,我們只看打包需要進(jìn)行的配置項,所以我們需要做的如下:

  1. 添加打包路徑工具
  2. 添加打包命令
  3. 進(jìn)行css和js分離
  4. 修改html-webpack-plugin配置項
  5. 添加react-loadablereact-router,進(jìn)行代碼分離和按需加載
  6. 添加optimization,進(jìn)行第三方庫代碼分離
  7. 進(jìn)行代碼壓縮
  8. 關(guān)于externals

添加打包命令

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

image.png

該配置項指定了打包路徑和打包后的js文件名,在webpack的配置項中,output是必須有的。
接著我們?nèi)サ?code>package.json中在script中添加打包命令build,該命令引用我們的webpack.config.js配置文件:
image.png

之后試試運(yùn)行npm run build,會發(fā)現(xiàn)已經(jīng)將項目打包出來了:
image.png

添加打包路徑工具

在上一步中,我們已經(jīng)知道打包出來的文件位于根目錄下的dist文件夾中,所以這個路徑工具的添加指向dist文件夾:
我們?nèi)サ?code>build/utils.js文件中,添加如下代碼:

image.png

以后指定打包文件存放路徑的時候就可以直接使用這個工具進(jìn)行指定。

分離css文件

在上面打包的結(jié)果中,我們會發(fā)現(xiàn)只有一個app.js文件,而實際上我們是有寫css樣式的,但是現(xiàn)在的卻并沒有這個css文件,這是因為webpack將所有的資源(包含js, css等等)都看成是chunk,然后一起打包進(jìn)一個文件中,這樣會導(dǎo)致打包出來的js文件體積巨大,從而拖累頁面的加載速度。

  1. webpack 4+版本中,我們可以使用mini-css-extract-plugin進(jìn)行css代碼的分離,所以首先安裝它npm install -D mini-css-extract-plugin。
  2. 然后我們到build/plugins.js中添加這個插件:
    image.png
  3. 最后需要注意,之前在提升開發(fā)體驗這一章中有提到過一點,style-loader用于將css-loader編譯出來的代碼轉(zhuǎn)為js代碼并寫入js文件中,所以在這里,我們需要用mini-css-extract-plugin中的loader去替換掉style-loader,讓它寫入單獨的css文件而不是js文件中:
    我們?nèi)サ?code>build/rules/styleRules.js中,將原本的style-loader全都替換成mini-css-extract-plugin的loader(這一步可以進(jìn)行開發(fā)環(huán)境和生產(chǎn)環(huán)境的區(qū)分,在文章中不進(jìn)行區(qū)分):
    image.png

    image.png
  4. 經(jīng)過上面的步驟,我們可以打包進(jìn)行測試:
    運(yùn)行npm run build可以發(fā)現(xiàn)打包結(jié)果中css文件已經(jīng)進(jìn)行了分離:
    image.png

    而在打包出來的index.html中也可以發(fā)現(xiàn)這個css文件被引入了:
    image.png
  5. 最后我們再在打包路徑中將打包出來的js文件用js文件夾包裹起來即可:


    image.png

    image.png

修改html-webpack-plugin配置項

這一步主要用于壓縮打包出來的index.html文件,但是單頁面應(yīng)用的話html內(nèi)容其實不多,所以做不做也差不多,在本文章中也只是做個介紹:

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

添加react-loadablereact-router,進(jìn)行代碼分離和按需加載

這一步和下一步都是在進(jìn)行代碼的拆分,考慮的是如果所有文件都塞進(jìn)一個js文件中,會導(dǎo)致這個js文件體積臃腫,而單頁面應(yīng)用的所有構(gòu)建又是依賴于這個js文件,所以需要進(jìn)行代碼分離,只加載當(dāng)前頁面需要構(gòu)建的js文件。
通常來說,我們會根據(jù)react-router分的頁面來進(jìn)行代碼分離,再用react-loadable進(jìn)行分割出來的代碼的異步加載(當(dāng)然你也可以將所有組件都進(jìn)行代碼分離然后異步加載)。
所以在這里我們先利用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進(jìn)行組件按需加載:
    當(dāng)然不要忘了使用react-hot-loader:
    image.png

    這一步需要注意的是,Loadable這個函數(shù)中的loading參數(shù)是必須有的,至于如何使用可以自行參考react-loadable的github鏈接。
  3. 這個時候去到頁面看一下:
    /路徑下,沒有加載page.js這個文件,而切換到/page路徑則會加載page.js文件,這個時候按需加載就完成了:
    image.png

    image.png
  4. 最后我們觀察一下打包后的js文件可以發(fā)現(xiàn)已經(jīng)進(jìn)行了分離:


    image.png

會用optimization進(jìn)行第三方庫代碼分離

optimization是webpack4+版本中新出的配置項,這個配置項的功能主要是進(jìn)行代碼壓縮,優(yōu)化。
在本節(jié)中,我們需要將用到的處于node_modules中的第三方代碼進(jìn)行分離,在這里主要用到的是兩個配置項optimization.runtimeChunkoptimization.splitChunks,其中runtimeChunk用于生成維系各各代碼塊關(guān)系的代碼,splitChunks則用于指定需要進(jìn)行分塊的代碼,和分塊后文件名。

  1. 我們?nèi)サ?code>build目錄下,新建optimization.js,并添加如下代碼:
    image.png

    然后在webpack.config.js中引入這個配置:
    image.png
  2. 最后我們打包試試看可以發(fā)現(xiàn)第三方代碼都被打包進(jìn)vendor.js文件中了:
    image.png

    你可以通過比對在添加optimization之前和之后打包出來的app.js文件來看出效果。

進(jìn)行代碼壓縮

在這一步中,我們主要是做js和css的代碼壓縮和優(yōu)化

  1. 在上面階段中,我們打包出來的js代碼是已經(jīng)經(jīng)過壓縮的:
    image.png

    所以在這個階段我們可以利用uglifyjs-webpack-plugin進(jìn)行一些壓縮優(yōu)化:
    首先我們需要安裝npm install -D uglifyjs-webpack-plugin,然后去到build/optimization.js中添加如下代碼即可,具體的優(yōu)化見代碼:
    image.png

    PS: 這里有一個點需要注意,在uglifyjs-webpack-plugin這個插件中,如果是2.x版本的話是不支持es6規(guī)范的,所以建議安裝1.x版本,而我這里的版本是:
    image.png
  2. 然后我們進(jìn)行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

到現(xiàn)在壓縮代碼步驟也做完了,最后將介紹一下webpack.externals這個選項。

關(guān)于externals

webpack.externals配置項用于在構(gòu)建過程中忽略一些常用包的集成,從而降低構(gòu)建時間和打包后的包大小,它的配置也很簡單,在本章中只做簡單介紹:
在本項目中,我們可以將reactreact-dom添加進(jìn)externals中,然后在html模板中引入它們的外部鏈接:

  1. 我們先去到webpack.config.js中,添加externals選項,并且把reactreact-dom添加進(jìn)去:
    image.png

    這個配置項接收的是一個對象(其他形式請自行查閱webpack文檔),對象的鍵是指webapck在獲取這個模塊時候require時候的參數(shù),而對應(yīng)的值則是標(biāo)明你打算將這個模塊掛載的變量名,這里是掛載在window對象中的。
  2. 去到build/tpl/index.html中,引入cdn中reactreact-dom的鏈接:
    image.png
  3. 重啟項目,可以發(fā)現(xiàn)在npm run dev中能夠正常使用,并且也已經(jīng)引入了兩者的外部資源:
    image.png
  4. 最后我們來對比一下打包后模塊占用情況:


    不使用externals

    使用externals

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


    不使用externals

    使用externals
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容