安裝
npm install webpack webpack -D
然后通過 npx webpack -v 查看版本號,這個時候查看的就是當前目錄下面的webpack
loader
webpack不能識別非js結(jié)尾的文件,這個時候就需要loader來做處理
plugin
可以在webpack運行到某個時刻的時候,幫忙做一些事情
html-webpack-plugin 會在打包結(jié)束后,自動生成一個html文件,并把打包生成的js文件自動引入到這個html文件中
然后還可以自己制定模板

clean-webpack-plugin 自動清除制定目錄
[圖片上傳失敗...(image-50a50a-1560925259310)]
Entry和Output配置
打包多個文件,在output的filename配置成自動獲取entry里面的鍵名


當我們的靜態(tài)資源需要部署到cdn上或者另外的服務器上,可以在output里面配置publicPath,打包完之后,模板里面就會自動帶上指定的域名了


SourceMap 配置 開發(fā)環(huán)境
當 webpack 打包源代碼時,可能會很難追蹤到 error(錯誤) 和 warning(警告) 在源代碼中的原始位置
為了更容易地追蹤 error 和 warning,JavaScript 提供了 source map 功能,可以將編譯后的代碼映射回原始源代碼

cheap-module-eval-source-map 推薦開發(fā)環(huán)境使用,所有的錯誤(包括依賴包)都會被顯示出來,同時速度比較快
cheap-module-source-map 推薦線上環(huán)境使用,
webpack-dev-server 自動更新,提升效率


命令開啟的時候,dist目錄會放到內(nèi)存中,項目中暫時看不到dist
模塊熱更替 HMR
因為HRM是webpack內(nèi)置的功能,所以在配置文件里先引入webpack
const webpack = require('webpack')


當我們在某個模塊里面引入了其它模塊,然后被引入的模塊更改后,頁面不要刷新,而只是更新被引入模塊,就需要在模塊里面進行一些配置
if(module.hot){
module.hot.accept('./count', () => {
count()
})
}
這里的意思是,如果count模塊更改,就執(zhí)行后面的回調(diào)函數(shù)
通過babel轉(zhuǎn)換JS代碼
https://www.babeljs.cn/setup#installation 里面查找打包工具
首先在rules里面加入

然后在根目錄加入.babelrc配置文件

上面使用了babel的polyfill功能,把低版本瀏覽器未實現(xiàn)的方法,通過膩子腳本來實現(xiàn),這里只會打包使用到的polyfill
在代碼里面引入polyfill就可以使用了,這種方式適用于業(yè)務代碼,如果想打包包文件,可以使用transform-runtime

