1. CDN
1.1 什么是CDN?
CDN稱之為內(nèi)容分發(fā)網(wǎng)絡(luò)(Content Delivery Network或Content Distribution Network,縮寫:CDN)
- 它是指通過相互連接的網(wǎng)絡(luò)系統(tǒng),利用最靠近每個用戶的服務(wù)器;
- 更快、更可靠地將音樂、圖片、視頻、應(yīng)用程序及其他文件發(fā)送給用戶;
-
來提供高性能、可擴(kuò)展性及低成本的網(wǎng)絡(luò)內(nèi)容傳遞給用戶;
image.png
在開發(fā)中,我們使用CDN主要是兩種方式:
- 方式一:打包的所有靜態(tài)資源,放到CDN服務(wù)器,用戶所有資源都是通過CDN服務(wù)器加載的;
- 方式二:一些第三方資源放到CDN服務(wù)器上;
1.2 購買CDN服務(wù)器
如果所有的靜態(tài)資源都想要放到CDN服務(wù)器上,我們需要購買自己的CDN服務(wù)器;
- 目前阿里、騰訊、亞馬遜、Google等都可以購買CDN服務(wù)器;
-
我們可以直接修改publicPath,在打包時添加上自己的CDN地址
image.png
打包后的文件
image.png
1.3 第三方庫的CDN服務(wù)器
通常一些比較出名的開源框架都會將打包后的源碼放到一些比較出名的、免費(fèi)的CDN服務(wù)器上:
- 國際上使用比較多的是unpkg、JSDelivr、cdnjs;
- 國內(nèi)也有一個比較好用的CDN是bootcdn
在項(xiàng)目中,我們?nèi)绾稳ヒ脒@些CDN呢?
- 第一,在打包的時候我們不再需要對類似于lodash或者dayjs這些庫進(jìn)行打包;
- 第二,在html模塊中,我們需要自己加入對應(yīng)的CDN服務(wù)器地址;
第一步,我們可以通過webpack配置,來排除一些庫的打包:
module.exports = {
mode: "production",
externals: {
// window._
lodash: "_",
// window.dayjs
dayjs: "dayjs"
}
}
第二步,在html模板中,加入CDN服務(wù)器地址:
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
1.4 html模板中開發(fā)環(huán)境的判斷
<!-- ejs中的if判斷 -->
<% if (process.env.NODE_ENV === 'production') { %>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<% } %>
2 shimming
shimming是一個概念,是某一類功能的統(tǒng)稱:
- shimming翻譯過來我們稱之為 墊片,相當(dāng)于給我們的代碼填充一些墊片來處理一些問題;
- 比如我們現(xiàn)在依賴一個第三方的庫,這個第三方的庫本身依賴lodash,但是默認(rèn)沒有對lodash進(jìn)行導(dǎo)入(認(rèn)為全局存在lodash),那么我們就可以通過ProvidePlugin來實(shí)現(xiàn)shimming的效果;
注意: webpack并不推薦隨意的使用shimming
- Webpack背后的整個理念是使前端開發(fā)更加模塊化;
- 也就是說,需要編寫具有封閉性的、不存在隱含依賴(比如全局變量)的彼此隔離的模塊;
目前我們的lodash、dayjs都使用了CDN進(jìn)行引入,所以相當(dāng)于在全局是可以使用_和dayjs的
-
假如一個文件中我們使用了axios,但是沒有對它進(jìn)行引入,那么下面的代碼是會報(bào)錯的;
image.png
我們可以通過使用ProvidePlugin來實(shí)現(xiàn)shimming的效果:
- ProvidePlugin能夠幫助我們在每個模塊中,通過一個變量來獲取一個package;
- 如果webpack看到這個模塊,它將在最終的bundle中引入這個模塊;
- 另外ProvidePlugin是webpack默認(rèn)的一個插件,所以不需要專門導(dǎo)入;
const webpack = require('webpack');
module.exports = {
plugins: [
// 當(dāng)在代碼中遇到某一個變量找不到時, 我們會通過ProvidePlugin, 自動導(dǎo)入對應(yīng)的庫
new webpack.ProvidePlugin({
axios: "axios",
get: ["axios", "get"]
})
],
}
3. Hash、ContentHash、ChunkHash
在我們給打包的文件進(jìn)行命名的時候,會使用placeholder,placeholder中有幾個屬性比較相似:
- hash、chunkhash、contenthash;
- hash本身是通過MD4的散列函數(shù)處理后,生成一個128位的hash值(32個十六進(jìn)制);
hash值的生成和整個項(xiàng)目有關(guān)系:
- 比如我們現(xiàn)在有兩個入口index.js和main.js;
- 它們分別會輸出到不同的bundle文件中,并且在文件名稱中我們有使用hash;
- 這個時候,如果修改了index.js文件中的內(nèi)容,那么hash會發(fā)生變化;
- 那就意味著兩個文件的名稱都會發(fā)生變化;
chunkhash可以有效的解決上面的問題,它會根據(jù)不同的入口進(jìn)行借來解析來生成hash值:
- 比如我們修改了index.js,那么main.js的chunkhash是不會發(fā)生改變的;
contenthash表示生成的文件hash名稱,只和內(nèi)容有關(guān)系:
- 比如我們的index.js,引入了一個style.css,style.css有被抽取到一個獨(dú)立的css文件中;
- 這個css文件在命名時,如果我們使用的是chunkhash;
- 那么當(dāng)index.js文件的內(nèi)容發(fā)生變化時,css文件的命名也會發(fā)生變化;
- 這個時候我們可以使用contenthash;



