這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、Git 1. git 和 svn 的區別 git 和 svn 最大的區別在於 git 是分散式的,而 svn 是集中式的。因此我們不能再離線的情況下使用 svn。如果伺服器出現問題,就沒有辦法使用 svn 來提交代碼。 svn 中的分 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
一、Git
1. git 和 svn 的區別
- git 和 svn 最大的區別在於 git 是分散式的,而 svn 是集中式的。因此我們不能再離線的情況下使用 svn。如果伺服器出現問題,就沒有辦法使用 svn 來提交代碼。
- svn 中的分支是整個版本庫的複製的一份完整目錄,而 git 的分支是指針指向某次提交,因此 git 的分支創建更加開銷更小並且分支上的變化不會影響到其他人。svn 的分支變化會影響到所有的人。
- svn 的指令相對於 git 來說要簡單一些,比 git 更容易上手。
- GIT把內容按元數據方式存儲,而SVN是按文件:因為git目錄是處於個人機器上的一個克隆版的版本庫,它擁有中心版本庫上所有的東西,例如標簽,分支,版本記錄等。
- GIT分支和SVN的分支不同:svn會發生分支遺漏的情況,而git可以同一個工作目錄下快速的在幾個分支間切換,很容易發現未被合併的分支,簡單而快捷的合併這些文件。
- GIT沒有一個全局的版本號,而SVN有
- GIT的內容完整性要優於SVN:GIT的內容存儲使用的是SHA-1哈希演算法。這能確保代碼內容的完整性,確保在遇到磁碟故障和網路問題時降低對版本庫的破壞
2. 經常使用的 git 命令?
git init // 新建 git 代碼庫 git add // 添加指定文件到暫存區 git rm // 刪除工作區文件,並且將這次刪除放入暫存區 git commit -m [message] // 提交暫存區到倉庫區 git branch // 列出所有分支 git checkout -b [branch] // 新建一個分支,並切換到該分支 git status // 顯示有變更文件的狀態
3. git pull 和 git fetch 的區別
- git fetch 只是將遠程倉庫的變化下載下來,並沒有和本地分支合併。
- git pull 會將遠程倉庫的變化下載下來,並和當前分支合併。
4. git rebase 和 git merge 的區別
git merge 和 git rebase 都是用於分支合併,關鍵在 commit 記錄的處理上不同:
- git merge 會新建一個新的 commit 對象,然後兩個分支以前的 commit 記錄都指向這個新 commit 記錄。這種方法會保留之前每個分支的 commit 歷史。
- git rebase 會先找到兩個分支的第一個共同的 commit 祖先記錄,然後將提取當前分支這之後的所有 commit 記錄,然後將這個 commit 記錄添加到目標分支的最新提交後面。經過這個合併後,兩個分支合併後的 commit 記錄就變為了線性的記錄了。
二、Webpack
1. webpack與grunt、gulp的不同?
Grunt、Gulp是基於任務運⾏的⼯具: 它們會⾃動執⾏指定的任務,就像流⽔線,把資源放上去然後通過不同插件進⾏加⼯,它們包含活躍的社區,豐富的插件,能⽅便的打造各種⼯作流。
Webpack是基於模塊化打包的⼯具: ⾃動化處理模塊,webpack把⼀切當成模塊,當 webpack 處理應⽤程式時,它會遞歸地構建⼀個依賴關係圖 (dependency graph),其中包含應⽤程式需要的每個模塊,然後將所有這些模塊打包成⼀個或多個 bundle。
因此這是完全不同的兩類⼯具,⽽現在主流的⽅式是⽤npm script代替Grunt、Gulp,npm script同樣可以打造任務流。
2. webpack、rollup、parcel優劣?
- webpack適⽤於⼤型複雜的前端站點構建: webpack有強⼤的loader和插件⽣態,打包後的⽂件實際上就是⼀個⽴即執⾏函數,這個⽴即執⾏函數接收⼀個參數,這個參數是模塊對象,鍵為各個模塊的路徑,值為模塊內容。⽴即執⾏函數內部則處理模塊之間的引⽤,執⾏模塊等,這種情況更適合⽂件依賴複雜的應⽤開發。
- rollup適⽤於基礎庫的打包,如vue、d3等: Rollup 就是將各個模塊打包進⼀個⽂件中,並且通過 Tree-shaking 來刪除⽆⽤的代碼,可以最⼤程度上降低代碼體積,但是rollup沒有webpack如此多的的如代碼分割、按需載入等⾼級功能,其更聚焦於庫的打包,因此更適合庫的開發。
- parcel適⽤於簡單的實驗性項⽬: 他可以滿⾜低⻔檻的快速看到效果,但是⽣態差、報錯信息不夠全⾯都是他的硬傷,除了⼀些玩具項⽬或者實驗項⽬不建議使⽤。
3. 有哪些常⻅的Loader?
- file-loader:把⽂件輸出到⼀個⽂件夾中,在代碼中通過相對 URL 去引⽤輸出的⽂件
- url-loader:和 file-loader 類似,但是能在⽂件很⼩的情況下以 base64 的⽅式把⽂件內容註⼊到代碼中去
- source-map-loader:載入額外的 Source Map ⽂件,以⽅便斷點調試
- image-loader:載入並且壓縮圖⽚⽂件
- babel-loader:把 ES6 轉換成 ES5
- css-loader:載入 CSS,⽀持模塊化、壓縮、⽂件導⼊等特性
- style-loader:把 CSS 代碼註⼊到 JavaScript 中,通過 DOM 操作去載入 CSS。
- eslint-loader:通過 ESLint 檢查 JavaScript 代碼
註意:在Webpack中,loader的執行順序是從右向左執行的。因為webpack選擇了compose這樣的函數式編程方式,這種方式的表達式執行是從右向左的。
4. 有哪些常⻅的Plugin?
- define-plugin:定義環境變數
- html-webpack-plugin:簡化html⽂件創建
- uglifyjs-webpack-plugin:通過 UglifyES 壓縮 ES6 代碼
- webpack-parallel-uglify-plugin: 多核壓縮,提⾼壓縮速度
- webpack-bundle-analyzer: 可視化webpack輸出⽂件的體積
- mini-css-extract-plugin: CSS提取到單獨的⽂件中,⽀持按需載入
5. bundle,chunk,module是什麼?
- bundle:是由webpack打包出來的⽂件;
- chunk:代碼塊,⼀個chunk由多個模塊組合⽽成,⽤於代碼的合併和分割;
- module:是開發中的單個模塊,在webpack的世界,⼀切皆模塊,⼀個模塊對應⼀個⽂件,webpack會從配置的 entry中遞歸開始找出所有依賴的模塊。
6. Loader和Plugin的不同?
不同的作⽤:
- Loader直譯為"載入器"。Webpack將⼀切⽂件視為模塊,但是webpack原⽣是只能解析js⽂件,如果想將其他⽂件也打包的話,就會⽤到 loader 。 所以Loader的作⽤是讓webpack擁有了載入和解析⾮JavaScript⽂件的能⼒。
- Plugin直譯為"插件"。Plugin可以擴展webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 運⾏的⽣命周期中會⼴播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
不同的⽤法:
- Loader在 module.rules 中配置,也就是說他作為模塊的解析規則⽽存在。 類型為數組,每⼀項都是⼀個 Object ,⾥⾯描述了對於什麼類型的⽂件( test ),使⽤什麼載入( loader )和使⽤的參數( options )
- Plugin在 plugins 中單獨配置。 類型為數組,每⼀項是⼀個 plugin 的實例,參數都通過構造函數傳⼊。
7. webpack的構建流程?
Webpack 的運⾏流程是⼀個串⾏的過程,從啟動到結束會依次執⾏以下流程:
- 初始化參數:從配置⽂件和 Shell 語句中讀取與合併參數,得出最終的參數;
- 開始編譯:⽤上⼀步得到的參數初始化 Compiler 對象,載入所有配置的插件,執⾏對象的 run ⽅法開始執⾏編譯;
- 確定⼊⼝:根據配置中的 entry 找出所有的⼊⼝⽂件;
- 編譯模塊:從⼊⼝⽂件出發,調⽤所有配置的 Loader 對模塊進⾏翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到所有⼊⼝依賴的⽂件都經過了本步驟的處理;
- 完成模塊編譯:在經過第4步使⽤ Loader 翻譯完所有模塊後,得到了每個模塊被翻譯後的最終內容以及它們之間的依賴關係;
- 輸出資源:根據⼊⼝和模塊之間的依賴關係,組裝成⼀個個包含多個模塊的 Chunk,再把每個 Chunk 轉換成⼀個單獨的⽂件加⼊到輸出列表,這步是可以修改輸出內容的最後機會;
- 輸出完成:在確定好輸出內容後,根據配置確定輸出的路徑和⽂件名,把⽂件內容寫⼊到⽂件系統。
在以上過程中,Webpack 會在特定的時間點⼴播出特定的事件,插件在監聽到感興趣的事件後會執⾏特定的邏輯,並且插件可以調⽤ Webpack 提供的 API 改變 Webpack 的運⾏結果。
8. 編寫loader或plugin的思路?
Loader像⼀個"翻譯官"把讀到的源⽂件內容轉義成新的⽂件內容,並且每個Loader通過鏈式操作,將源⽂件⼀步步翻譯成想要的樣⼦。
編寫Loader時要遵循單⼀原則,每個Loader只做⼀種"轉義"⼯作。 每個Loader的拿到的是源⽂件內容(source),可以通過返回值的⽅式將處理後的內容輸出,也可以調⽤ this.callback() ⽅法,將內容返回給webpack。 還可以通過this.async() ⽣成⼀個 callback 函數,再⽤這個callback將處理後的內容輸出出去。 此外 webpack 還為開發者準備了開發loader的⼯具函數集——loader-utils 。
相對於Loader⽽⾔,Plugin的編寫就靈活了許多。 webpack在運⾏的⽣命周期中會⼴播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
9. webpack 熱更新的實現原理?
webpack的熱更新⼜稱熱替換(Hot Module Replacement),縮寫為HMR。 這個機制可以做到不⽤刷新瀏覽器⽽將新變更的模塊替換掉舊的模塊。
原理:
⾸先要知道server端和client端都做了處理⼯作:
- 第⼀步,在 webpack 的 watch 模式下,⽂件系統中某⼀個⽂件發⽣修改,webpack 監聽到⽂件變化,根據配置⽂
件對模塊重新編譯打包,並將打包後的代碼通過簡單的 JavaScript 對象保存在記憶體中。
- 第⼆步是 webpack-dev-server 和 webpack 之間的接⼝交互,⽽在這⼀步,主要是 dev-server 的中間件 webpack- dev-middleware 和 webpack 之間的交互,webpack-dev-middleware 調⽤ webpack 暴露的 API對代碼變化進⾏監 控,並且告訴 webpack,將代碼打包到記憶體中。
- 第三步是 webpack-dev-server 對⽂件變化的⼀個監控,這⼀步不同於第⼀步,並不是監控代碼變化重新打包。當我們在配置⽂件中配置了devServer.watchContentBase 為 true 的時候,Server 會監聽這些配置⽂件夾中靜態⽂件的變化,變化後會通知瀏覽器端對應⽤進⾏ live reload。註意,這⼉是瀏覽器刷新,和 HMR 是兩個概念。
- 第四步也是 webpack-dev-server 代碼的⼯作,該步驟主要是通過 sockjs(webpack-dev-server 的依賴)在瀏覽器端和服務端之間建⽴⼀個 websocket ⻓連接,將 webpack 編譯打包的各個階段的狀態信息告知瀏覽器端,同時也包括第三步中 Server 監聽靜態⽂件變化的信息。瀏覽器端根據這些 socket 消息進⾏不同的操作。當然服務端傳遞的最主要信息還是新模塊的 hash 值,後⾯的步驟根據這⼀ hash 值來進⾏模塊熱替換。
- webpack-dev-server/client 端並不能夠請求更新的代碼,也不會執⾏熱更模塊操作,⽽把這些⼯作⼜交回給了webpack,webpack/hot/dev-server 的⼯作就是根據 webpack-dev-server/client 傳給它的信息以及 dev-server 的配置決定是刷新瀏覽器呢還是進⾏模塊熱更新。當然如果僅僅是刷新瀏覽器,也就沒有後⾯那些步驟了。
- HotModuleReplacement.runtime 是客戶端 HMR 的中樞,它接收到上⼀步傳遞給他的新模塊的 hash 值,它通過JsonpMainTemplate.runtime 向 server 端發送 Ajax 請求,服務端返回⼀個 json,該 json 包含了所有要更新的模塊的 hash 值,獲取到更新列表後,該模塊再次通過 jsonp 請求,獲取到最新的模塊代碼。這就是上圖中 7、8、9 步驟。
- ⽽第 10 步是決定 HMR 成功與否的關鍵步驟,在該步驟中,HotModulePlugin 將會對新舊模塊進⾏對⽐,決定是否更新模塊,在決定更新模塊後,檢查模塊之間的依賴關係,更新模塊的同時更新模塊間的依賴引⽤。
- 最後⼀步,當 HMR 失敗後,回退到 live reload 操作,也就是進⾏瀏覽器刷新來獲取最新打包代碼。
10. 如何⽤webpack來優化前端性能?
⽤webpack優化前端性能是指優化webpack的輸出結果,讓打包的最終結果在瀏覽器運⾏快速⾼效。
- 壓縮代碼:刪除多餘的代碼、註釋、簡化代碼的寫法等等⽅式。可以利⽤webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 來壓縮JS⽂件, 利⽤ cssnano (css-loader?minimize)來壓縮css
- 利⽤CDN加速: 在構建過程中,將引⽤的靜態資源路徑修改為CDN上對應的路徑。可以利⽤webpack對於 output 參數和各loader的 publicPath 參數來修改資源路徑
- Tree Shaking: 將代碼中永遠不會⾛到的⽚段刪除掉。可以通過在啟動webpack時追加參數 --optimize-minimize 來實現
- Code Splitting: 將代碼按路由維度或者組件分塊(chunk),這樣做到按需載入,同時可以充分利⽤瀏覽器緩存
- 提取公共第三⽅庫: SplitChunksPlugin插件來進⾏公共模塊抽取,利⽤瀏覽器緩存可以⻓期緩存這些⽆需頻繁變動的公共代碼
11. 如何提⾼webpack的打包速度?
- happypack: 利⽤進程並⾏編譯loader,利⽤緩存來使得 rebuild 更快,遺憾的是作者表示已經不會繼續開發此項⽬,類似的替代者是thread-loader
- 外部擴展(externals): 將不怎麼需要更新的第三⽅庫脫離webpack打包,不被打⼊bundle中,從⽽減少打包時間,⽐如jQuery⽤script標簽引⼊
- dll: 採⽤webpack的 DllPlugin 和 DllReferencePlugin 引⼊dll,讓⼀些基本不會改動的代碼先打包成靜態資源,避免反覆編譯浪費時間
- 利⽤緩存: webpack.cache 、babel-loader.cacheDirectory、 HappyPack.cache 都可以利⽤緩存提⾼rebuild效率縮⼩⽂件搜索範圍: ⽐如babel-loader插件,如果你的⽂件僅存在於src中,那麼可以 include: path.resolve(__dirname,'src') ,當然絕⼤多數情況下這種操作的提升有限,除⾮不⼩⼼build了node_modules⽂件
12. 如何提⾼webpack的構建速度?
- 多⼊⼝情況下,使⽤ CommonsChunkPlugin 來提取公共代碼
- 通過 externals 配置來提取常⽤庫
- 利⽤ DllPlugin 和 DllReferencePlugin 預編譯資源模塊 通過 DllPlugin 來對那些我們引⽤但是絕對不會修改的npm包來進⾏預編譯,再通過 DllReferencePlugin 將預編譯的模塊載入進來。
- 使⽤ Happypack 實現多線程加速編譯
- 使⽤ webpack-uglify-parallel 來提升 uglifyPlugin 的壓縮速度。 原理上 webpack-uglify-parallel 採⽤了多核並⾏壓縮來提升壓縮速度
- 使⽤ Tree-shaking 和 Scope Hoisting 來剔除多餘代碼
13. 怎麼配置單⻚應⽤?怎麼配置多⻚應⽤?
單⻚應⽤可以理解為webpack的標準模式,直接在 entry 中指定單⻚應⽤的⼊⼝即可,這⾥不再贅述多⻚應⽤的話,可以使⽤webpack的 AutoWebPlugin 來完成簡單⾃動化的構建,但是前提是項⽬的⽬錄結構必須遵守他預設的規範。 多⻚應⽤中要註意的是:
- 每個⻚⾯都有公共的代碼,可以將這些代碼抽離出來,避免重覆的載入。⽐如,每個⻚⾯都引⽤了同⼀套css樣式表
- 隨著業務的不斷擴展,⻚⾯可能會不斷的追加,所以⼀定要讓⼊⼝的配置⾜夠靈活,避免每次添加新⻚⾯還需要修改構建配置
三、其他
1. Babel的原理是什麼?
babel 的轉譯過程也分為三個階段,這三步具體是:
- 解析 Parse: 將代碼解析⽣成抽象語法樹(AST),即詞法分析與語法分析的過程;
- 轉換 Transform: 對於 AST 進⾏變換⼀系列的操作,babel 接受得到 AST 並通過 babel-traverse 對其進⾏遍歷,在此過程中進⾏添加、更新及移除等操作;
- ⽣成 Generate: 將變換後的 AST 再轉換為 JS 代碼, 使⽤到的模塊是 babel-generator。