摘要:配置以何種方式導出庫。當檢測文件不再發生變化,會先緩存起來,等等待一段時間后之后再通知監聽者,這個等待時間通過配置。發布到線上給用戶使用的運行環境。
一 縮小文件搜索范圍 1 include & exclude 1) action
限制編譯范圍
2) useagemodule: { rules: [ { test: /.js$/, use: ["babel-loader?cacheDirectory"], include: path.resolve(__dirname, "src"), exclude: /node_modules/ } ] }
"babel-loader?cacheDirectory"
You can also speed up babel-loader by as much as 2x by using the cacheDirectory option. This will cache transformations to the filesystem.
QA[BABEL] Note: The code generator has deoptimised the styling of "/Users/xxx/Documents/xxx/webpack_test/test3/node_modules/lodash/lodash.js" as it exceeds the max of "500KB".
加上exclude限制范圍就不會報錯了
2 resolve.modules 1) actionTell webpack what directories should be searched when resolving modules.
2) useageresolve: { modules: [path.resolve("node_modules"), path.resolve("lib")] }3) note
Absolute and relative paths can both be used, but be aware that they will behave a bit differently.
A relative path will be scanned similarly to how Node scans for node_modules, by looking through the current directory as well as it"s ancestors (i.e. ./node_modules, ../node_modules, and on).
With an absolute path, it will only search in the given directory.
If you want to add a directory to search in that takes precedence over node_modules/:(即是有先后順序的)
modules: [path.resolve(__dirname, "src"), "node_modules"]4) QA
Module not found: Error: Can"t resolve "ajax" in "/Users/xxx/Documents/xxx/webpack_test/test3/src"
當你需要指定除node_modules之外的其它模塊目錄的時候可以在數組中添加屬性
3 resolve.mainFields 1) actionWebpack 配置中的 resolve.mainFields 用于配置第三方模塊使用哪個入口文件。
安裝的第三方模塊中都會有一個 package.json文件,用于描述這個模塊的屬性,其中有些字段用于描述入口文件在哪里,resolve.mainFields 用于配置采用哪個字段作為入口文件的描述。
可以存在多個字段描述入口文件的原因是因為有些模塊可以同時用在多個環境中,針對不同的運行環境需要使用不同的代碼。 以 isomorphic-fetch API 為例,它是 Promise的一個實現,但可同時用于瀏覽器和 Node.js 環境。
2) useage為了減少搜索步驟,在你明確第三方模塊的入口文件描述字段時,你可以把它設置的盡量少。 由于大多數第三方模塊都采用 main字段去描述入口文件的位置,可以這樣配置 Webpack:
module.exports = { resolve: { // 只采用 main 字段作為入口文件描述字段,以減少搜索步驟 mainFields: ["main"], }, };4 resolve.alias 1) action
配置項通過別名來把原導入路徑映射成一個新的導入路徑
此優化方法會影響使用Tree-Shaking去除無效代碼
2) useagealias: { "bootstrap": "bootstrap/dist/css/bootstrap.css" }5 resolve.extensions 1) action
在導入語句沒帶文件后綴時,Webpack會自動帶上后綴后去嘗試詢問文件是否存在 -
默認后綴是 extensions: [".js", ".json"]
2) useage 3) note后綴列表盡可能小
頻率最高的往前方
導出語句里盡可能帶上后綴
6 module.noParse 1) actionmodule.noParse 配置項可以讓 Webpack 忽略對部分沒采用模塊化的文件的遞歸解析處理
2) useagemodule: { noParse: [/react.min.js/] }2) note
被忽略掉的文件里不應該包含 import 、 require 、 define 等模塊化語句二 DLL 1 action
dll 為后綴的文件稱為動態鏈接庫,在一個動態鏈接庫中可以包含給其他模塊調用的函數和數據
把基礎模塊獨立出來打包到多帶帶的動態連接庫里
當需要導入的模塊在動態連接庫里的時候,模塊不能再次被打包,而是去動態連接庫里獲取
2 usage定義插件(DLLPlugin) ---> 引用插件(DllReferencePlugin)
本次例子用jquery舉例
1) 定義DLL用于打包出一個個動態連接庫
需要多帶帶build
webpack.jquery.config.js
module.exports = { entry: ["jquery"], output: { filename: "vendor.js", path: path.resolve(__dirname, "dist"), libraryTarget: "var",// 打包的方式,hou library: "vendor_lib_vendor"http:// DLL的名字 }, plugins: [ new webpack.DllPlugin({ name: "vendor_lib_vendor",// 定義DLL path: path.resolve(__dirname, "dist/vendor-manifest.json") }) ] };
package.json 的scripts添加
"dll": "webpack --config webpack.jquery.config.js --mode development"
配置好上述的文件后,在終端運行 npm run dll,時候會在dist目錄下生成兩個文件,分別是vendor.js 和 vendor-manifest.json。vendor.js包含的就是打包后的jquery文件代碼,vendor-manifest.json是用來做關聯的。DLL定義好了,接下來就是應用打包好的DLL了。
2) 引用DLLwebpack.config.js 配置文件中引入DllPlugin插件打包好的動態連接庫
plugins: [ new webpack.DllReferencePlugin({ context: __dirname, manifest: require("./dist/vendor-manifest.json") }) ],3) 使用DLL
app.html3 note
在app.html的底部添加
libraryTarget 和 library
當用 Webpack 去構建一個可以被其他模塊導入使用的庫時需要用到它們。
output.libraryTarget 配置以何種方式導出庫。
output.library 配置導出庫的名稱。 它們通常搭配在一起使用。
output.libraryTarget 是字符串的枚舉類型,支持以下配置。
1) var (默認)編寫的庫將通過 var 被賦值給通過 library 指定名稱的變量。
假如配置了 output.library="LibraryName",則輸出和使用的代碼如下:
// Webpack 輸出的代碼 var LibraryName = lib_code; //其中 lib_code 代指導出庫的代碼內容,是有返回值的一個自執行函數。 // 使用庫的方法 LibraryName.doSomething();2) commonjs2
編寫的庫將通過 CommonJS 規范導出。
假如配置了 output.library="LibraryName",則輸出和使用的代碼如下:
// Webpack 輸出的代碼 exports["LibraryName"] = lib_code; // 使用庫的方法 require("library-name-in-npm")["LibraryName"].doSomething(); // 其中 library-name-in-npm 是指模塊發布到 Npm 代碼倉庫時的名稱。3) commonjs2
編寫的庫將通過 CommonJS2 規范導出,輸出和使用的代碼如下:
// Webpack 輸出的代碼 module.exports = lib_code; // 使用庫的方法 require("library-name-in-npm").doSomething();
CommonJS2 和 CommonJS 規范很相似,差別在于 CommonJS 只能用 exports 導出,而 CommonJS2 在 CommonJS 的基礎上增加了 module.exports 的導出方式。
在 output.libraryTarget 為 commonjs2 時,配置 output.library 將沒有意義。
編寫的庫將通過 this 被賦值給通過 library 指定的名稱,輸出和使用的代碼如下:
// Webpack 輸出的代碼 this["LibraryName"] = lib_code; // 使用庫的方法 this.LibraryName.doSomething();5) window
編寫的庫將通過 window 被賦值給通過 library 指定的名稱,即把庫掛載到 window 上,輸出和使用的代碼如下:
// Webpack 輸出的代碼 window["LibraryName"] = lib_code; // 使用庫的方法 window.LibraryName.doSomething();6) global
編寫的庫將通過 global 被賦值給通過 library 指定的名稱,即把庫掛載到 global 上,輸出和使用的代碼如下:
// Webpack 輸出的代碼 global["LibraryName"] = lib_code; // 使用庫的方法 global.LibraryName.doSomething();三 HappyPack 1 action
HappyPack就能讓Webpack把任務分解給多個子進程去并發的執行,子進程處理完后再把結果發送給主進程。
2 usageinstall
由于webpack 4.0 剛剛發布,響應的插件還沒有更新完,不過可以在后面加一個@next來安裝即將發布的版本
npm i happypack@next -D
webpack.config.js
module: { rules: [ { test: /.css$/, use: "happypack/loader?id=css", //把對.js文件的處理轉交給id為babel的HappyPack實例 //用唯一的標識符id來代表當前的HappyPack是用來處理一類特定文件 include: path.resolve("./src"), exclude: /node_modules/ }, { test: /.js/, use: "happypack/loader?id=babel", include: path.resolve("./src"), exclude: /node_modules/ } ] }, plugins: [ new HtmlWebPackPlugin({ template: "./src/index.html" }), new HappyPack({ id: "babel", loaders: ["babel-loader"]// 和rules里的配置相同 }), new HappyPack({ id: "css", loaders: ["style-loader", "css-loader"]// 和rules里的配置相同 }), ]四 ParallelUglifyPlugin 1.action
可以把對JS文件的串行壓縮變為開啟多個子進程并行執行
2 usageinsatll
npm install webpack-parallel-uglify-plugin -D
webpackage.config.js
new ParallelUglifyPlugin({ workerCount: os.cpus().length - 1,//開啟幾個子進程去并發的執行壓縮。默認是當前運行電腦的 CPU 核數減去1 uglifyJS: { output: { beautify: false, //不需要格式化 comments: true, //不保留注釋 }, compress: { warnings: false, // 在UglifyJs刪除沒有用到的代碼時不輸出警告 drop_console: true, // 刪除所有的 `console` 語句,可以兼容ie瀏覽器 collapse_vars: true, // 內嵌定義了但是只用到一次的變量 reduce_vars: true, // 提取出出現多次但是沒有定義成變量去引用的靜態值 } } })五 服務器自動刷新 1 文件監聽 1) action
可以監聽文件變化,當文件發生變化的時候重新編譯
2) useagewatch: true, watchOptions: { ignored: /node_modules/, aggregateTimeout: 300, poll: 1 }3) note
watch
只有在開啟監聽模式時(watch為true),watchOptions才有意義
aggregateTimeout
監聽到變化發生后等300(ms)再去執行動作,防止文件更新太快導致編譯頻率太高
poll
通過不停的詢問文件是否改變來判斷文件是否發生變化,默認每秒詢問1000次
文件監聽流程
webpack定時獲取文件的更新時間,并跟上次保存的時間進行比對,不一致就表示發生了變化,poll就用來配置每秒問多少次。
當檢測文件不再發生變化,會先緩存起來,等等待一段時間后之后再通知監聽者,這個等待時間通過aggregateTimeout配置。
webpack只會監聽entry依賴的文件
我們需要盡可能減少需要監聽的文件數量和檢查頻率,當然頻率的降低會導致靈敏度下降。
devServer: { inline: true },2) note
webpack負責監聽文件變化,webpack-dev-server負責刷新瀏覽器。這些文件會被打包到chunk中,它們會代理客戶端向服務器發起WebSocket連接
3 模塊熱替換 1) action模塊熱替換(Hot Module Replacement)的技術可在不刷新整個網頁的情況下只更新指定的模塊.
原理是當一個源碼發生變化時,只重新編譯發生變化的模塊,再用新輸出的模塊替換掉瀏覽器中對應的老模塊
2) 優點反應更快,時間更短
不刷新網頁可以保留網頁運行狀態
監聽更少的文件
忽略掉 node_modules 目錄下的文件
2) usewebpack.config.js
devServer: { hot:true//將hot設置為true }, // 需要的插件 plugins: [ new webpack.NamedModulesPlugin(),//顯示模塊的相對路徑 new webpack.HotModuleReplacementPlugin()// 啟動熱加載功能 ]
code
if (module.hot) { module.hot.accept("./hot.js", () => { let hot = require("./hot"); document.getElementById("app2").innerHTML = hot + "1"; }) }3 note
需要熱加載的模塊需要在初始化的時候引入到模塊中,否則不會觸發HMR。六 區分環境 1 action
在開發網頁的時候,一般都會有多套運行環境,例如,在開發過程中方便開發調試的環境。發布到線上給用戶使用的運行環境。
線上的環境和開發環境區別主要有以下不同:
線上的代碼被壓縮
開發環境可能會打印只有開發者才能看到的日志
開發環境和線上環境后端數據接口可能不同
2 usagepackage.json
cross-env跨平臺設置環境變量(后面沒有&&)
"scripts": { "build-dev": "cross-env NODE_ENV=development webpack --mode development", "build-prod": "cross-env NODE_ENV=production webpack --mode production" }
webpack.config.js
根據環境變量區分生產環境還是開發環境,然后和webpack.base.config.js合并,生產環境(或者開發環境)的優先級高于webpack.base.config.js的配置。
let merge = require("webpack-merge"); let base = require("./webpack.base.config"); let other = null; if (process.env.NODE_ENV === "development") { other = require("./webpack.dev.config"); } else { other = require("./webapack.prod.config"); } module.exports = merge(base, other);
webpack.base.config.js
基本配置
webpack.DefinePlugin 定義環境變量
基本配置... plugins: [ new webpack.DefinePlugin({ __isDevelopment__: JSON.stringify(process.env.NODE_ENV == "development") }) ]
webpack.dev.config.js
以output舉例,如果開發和生產環境的參數不同,就會覆蓋webpack.base.config.js里面的配置
const path = require("path"); module.exports = { output: { path: path.resolve("./dist"), filename: "[name].dev.[hash:2].js" } };
webpack.prod.config.js
(以output舉例)
const path = require("path"); module.exports = { output: { path: path.resolve("./dist"), filename: "[name].prod.[hash:8].js" } };
base.js
配置文件中的webpack.DefinePlugin定義的變量(__isDevelopment__),在入口文件和入口文件引用的其他文件中都可以獲取到__isDevelopment__的值
let env = null; if (__isDevelopment__) { env = "dev"; } else { env = "prod"; } module.exports = env;
index.js
let env = require("./base.js"); if (__isDevelopment__) { console.log("dev"); } else { console.log("prod"); } console.log("env", env); /* prod env prod */3 note
webpack.DefinePlugin
定義環境變量的值時用 JSON.stringify 包裹字符串的原因是環境變量的值需要是一個由雙引號包裹的字符串,而 JSON.stringify("production")的值正好等于""production""
七 CDNCDN 又叫內容分發網絡,通過把資源部署到世界各地,用戶在訪問時按照就近原則從離用戶最近的服務器獲取資源,從而加速資源的獲取速度。
HTML文件不緩存,放在自己的服務器上,關閉自己服務器的緩存,靜態資源的URL變成指向CDN服務器的地址
靜態的JavaScript、CSS、圖片等文件開啟CDN和緩存,并且文件名帶上HASH值
為了并行加載不阻塞,把不同的靜態資源分配到不同的CDN服務器上
八 Tree Shaking 1 actiontree Shaking 可以用來剔除JavaScript中用不上的死代碼。
2 useage它依賴靜態的ES6模塊化語法,例如通過import和export導入導出
不要編譯ES6模塊
use: { loader: "babel-loader", query: { presets: [ [ "env", { modules: false //含義是關閉 Babel 的模塊轉換功能,保留原本的 ES6 模塊化語法 } ], "react" ] } },3 note
需要注意的是它依賴靜態的ES6模塊化語法,例如通過import和export導入導出。也就是說如果項目代碼運行在不支持es6語法的環境上,Tree Shaking也就沒有意義了。
九 提取公共代碼 1 為什么需要提取公共代碼大網站有多個頁面,每個頁面由于采用相同技術棧和樣式代碼,會包含很多公共代碼,如果都包含進來會有問題
相同的資源被重復的加載,浪費用戶的流量和服務器的成本;
每個頁面需要加載的資源太大,導致網頁首屏加載緩慢,影響用戶體驗。 如果能把公共代碼抽離成多帶帶文件進行加載能進行優化,可以減少網絡傳輸流量,降低服務器成本
不同類型的文件,打包后的代碼塊也不同:
基礎類庫,方便長期緩存
頁面之間的公用代碼
各個頁面多帶帶生成文件
2) usagewebpack.config.js
optimization: { splitChunks: { cacheGroups: { commons: {// 頁面之間的公用代碼 chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, vendor: {// 基礎類庫 chunks: "initial", test: /node_modules/, name: "vendor", priority: 10, enforce: true } } } },
./src/pageA.js
require("./utils/utility1.js"); require("./utils/utility2.js"); require("react");
./src/pageB.js
require("./utils/utility2.js"); require("./utils/utility3.js");
./src/pageC.js
require("./utils/utility2.js"); require("./utils/utility3.js");
utils/utility1.js
module.exports = 1;
utils/utility2.js
module.exports = 2;
utils/utility3.js
module.exports = 3;
打包后的結果
上述三種代碼的生成的結果,如下圖:
Scope Hoisting 可以讓 Webpack 打包出來的代碼文件更小、運行的更快, 它又譯作 "作用域提升",是在 Webpack3 中新推出的功能。
代碼體積更小,因為函數申明語句會產生大量代碼
代碼在運行時因為創建的函數作用域更少了,內存開銷也隨之變小 hello.js
2 useagepackage.json
"build": "webpack --display-optimization-bailout --mode development",
webpack.config.js
plugins: [ new ModuleConcatenationPlugin() ],
./h.js
export default "scope hoist"
./index.js
import str from "./h.js" console.log(str);3 note
必須使用ES6語法,否則不起作用(--display-optimization-bailout 參數會提示)十一 代碼分離
代碼分離是 webpack 中最引人注目的特性之一。此特性能夠把代碼分離到不同的 bundle 中,然后可以按需加載或并行加載這些文件。 有三種常用的代碼分離方法:
入口起點:使用 entry 配置手動地分離代碼。
防止重復:使用 splitChunks 去重和分離 chunk。
動態導入:通過模塊的內聯函數調用來分離代碼。
入口起點和防止重復上面已經提到了,下面我們重點講一下動態導入
1 action用戶當前需要用什么功能就只加載這個功能對應的代碼,也就是所謂的按需加載 在給單頁應用做按需加載優化時,一般采用以下原則:
對網站功能進行劃分,每一類一個chunk
對于首次打開頁面需要的功能直接加載,盡快展示給用戶
某些依賴大量代碼的功能點可以按需加載
被分割出去的代碼需要一個按需加載的時機
2 usage使用import(module)的語法
import 異步 加載 模塊是一個es7的語法
在webpack里import是一個天然的分割點
document.getElementById("play").addEventListener("click",function(){ import("./vedio.js").then(function(video){ let name = video.getName(); console.log(name); }); });參考文檔
webpack官方文檔
webpack官方文檔中文版
webpackGitHub
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93904.html
摘要:剛剛發布,官網自稱最大的特點就是零配置。本文就詳細介紹一下實戰那些事兒。自動刷新監聽本地源代碼的變化,自動重新構建刷新瀏覽器。自動發布更新完代碼后,自動構建出線上發布代碼并傳輸給發布系統。代碼塊,一個由多個模塊組合而成,用于代碼合并與分割。 webpack4.0剛剛發布,官網自稱4.0最大的特點就是零配置。本文就詳細介紹一下webpack4.0實戰那些事兒。 1 什么是WebPack ...
摘要:我們發布了新版本的插件系統,以便事件掛鉤和處理程序是單態的。倒計時按照承諾,我們將從今天開始等待一個月,然后再釋放穩定版。這為我們的插件,加載程序和集成生態系統提供了測試,報告和升級到的時間我們需要您幫助我們升級并測試此測試版。 自8月初以來—當我們將 nex branch?合并到webpack/webpack#master—我們看到了巨大的貢獻! showImg(https://se...
摘要:本文是到家技術總監沈劍在北京站上的演講視頻。全面解析單點系統的可用性架構與優化消息系統的可達性架構與優化事務系統的一致性架構與優化。時長分鐘,建議收藏和轉發后在環境下觀看。沈劍到家技術總監,互聯網架構技術專家,架構師之路公眾號作者。 showImg(https://segmentfault.com/img/bVz49R);本文是58到家技術總監沈劍在MPD2016 北京站上的演講視頻。...
摘要:要快,但是我們的服務也必須萬無一失,后續我會分享百度移動端首頁的前端架構設計那么這樣的優化,是如何做到的呢,又如何兼顧穩定性,架構性,與速度呢別急,讓我們把這些優化一一道來。百度移動端首頁的很多就是這樣緩存在客戶端的。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fronte...
閱讀 3031·2021-11-24 09:39
閱讀 2268·2021-10-08 10:05
閱讀 2758·2021-09-24 13:52
閱讀 1576·2021-09-22 15:07
閱讀 595·2019-08-30 15:55
閱讀 1814·2019-08-30 15:53
閱讀 694·2019-08-30 15:44
閱讀 3122·2019-08-30 11:20