摘要:處理文件的擴展名很多的配置文件都有一個屬性,然后就像下面代碼所示有一個空字符串的值。空字符串在此是為了一些在文件時不帶文件擴展名的表達式,如或者譯者注實際就是自動添加后綴,默認是當成文件來查找路徑就這么多。
原文 Webpack—The Confusing Parts
issue討論
Webpack是目前基于React和Redux開發的應用的主要打包工具。我想使用Angular 2或其他框架開發的應用也有很多在使用Webpack。
當我第一次看到Webpack的配置文件時,它看起來非常的陌生,我非常的疑惑。經過一段時間的嘗試之后我認為這是因為Webpack只是使用了比較特別的語法和引入了新的原理,因此會讓使用者感到疑惑。這些也是導致Webpack不被人熟悉的原因。
因為剛開始使用Webpack很讓人疑惑,我覺得有必要寫幾篇介紹Webpack的功能和特性的文章以幫助初學者快速理解。此文是最開始的一篇。
Webpack的核心原理Webpack的兩個最核心的原理分別是:
1. 一切皆模塊
正如js文件可以是一個“模塊(module)”一樣,其他的(如css、image或html)文件也可視作模 塊。因此,你可以require("myJSfile.js")亦可以require("myCSSfile.css")。這意味著我們可以將事物(業務)分割成更小的易于管理的片段,從而達到重復利用等的目的。
2. 按需加載
傳統的模塊打包工具(module bundlers)最終將所有的模塊編譯生成一個龐大的bundle.js文件。但是在真實的app里邊,“bundle.js”文件可能有10M到15M之大可能會導致應用一直處于加載中狀態。因此Webpack使用許多特性來分割代碼然后生成多個“bundle”文件,而且異步加載部分代碼以實現按需加載。
好了,下面來看看那些令人困惑的部分吧。
1. 開發模式和生產模式首先要知道的是Webpack有許許多多的特性,一些是”開發模式“下才有的,一些是”生產模式“下才有的,還有一些是兩種模式下都有的。
通常使用到Webpack如此多特性的項目都會有兩個比較大的Webpack配置文件
為了生成bundles文件你可能在package.json文件加入如下的scripts項:
"scripts": { // 運行npm run build 來編譯生成生產模式下的bundles "build": "webpack --config webpack.config.prod.js", // 運行npm run dev來生成開發模式下的bundles以及啟動本地server "dev": "webpack-dev-server" }2. webpack CLI 和webpack-dev-server
值得注意的是,Webpack作為模塊打包工具,提供兩種用戶交互接口:
Webpack CLI tool:默認的交互方式(已隨Webpack本身安裝到本地)
webpack-dev-server:一個Node.js服務器(需要開發者從npm自行安裝)
這種方式可以從命令行獲取參數也可以從配置文件(默認叫webpack.config.js)獲取,將獲取到的參數傳入Webpack來打包。
當然你也可以從命令行(CLI)開始學習Webpack,以后你可能主要在生產模式下使用到它。
用法:
方式1: // 全局模式安裝webpack npm install webpack --g // 在終端輸入 $ webpack // <--使用webpack.config.js生成bundle 方式 2 : // 費全局模式安裝webpack然后添加到package.json依賴里邊 npm install webpack --save // 添加build命令到package.json的scripts配置項 "scripts": { "build": "webpack --config webpack.config.prod.js -p", ... } // 用法: "npm run build"
這是一個基于Express.js框架開發的web server,默認監聽8080端口。server內部調用Webpack,這樣做的好處是提供了額外的功能如熱更新“Live Reload”以及熱替換“Hot Module Replacement”(即HMR)。
用法:
方式 1: // 全局安裝 npm install webpack-dev-server --save // 終端輸入 $ webpack-dev-server --inline --hot 用法 2: // 添加到package.json scripts "scripts": { "start": "webpack-dev-server --inline --hot", ... } // 運行: $ npm start // 瀏覽器預覽: http://localhost:8080
注意像inline和hot這些選項是Webpack-dev-server特有的,而另外的如hide-modules則是CLI模式特有的選項。
另外值得注意的是你可以通過以下兩種方式向webpack-dev-server傳入參數:
通過webpack.config.js文件的"devServer"對象
通過CLI選項
// 通過CLI傳參 webpack-dev-server --hot --inline // 通過webpack.config.js傳參 devServer: { inline: true, hot:true }
我發現有時devServer配置項(hot: true 和inline: true)不生效,我更偏向使用如下的方式向CLI傳遞參數:
// package.json { "scripts": "webpack-dev-server --hot --inline" }
注意:確定你沒有同時傳入hot:true和-hot
“inline”選項會為入口頁面添加“熱加載”功能,“hot”選項則開啟“熱替換(Hot Module Reloading)”,即嘗試重新加載組件改變的部分(而不是重新加載整個頁面)。如果兩個參數都傳入,當資源改變時,webpack-dev-server將會先嘗試HRM(即熱替換),如果失敗則重新加載整個入口頁面。
// 當資源發生改變,以下三種方式都會生成新的bundle,但是又有區別: // 1. 不會刷新瀏覽器 $ webpack-dev-server //2. 刷新瀏覽器 $ webpack-dev-server --inline //3. 重新加載改變的部分,HRM失敗則刷新頁面 $ webpack-dev-server --inline --hot3. “entry”:值分別是字符串、數組和對象的情況
Enter配置項告訴Webpack應用的根模塊或起始點在哪里,它的值可以是字符串、數組或對象。這看起來可能令人困惑,因為不同類型的值有著不同的目的。
像絕大多數app一樣,倘若你的應用只有一個單一的入口,enter項的值你可以使用任意類型,最終輸出的結果都是一樣的。
但是,如果你想添加多個彼此不互相依賴的文件,你可以使用數組格式的值。
例如,你可能在html文件里引用了“googleAnalytics.js”文件,可以告訴Webpack將其加到bundle.js的最后。
現在,假設你的應用是多頁面的(multi-page application)而不是SPA,有多個html文件(index.html和profile.html)。然后你通過一個對象告訴Webpack為每一個html生成一個bundle文件。
以下的配置將會生成兩個js文件:indexEntry.js和profileEntry.js分別會在index.html和profile.html中被引用。
用法:
//profile.html //index.html
注意:文件名取自“entry”對象的鍵名。
你也可以在enter對象里使用數組類型,例如下面的配置將會生成3個文件:vender.js(包含三個文件),index.js和profile.js文件。
4. output:“path”項和“publicPath”項output項告訴webpack怎樣存儲輸出結果以及存儲到哪里。output的兩個配置項“path”和“publicPath”可能會造成困惑。
“path”僅僅告訴Webpack結果存儲在哪里,然而“publicPath”項則被許多Webpack的插件用于在生產模式下更新內嵌到css、html文件里的url值。
例如,在localhost(譯者注:即本地開發模式)里的css文件中邊你可能用“./test.png”這樣的url來加載圖片,但是在生產模式下“test.png”文件可能會定位到CDN上并且你的Node.js服務器可能是運行在HeroKu上邊的。這就意味著在生產環境你必須手動更新所有文件里的url為CDN的路徑。
然而你也可以使用Webpack的“publicPath”選項和一些插件來在生產模式下編譯輸出文件時自動更新這些url。
// 開發環境:Server和圖片都是在localhost(域名)下 .image { background-image: url("./test.png"); } // 生產環境:Server部署下HeroKu但是圖片在CDN上 .image { background-image: url("https://someCDN/test.png"); }5. 模塊加載和鏈式模塊加載
模塊加載器是可自由添加的Node模塊,用于將不同類型的文件“load”或“import”并轉換成瀏覽器可以識別的類型,如js、Stylesheet等。更高級的模塊加載器甚至可以支持使用ES6里邊的“require”或“import”引入模塊。
例如,你可以使用babel-loader來將使用ES6語法寫成的文件轉換成ES5:
module: { loaders: [{ test: /.js$/, // 匹配.js文件,如果通過則使用下面的loader exclude: /node_modules/, // 排除node_modules文件夾 loader: "babel" // 使用babel(babel-loader的簡寫)作為loader }]
多個loader可以用在同一個文件上并且被鏈式調用。鏈式調用時從右到左執行且loader之間用“!”來分割。
例如,假設我們有一個名為“myCssFile.css”的css文件,然后我們想將它的內容使用style標簽內聯到最終輸出的html里邊。我們可以使用css-loader和style-loader兩個loader來達到目的。
module: { loaders: [{ test: /.css$/, loader: "style!css" //(short for style-loader!css-loader) }]
這里展示它是如何工作的:
Webpack在模塊顳部搜索在css的依賴項,即Webpack檢查js文件是否有“require("myCssFile.css")”的引用,如果它發現有css的依賴,Webpack將css文件交給“css-loader”去處理
css-loader加載所有的css文件以及css自身的依賴(如,@import 其他css)到JSON對象里,Webpack然后將處理結果傳給“style-loader”
style-loader接受JSON值然后添加一個style標簽并將其內嵌到html文件里
6. loader自身可以配置模塊加載器(loader)自身可以根據傳入不同的參數進行配置。
在下面的例子中,我們可以配置url-loader來將小于1024字節的圖片使用DataUrl替換而大于1024字節的圖片使用url,我們可以用如下兩種方式通過傳入“limit“參數來實現這一目的:
7. .babelrc 文件babal-loader使用”presets“配置項來標識如何將ES6語法轉成ES5以及如何轉換React的JSX成js文件。我們可以用如下的方式使用”query“參數傳入配置:
module: { loaders: [ { test: /.jsx?$/, exclude: /(node_modules|bower_components)/, loader: "babel", query: { presets: ["react", "es2015"] } } ] }
然而在很多項目里babal的配置可能比較大,因此你可以把babal-loader的配置項多帶帶保存在一個名為”.babelrc“的文件中,在執行時babal-loader將會自動加載.babelrc文件。
所以在很多例子里,你可能會看到:
//webpack.config.js module: { loaders: [ { test: /.jsx?$/, exclude: /(node_modules|bower_components)/, loader: "babel" } ] } //.bablerc { presets: ["react", "es2015"] }8. 插件
插件一般都是用于輸出bundle的node模塊。
例如,uglifyJSPlugin獲取bundle.js然后壓縮和混淆內容以減小文件體積。
類似的extract-text-webpack-plugin內部使用css-loader和style-loader來收集所有的css到一個地方最終將結果提取結果到一個獨立的”styles.css“文件,并且在html里邊引用style.css文件。
//webpack.config.js // 獲取所有的.css文件,合并它們的內容然后提取css內容到一個獨立的”styles.css“里 var ETP = require("extract-text-webpack-plugin"); module: { loaders: [ {test: /.css$/, loader:ETP.extract("style-loader","css-loader") } ] }, plugins: [ new ExtractTextPlugin("styles.css") //Extract to styles.css file ] }
注意:如果你只是想把css使用style標簽內聯到html里,你不必使用extract-text-webpack-plugin,僅僅使用css loader和style loader即可:
module: { loaders: [{ test: /.css$/, loader: "style!css" // (short for style-loader!css-loader) }]9. 加載器(loader)和插件
你可能已經意識到了,Loader處理多帶帶的文件級別并且通常作用于包生成之前或生成的過程中。
而插件則是處理包(bundle)或者chunk級別,且通常是bundle生成的最后階段。一些插件如commonschunkplugin甚至更直接修改bundle的生成方式。
10. 處理文件的擴展名很多Webpack的配置文件都有一個resolve屬性,然后就像下面代碼所示有一個空字符串的值。空字符串在此是為了resolve一些在import文件時不帶文件擴展名的表達式,如require("./myJSFile")或者import myJSFile from "./myJSFile"(譯者注:實際就是自動添加后綴,默認是當成js文件來查找路徑)
{ resolve: { extensions: ["", ".js", ".jsx"] } }
就這么多。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79417.html
摘要:通過中的通過選項使用方法通過通過我發現通過設置的配置項有時不起作用。當代碼發生變化時,以下種方式都會重新打包,但是不會重載頁面會重載整個頁面若失敗則加載整個頁面指出了打包入口文件,支持字符串數組和對象三種形式。 【注】本文原發自此處,轉載請注明出處。 本文譯自【Webpack-The Confusing Parts】原文 本文已同步發表在我的博客 前言 webpack是當前最受歡迎的模...
學習的過程中收藏了這些優秀教程和的項目,希望對你有幫助。 github地址, 有不錯的就更新 官方文檔 中文指南 初級教程 webpack-howto 作者:Pete Hunt Webpack 入門指迷 作者:題葉 webpack-demos 作者:ruanyf 一小時包教會 —— webpack 入門指南 作者:VaJoy Larn webpack 入門及實踐 作者:...
摘要:是在谷歌的年開發者峰會上宣布,但穩定的技術和工具終于在月到達。固然也不能保證蘋果將實施這項技術,但這并不重要,你的應用程序仍然可以在中工作,它只是不會從離線執行中受益。我有一種感覺一旦上體驗有明顯提升蘋果將鼓勵支持。 2016年是值得紀念、奇怪的、有點歡騰/可怕的一年,取決于你的觀點。跟其他事件相比僅僅專注于JavaScript可能看起來無關緊要,但它是每個Web開發人員的工作生活中巨...
摘要:是在谷歌的年開發者峰會上宣布,但穩定的技術和工具終于在月到達。固然也不能保證蘋果將實施這項技術,但這并不重要,你的應用程序仍然可以在中工作,它只是不會從離線執行中受益。我有一種感覺一旦上體驗有明顯提升蘋果將鼓勵支持。 2016年是值得紀念、奇怪的、有點歡騰/可怕的一年,取決于你的觀點。跟其他事件相比僅僅專注于JavaScript可能看起來無關緊要,但它是每個Web開發人員的工作生活中巨...
摘要:是在谷歌的年開發者峰會上宣布,但穩定的技術和工具終于在月到達。固然也不能保證蘋果將實施這項技術,但這并不重要,你的應用程序仍然可以在中工作,它只是不會從離線執行中受益。我有一種感覺一旦上體驗有明顯提升蘋果將鼓勵支持。 2016年是值得紀念、奇怪的、有點歡騰/可怕的一年,取決于你的觀點。跟其他事件相比僅僅專注于JavaScript可能看起來無關緊要,但它是每個Web開發人員的工作生活中巨...
閱讀 1386·2019-08-30 12:54
閱讀 1870·2019-08-30 11:16
閱讀 1613·2019-08-30 10:50
閱讀 2448·2019-08-29 16:17
閱讀 1266·2019-08-26 12:17
閱讀 1378·2019-08-26 10:15
閱讀 2387·2019-08-23 18:38
閱讀 785·2019-08-23 17:50