快速過一遍Webpack4核心知識

1、webpack和webpack-dev-server區別
webpack 每次會生成一個bundle.js文件,webpack-dev-server不會,只是將打包結果放在內存中,並不會寫入實際的bundle.js,在每次webpack-dev-server接收到請求時,都將內存中的打包結果返回給瀏覽器。

2、webpack-cli安裝後可以直接在控制檯調用webpack命令
3、url-loader 和 file-loader
url-loader和file-loader都可以用來作爲打包圖片的loader

url-loader不會生成一個具體的圖片文件,而是直接在需要這個圖片src地址的地方給出圖片的base64地址,這樣比較適合幾k大小的小圖,減少http請求;url-loader有個limit設置一個numer,單位是bytes,如果圖片大於這個limit值,則默認使用file-loader, 如果小於則使用url-loader
file-loader會生成一個圖片文件,適合大點的圖片
4、style-loader作用主要是將css放到dom中
官方英文解釋很到位:Adds CSS to the DOM by injecting a

如果配置style-loader/url,則會生成一個類似這樣的內聯css。

5、postcss-loader與Autoprefixer一起,用來適配各大瀏覽器廠商css前綴
需要配置postcss.config.js,和安裝autoprefixer
6、resolve配置
resolve.alias 設置別名來替換某個路徑,如:
resolve:{
alias:{
@: ‘./src/components/’
}
}
當需要引入import './src/components/header’時,可以寫成import ‘@/header’

resolve.extensions 設置引入文件的擴展格式,當引入文件省略了後綴名時候,會按照設置的resolve.extensions去相應路徑匹配對應格式的文件,默認是[‘js’, ‘json’],如果是react項目可以設置:extensions: [’.jsx’, ‘.js’, ‘.json’]
7、模塊樣化處理
{
loader: ‘css-loader’,
options: {
importLoaders: 2,
modules: true,
},
},
如上在配置css-loader時候,配置modules: true

但一般出路antd的樣式時候,需要做兩手處理:

{
test: /.lessKaTeX parse error: Undefined control sequence: \/ at position 30: …: /node_modules\̲/̲antd/, use:…/,
exclude: /node_modules/antd/,
use: [
‘style-loader’,
{ loader: ‘css-loader’, options: {modules: true} },
‘less-loader’
]
}
這樣避免了 css-modules 對 antd 的樣式進行處理,否則會造成antd 的樣式的不匹配。

8、iconfont字體打包
{
test: /.(eot|ttf|svg|woff)$/,
use: {
loader: ‘file-loader’,
},
}
如上示例,打包.eot, .ttf等字體文件

9、html-webpack-plugin
會在打包完成後,自動生成一個html文件,並把打包生成的js自動引入到這個html中
如果希望打包出來的html是按照要求配置的,如加上