"presets": [["@babel/preset-env",{ // 業(yè)務
"useBuiltIns": "usage"
}]],
"plugins": [ // 包打包
[
"@babel/plugin-transform-runtime",
{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
Tree shaking
只打包我們我們使用文件中的內(nèi)容
optimization: {
usedExports: true
}

上圖配置的sideEffects的意思是,對所有文件都執(zhí)行tree shaking,如果我們想忽略某些文件,可以這么使用
sideEffects: [".css",".less"] 這樣即使css或者less沒有導出模塊,treeshaking也不會忽略掉
但是在開發(fā)模式中,我們打包完的文件里面還是能看到全部的代碼,這是因為如果開發(fā)的時候,treeshaking幫我們刪除了一些代碼,在代碼出錯提示的時候,行數(shù)就可能會出錯。但是在生產(chǎn)環(huán)境就沒有這個問題,只會打包引用的內(nèi)容
開發(fā)模式和生產(chǎn)模式
通常開發(fā)和生產(chǎn)環(huán)境的打包配置文件有區(qū)別,這個時候我們可以把公共部分抽取出來,然后在我們打包的時候,通過merge把公共的配置加載進去,然后執(zhí)行不同的配置文件
Code Splitting
默認方式
optimization: {
splitChunks: {
chunks: 'all'
}
}
異步方式需要先通過babel轉(zhuǎn)碼
Lazy loading 懶加載 Chunk
打包生成的每個文件都算一個chunk,懶加載就是延遲加載chunk
打包分析 Preloading Prefetching
webpack 官方打包工具分析 通過這個里面提供的命令,可以生成一份json文件,然后把json文件傳到這個地址就可以進行分析了
或者使用命令工具,自動生成完整的的信息 webpack-bundle-analyzer
查看代碼利用率 使用ctrl+shift+p 然后查找coverage
prefetch 等待核心代碼加載完成后,然后再加載異步代碼
CSS 文件的代碼分割
minicssextractplugin 目前還不支持HMR 所以最好是用在線上的環(huán)境
這里需要注意treeshsaking的問題,因為treeshaking會把引入而沒有使用的文件忽略掉,所以,我們要現(xiàn)在package里面把指定的文件進行配置


如果一個文件在模本里面被直接引用,打包的文件名就是filename,而不再模板里面的就走chunkfilename

如果在需要css代碼壓縮和合并,還需要另外一個插件
Webpack 與瀏覽器緩存

當我們配置contenthash后,文件內(nèi)容不改動,重新打包的文件名是不會發(fā)生改變的
shimming 墊片
當我們使用的第三方庫依賴某些包的時候

這個文件沒有引入jquery,但是又使用了jquery提供的方法,所以需要在webpack配置文件中加一個插件

當頁面中所有地方使用到$這個變量的時候,webpack會自動幫我們引入jquery
PWA 配置
workbox-webpack-plugin 因為這個插件只在線上使用,所以只用在線上的配置文件里面引入就可以了

然后還需要在業(yè)務代碼里面使用生成好的service-worker文件
if('serviceWorker' in navigator){
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').
then(registration => {
console.log('registed')
}).catch(error => {
console.log(error)
})
})
}
使用webpackDevServer 實現(xiàn)請求轉(zhuǎn)發(fā)

會把所有的請求代理到dell-lee的域名下面
如果接口地址不變,而又想拿另外一個接口的數(shù)據(jù),例如請求的還是header.json 但因為這個接口還在開發(fā)中,只能提供一個假接口demo.json 這個時候就可以使用下面的配置


當被代理網(wǎng)站有防爬蟲的時候開啟
dev-server 使用了非常強大的 http-proxy-middleware 包。更多高級用法,請查閱其 文檔 在這個文檔里面,就可以配置更多的東西了,例如header,auth
webpack-dev-server 單頁路由
當我們在配置單頁路由的時候,需要把不存在的路徑全部指向到index,就可以這么配置 這個是在開發(fā)環(huán)境

historyapifallback 會把所有404都指向到默認頁面
Eslint 安裝
npm install eslint --save-dev
npx eslint --init // 初始化
Webpack 優(yōu)化
跟上技術(shù)的迭代(Node,Npm,Yarn)
在盡可能少的模塊上引用loader
Plugin盡可能精簡并確??煽?/p>
resolve 參數(shù)合理配置

- 使用DllPlugin 提高打包速度 應為第三方模塊基本不會改變,所以可以針對第三方模塊單獨打包,這樣每次webpack打包的時候,就不用再去分析第三方模塊了。然后通過映射關系,使用第三方插件的時候,就不讀取node_modules里面的文件了,而是讀取我們打包完成的文件
- 首先單獨配置一份dll的配置文件 這樣指定的第三方模塊就打包在一起了
const path = require('path');
module.exports = {
mode: 'production',
entry: {
vendors: ['react','react-dom','lodash'] // 把這三個包打包在一起
},
output: {
filename: '[name].dll.js',
path: path.resolve(__dirname, '../dll')
}
}
// 命令 "build:dll": "webpack --config ./build/webpack.dll.js"
? 2. 然后把打包的文件,通過一個全局變量暴露出去

? 3. 然后再增加一個插件add-asset-html-webpack-plugin 把我們打包好的文件添加到模板里面

? 4.但是到這里,我們代碼里面還是使用的是第三方的包,并沒有使用我們打包好的文件,下面我們需要生成一個映射文件,在webpack打包的時候,如果發(fā)現(xiàn)第三方包在映射文件內(nèi),就直接取我們打包好的文件,下面是配置 還是webpack.dll.js

? 5.然后再common配置文件里面,再增加一個插件,把我們剛生成的manifest映射文件引入進來,然后自動幫我們處理映射關系
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, '../dll/vendors.dll.js')
}),
new webpack.DllReferencePlugin({ // 就是這個
manifest: path.resolve(__dirname, '../dll/vendors.manifest.json')
})
? 6.最后,當我們要打包的文件分為多個,那怎么辦呢 首先配置webpack.dll.js
[圖片上傳失敗...(image-e9dc73-1560925259310)]
? https://github.com/tinyzh/tinyzh.github.io/tree/master/webpack-dllplugn)
- 縮小包的大小
- 多進程打包
- 合理使用sourceMap
- 結(jié)合stats分析打包結(jié)果
- 開發(fā)過程中,剔除無用插件,例如開發(fā)過程中不需要代碼壓縮,配置文件的mode就選擇development就行