相關(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)行的配置項,所以我們需要做的如下:
- 添加打包路徑工具
- 添加打包命令
- 進(jìn)行css和js分離
- 修改
html-webpack-plugin配置項 - 添加
react-loadable和react-router,進(jìn)行代碼分離和按需加載 - 添加optimization,進(jìn)行第三方庫代碼分離
- 進(jìn)行代碼壓縮
- 關(guān)于
externals
添加打包命令
我們先去webpack.config.js中觀察一下output這個配置項:

該配置項指定了打包路徑和打包后的js文件名,在
webpack的配置項中,output是必須有的。接著我們?nèi)サ?code>package.json中在
script中添加打包命令build,該命令引用我們的webpack.config.js配置文件:
之后試試運(yùn)行
npm run build,會發(fā)現(xiàn)已經(jīng)將項目打包出來了:
添加打包路徑工具
在上一步中,我們已經(jīng)知道打包出來的文件位于根目錄下的dist文件夾中,所以這個路徑工具的添加指向dist文件夾:
我們?nèi)サ?code>build/utils.js文件中,添加如下代碼:

以后指定打包文件存放路徑的時候就可以直接使用這個工具進(jìn)行指定。
分離css文件
在上面打包的結(jié)果中,我們會發(fā)現(xiàn)只有一個app.js文件,而實際上我們是有寫css樣式的,但是現(xiàn)在的卻并沒有這個css文件,這是因為webpack將所有的資源(包含js, css等等)都看成是chunk,然后一起打包進(jìn)一個文件中,這樣會導(dǎo)致打包出來的js文件體積巨大,從而拖累頁面的加載速度。
- 在
webpack 4+版本中,我們可以使用mini-css-extract-plugin進(jìn)行css代碼的分離,所以首先安裝它npm install -D mini-css-extract-plugin。 - 然后我們到
build/plugins.js中添加這個插件:
image.png - 最后需要注意,之前在提升開發(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 - 經(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 -
最后我們再在打包路徑中將打包出來的js文件用js文件夾包裹起來即可:
image.png
image.png
修改html-webpack-plugin配置項
這一步主要用于壓縮打包出來的index.html文件,但是單頁面應(yīng)用的話html內(nèi)容其實不多,所以做不做也差不多,在本文章中也只是做個介紹:
- 首先在
html-webpack-plugin中利用的是html-minifier來做壓縮工作的,所以詳細(xì)配置點擊進(jìn)去看即可,常用的如下:
image.png - 第二個需要提一下則是
inject這個配置項,該項指定資源如何注入,我們直接使用默認(rèn)的true即可,他會將js資源注入到<body>標(biāo)簽的底部,如果要注入到頭部填寫head即可
添加react-loadable和react-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分兩個頁面home和page出來:
- 首先我們安裝
react-router:
npm install -S react-router-dom,然后在src/containers/views中新建Home和Page組件:
image.png
image.png
image.png - 接著安裝
react-loadable:
npm install -S react-loadable, 然后在src/containers/shared中新建App組件:
image.png
之后在里面的index.tsx中引用react-router和react-loadable進(jìn)行組件按需加載:
當(dāng)然不要忘了使用react-hot-loader:
image.png
這一步需要注意的是,Loadable這個函數(shù)中的loading參數(shù)是必須有的,至于如何使用可以自行參考react-loadable的github鏈接。 - 這個時候去到頁面看一下:
在/路徑下,沒有加載page.js這個文件,而切換到/page路徑則會加載page.js文件,這個時候按需加載就完成了:
image.png
image.png -
最后我們觀察一下打包后的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.runtimeChunk和optimization.splitChunks,其中runtimeChunk用于生成維系各各代碼塊關(guān)系的代碼,splitChunks則用于指定需要進(jìn)行分塊的代碼,和分塊后文件名。
- 我們?nèi)サ?code>build目錄下,新建
optimization.js,并添加如下代碼:
image.png
然后在webpack.config.js中引入這個配置:
image.png - 最后我們打包試試看可以發(fā)現(xiàn)第三方代碼都被打包進(jìn)
vendor.js文件中了:
image.png
你可以通過比對在添加optimization之前和之后打包出來的app.js文件來看出效果。
進(jìn)行代碼壓縮
在這一步中,我們主要是做js和css的代碼壓縮和優(yōu)化
- 在上面階段中,我們打包出來的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 - 然后我們進(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)建時間和打包后的包大小,它的配置也很簡單,在本章中只做簡單介紹:
在本項目中,我們可以將react和react-dom添加進(jìn)externals中,然后在html模板中引入它們的外部鏈接:
- 我們先去到
webpack.config.js中,添加externals選項,并且把react和react-dom添加進(jìn)去:
image.png
這個配置項接收的是一個對象(其他形式請自行查閱webpack文檔),對象的鍵是指webapck在獲取這個模塊時候require時候的參數(shù),而對應(yīng)的值則是標(biāo)明你打算將這個模塊掛載的變量名,這里是掛載在window對象中的。 - 去到
build/tpl/index.html中,引入cdn中react和react-dom的鏈接:
image.png - 重啟項目,可以發(fā)現(xiàn)在
npm run dev中能夠正常使用,并且也已經(jīng)引入了兩者的外部資源:
image.png -
最后我們來對比一下打包后模塊占用情況:
不使用externals
使用externals
再來對比一下兩者打包出來的包體積大小:
不使用externals
使用externals
