,那麼就可以在HtmlWebpackPlugin配置中加入template指定一個模板文件
10、clean-webpack-plugin
清除打包數據
clean-webpack-plugin v3.0以上版本,不需要添加額外配置項,默認清除的文件是output.path指定的路徑文件夾內容
11、output.publicPath
在output中配置publicPath,如一個路徑或者一個cdn地址,然後打包出來的資源會自動加上這個publicPath前綴,如加上一個cdn的host後,打包出來的script的src會在文件名前加上這個cdn地址。
12、source-map
souce-map是源代碼和打包後的代碼的一個映射關係,對應的webpack配置是devtool,可以快速定位錯誤行代碼。
devtool在mode=development中一般配置,devtool:cheap-module-eval-source-map,這樣既可以定位錯誤正確的位置,同時打包速度也不會太受影響。
devtool在mode=production中一般配置,devtool:cheap-module-source-map。
devtool設置了source-map會生成一個.map映射文件;
設置了帶inline,則會將映射文件內容放到打包文件裏,不會單獨生成.map映射文件;
設置了帶cheap的配置只會提示行不提示列錯誤,同時只提示業務代碼,不管loader的打包代碼;
設置了帶module的是除了核心業務代碼,loader打包文件代碼也會提示錯誤位置
設置了帶eval的會提高打包速度。
13、devServer
主要用於快速開發應用,提高開發效率
通過設置package.json中的stripts,“watch”: “webpack --watch”,可以實現修改頁面代碼後自動打包,但是沒法開啓一個服務,這就不能滿足ajax(ajax必須在一個http服務裏才能使用)調用服務等開發需求了,此時需要webpack-dev-server了
webpack-dev-server打包出來的文件不會放到原先的dist或者配置好的output路徑,而是放到了本地電腦內存中,這樣提升打包速度
配置contentBase,告訴服務器從哪個目錄中提供內容,填寫output的path就可以了
配置open,設爲true時devserver啓動後自動打開瀏覽器
配置port,可以修改開啓服務的端口號
配置proxy,如果現在在http://localhost:3000上有服務端的話,可以設置proxy: {’/api’: ‘http://localhost:3000’},這樣在本地的非3000端口host上請求/api/info接口,實際是請求了http://localhost:3000/api/info,否則會報跨域錯誤
如果不用 webpack-dev-server,可以通過 webpack-dev-middleware 和express/koa2寫一個server.js的服務,然後啓動這個服務,可以達到和 webpack-dev-server 一樣的修改後自動更新等效果
14、hot-module-replacement
當添加了 webpack-dev-server 之後,那麼每次有代碼修改時,就會重新請求頁面,然後刷新頁面,但這有個小問題,就是即便一個css顏色值修改了,頁面也會重新刷新,加入hot-module-replacement可以簡化這個請求過程。
首先在devServer中加入 hot:true,然後在 plugins 中加入new webpack.HotModuleReplacementPlugin()配置,這樣僅僅只能做到css樣式的無刷新修改
如果需要js也能無刷新修改,則需要在js中加入module.hot的判斷,判斷的對應結果中需要更新代碼,使用 module.hot.accept 將其綁定到新的函數執行中,詳見https://webpack.docschina.org/guides/hot-module-replacement/#%E5%90%AF%E7%94%A8-hmr
具體針對前端不同框架,社區有不同loader可以支持HMR,React Hot Loader,Vue loader等
15、配置Babel
Babel主要是將es6+代碼轉換爲es5代碼,讓低版本瀏覽器也能加載代碼
① 最基本的設置是:
npm install --save-dev babel-loader @babel/core

webpack 設置:

module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: “babel-loader”
}
]
}
.babelrc 文件設置如下:

npm install @babel/preset-env --save-dev

{
“presets”: ["@babel/preset-env"]
}
但面對更低版本的瀏覽器的時候,像promise還需要轉化注入,就需要引入babel/polyfill


npm install --save @babel/polyfill
在對應業務js代碼文件開頭引入polyfill import “@babel/polyfill”;

但是這樣有個缺點,就是會把所有es6轉es5的需要的語法都給打包到對應文件,造成打包文件過大。

如果需要按需去打包polyfill語法,根據代碼需要,可以設置文件 .babelrc:

{
“presets”: [["@babel/preset-env", {
“targets”: {
chrome: “67”
},
“useBuiltIns”: “usage”,
}]],
}
上面配置中的 targets 中配置的瀏覽器版本,是指大於該版本的瀏覽器,根據該瀏覽器對es6的支持情況去有針對性的打包polyfill代碼,這樣可以讓打包文件變得更小一點,比如如果chrome67以上的版本瀏覽器對promise支持很好,那麼就不需要打包promise的語法了,更不需要對promise去轉碼。

總的來說,polyfill修改了全局作用域,瀏覽器下是window,node下是global。

babel-polyfill主要由兩部分組成,core-js和regenerator runtime。

core-js:提供瞭如ES5、ES6、ES7等規範中 中新定義的各種對象、方法的模擬實現。
regenerator:提供generator支持,如果應用代碼中用到generator、async函數的話用到。

引入babel-polyfill全量包後文件會變得非常大。

③ 以上方式需要在對應入口js文件開頭引入polyfillimport “@babel/polyfill”;
這種方式會產生一些全局變量,代碼量大了之後如寫一個大型庫或者ui組件庫等全局變量會產生變量污染全局。這樣就需要用到 transform-runtime,它不會污染全局環境:
npm install --save-dev @babel/plugin-transform-runtime

npm install --save @babel/runtime @babel/runtime-corejs2

刪除對應文件開頭的引入 import “@babel/polyfill”;

.babelrc 文件設置如下:

{
“plugins”: [["@babel/plugin-transform-runtime",
{
“absoluteRuntime”: false,
“corejs”: 2,
“helpers”: true,
“regenerator”: true,
“useESModules”: false,
}]],
}
@babel/plugin-transform-runtime 會以閉包的形式

16、Tree Shaking
Tree Shaking 用來檢測項目中沒有被引用的代碼(dead-code),Webpack會對這部分代碼進行標記,然後在資源壓縮打包的時候,從打包出來的文件中去掉,如下示例:
// outer.js

export const foo = () => {
console.log(‘Fucked Up’);
};

export const bar = () => {
console.log(‘Beyond All Repair’);
};

// index.js
import { foo } from ‘./outer’;

foo();
然後配置webpack.config.js文件,添加如下mode和optimization2個配置:

// webpack.config.js
mode: ‘development’,
optimization: {
usedExports: true,
},
然後打包,打開打包好的文件,可以看到如下部分:

// “./src/outer.js”:
/
!
!
!
./src/outer.js ***!
*
****/
/
! exports provided: foo, bar /
/
! exports used: foo /
/
**/ (function(module, webpack_exports, webpack_require) {

“use strict”;
eval("/* harmony export (binding) / webpack_require.d(webpack_exports, “a”, function() { return foo; });\n/ unused harmony export bar */\nvar foo = function foo() {\n console.log(‘Fucked Up’);\n};\nvar bar = function bar() {\n console.log(‘Beyond All Repair’);\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvb3V0ZXIuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvb3V0ZXIuanM/NGJlZiJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgZm9vID0gKCkgPT4ge1xuICBjb25zb2xlLmxvZygnRnVja2VkIFVwJyk7XG59O1xuXG5leHBvcnQgY29uc3QgYmFyID0gKCkgPT4ge1xuICBjb25zb2xlLmxvZygnQmV5b25kIEFsbCBSZXBhaXInKTtcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/outer.js\n");

/***/ })
其中有2行註釋說明了:

/*! exports provided: foo, bar /
/
! exports used: foo */
就是打包文件中還是導出了foo和bar兩個方法,但只用到了foo,這說明在development中代碼的tree shaking只是找出來了並告知了,但並沒有真的去刪除這部分沒用到的代碼,webpack4新增了mode,將其設置爲production後,不用設置optimization,就會真實執行tree shaking:

// webpack.config.js
mode: ‘production’,
因爲設置了mode: 'production’後代碼被作了minify(壓縮)和 mangle(混淆破壞),foo和bar方法已經搜不到了,但是方法體中的console內容還是可以搜的,可以發現,foo中的console內容Fucked Up還可以搜到,而bar中的console內容Beyond All Repair已經搜不到了,因爲已經被刪除了。

webpack4新增了一個例外處理的口子,就是在package.json中配置一個sideEffects屬性,來設置哪些文件是永遠都不會被刪除掉的,如果設置了sideEffects: false,那麼則會正常的刪除未被用到的代碼。如果設置了sideEffects: ["@babel/polly-fill"]則表明,即便@babel/polly-fill沒被直接應用,但還是會在打包時,將它打包進來。

Tree Shaking的注意事項(來至官網):
使用 ES2015 模塊語法(即 import 和 export)。
確保沒有 compiler 將 ES2015 模塊語法轉換爲 CommonJS 模塊(這也是流行的 Babel preset 中 @babel/preset-env 的默認行爲)。
在項目 package.json 文件中,添加一個 “sideEffects” 屬性。
通過將 mode 選項設置爲 production ,啓用 minification (代碼壓縮) 和 tree shaking。
17、Mode: development/production
wenpack4新增了mode配置:

設置mode: ‘development’
會將 process.env.NODE_ENV 的值設爲 development
啓用 NamedChunksPlugin 和 NamedModulesPlugin。
設置mode: ‘production’
會將 process.env.NODE_ENV 的值設爲 production
啓用 FlagDependencyUsagePlugin
FlagIncludedChunksPlugin
ModuleConcatenationPlugin
NoEmitOnErrorsPlugin
OccurrenceOrderPlugin
SideEffectsFlagPlugin
UglifyJsPlugin
0人點贊
Code.life

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章