歡迎訪問個人我的博客html
以你喜歡的任意方式,建立項目根目錄,如:vue
mkdir vue-hello
進入項目根目錄,初始化項目包模塊管理文件package.json:node
npm init
命令臺會提示你輸入一堆信息,若是你想簡單一點,能夠添加-y
參數,跳過輸入步驟,生成默認信息:webpack
npm init -y
在項目根目錄下建立源碼目錄結構,一般源碼目錄是src或app,我的喜愛是使用src:git
雖然在本篇文章咱們不會對webpack作太過詳細的介紹,可是依然但願能幫助讀者對webpack擁有更清晰的瞭解,webpack是什麼?github
webpack is a tool to build JavaScript modules in your applicationweb
webpack是一個幫助你的應用構建JavaScript模塊的工具。正則表達式
接下來,咱們介紹幾個知識點幫助理解webpack:模塊化,webpack原理及其與grunt和gulp的比較。express
模塊化 指解決一個複雜問題時自頂向下逐層把系統劃分紅若干模塊的過程。npm
模塊是一個可組合、分解和更換的單元,將一個系統分解成若干模塊,單元;你們遵循必定的規範,各司其職,各自開發不一樣模塊;以後能夠較低成本的將模塊組合起來,構成一個完整的系統,極大方便了團隊成員之間的協助開發,產出效率獲得有效提高。
webpack是一個幫助你的應用構建JavaScript模塊的工具,其本質只能處理JavaScript,那你會疑惑了,不是說使用webpack,能夠很方便的在JavaScript代碼中引用圖片,CSS等資源嘛?是的,這正是webpack的優點,那怎麼實現的呢?這就要涉及到webpack中的一個概念:加載器(loader)。
加載器 是做用於應用資源文件的轉換器,它們是一系列JavaScript函數,接受資源文件的內容作參數,而後返回新的資源(以一個JavaScript模塊的形式返回)。
因此,對於webpack,咱們明確三點:
grunt
打開grunt官網,你能夠看到最醒目的介紹:
The JavaScript Task Runner
,還有一個關鍵字automation
- 自動化,其定位是一個JavaScript的自動化構建任務處理器,幫助開發者自動化處理項目的構建流程;
gulp
gulp官網的定義是:Automate and enhance your workflow
,自動強化項目構建流程,其與grunt的目標一致,都是幫助開發者自動化處理項目的構建流程,不一樣的是gulp實現方式是基於流的,即以流的方式處理文件,而grunt是以二進制方式處理文件,gulp使用性能是要強於grunt的;
總結
首先安裝webpack,npm或yarn均可以,無甚區別:
npm install --save-dev webpack
關於此處的--save
和-dev
參數作簡要說明:
--save
是聲明將安裝依賴添加入package.json文件;"dependencies"
屬性對象內,表示項目依賴;-dev
參數,以聲明其是開發環境依賴;實踐項目使用webpack完成自動化構建,本地服務調試與熱加載,首先在根目錄下建立webpack的配置入口文件webpack.config.js,基本內容結構以下:
var path = require('path'); module.exports = { context: path.resolve(__dirname, 'src/'), entry: { app: './scripts/app.js' }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dist/scripts/') }, module: { loaders: [] }, resolve: { modules:[], alias: {}, extensions: [] }, plugins: [], devServer: {} };
如上,webpack配置文件使用module.exports方式導出配置對象,webpack執行時會默認讀取項目根目錄下webpack.config.js文件,固然能夠手動配置指定一個文件做爲配置文件,咱們不討論,能夠參考webpack文檔,接下來對webpack配置內容作簡要介紹,若是你對webpack使用比較熟悉,能夠跳過此節。
和webpack文件處理相關的幾個配置屬性主要有三個:目錄上下文信息(context), 處理文件入口信息(entry), 文件輸出信息(output)。
設置解析處理文件入口的相對目錄,值爲一個絕對目錄路徑,默認爲當前執行目錄,一般即項目根目錄,在Node中其值與process.cwd()
相同,如:
context: path.resolve(__dirname, 'src/'),
如上即解析爲項目根目錄下的src目錄。
處理文件入口,值能夠是字符串,或數組,或對象,值爲字符串或數組時,即輸出單文件,值爲對象,能夠輸出多文件,輸出文件名稱等信息參考文件輸出信息(output)。
此配置聲明webpack編譯輸出文件的文件名等信息,如:
filename: '[name].js',
聲明文件名就是模塊(chunk)名,對應在entry中定義的入口,你可能還見過[id]
,[hash]
,[chunkhash]
這些用法,現作簡單介紹:
編譯對象,即webpack執行時讀取配置後生成的一個編譯配置對象,包含模塊,待編譯文件,相對於上次編譯的變動文件等諸多信息,須要注意的是該對象在webpack啓動讀取配置文件後造成,在這次編譯過程保持不變。
webpack-dev-server
一塊兒使用。在介紹加載器配置以前,先看看加載器是什麼:
Loaders are transformations that are applied on a resource file of your app. They are functions (running in node.js) that take the source of a resource file as the parameter and return the new source.
加載器是做用於應用資源文件的轉換器,它們是一系列函數,接受資源文件的內容作參數,而後返回新的資源(以一個模塊的形式返回)。
webpack
webpack解析文件時使用的加載器都聲明在module
屬性的loaders
數組中,能夠設置一個或多個加載器。
test
: 待解析文件需匹配的規則,一般以文件後綴名稱匹配文件;include
:待解析文件所處目錄;exclude
: 過濾掉的目錄;loader
:加載器模塊名稱;loaders
多個加載器;webpack支持在resolve
屬性對象中配置模塊解析規則,主要有root
,modules
, alias
和extensions
屬性。
該屬性設置的是在開發代碼中使用require
或import
加載某模塊時,webpack查找該模塊所遵循的查找目錄範圍,如在源代碼中存在:
var utils = require('utils/utils.js');
而root
配置以下:
resolve: { root: [ path.resolve('./src/'), 'node_modules' ] }
webpack編譯時將自動在項目根目錄下的src
目錄內的utils
目錄下查找utils.js
,若存在,則返回,不然進入node_modules
目錄內查找utils.js
模塊。
固然,若未設置resolve.root
屬性值,則webpack默認先從node_modules
查找模塊,而後在根目錄下查找。
注意:resolve.root在webpack v1版本中使用,而在webpack v2 中,使用modules代替,建議使用v2版本,後文也將統一使用modules屬性。
alias,有別名的意思,這裏的做用是設置其餘模塊或路徑的別名,webpack在解析模塊時,將使用配置值替換該別名,如,在未設置alias屬性內容時,即resolve.alias默認是空對象{}
時,咱們在代碼中引用模塊:
var Vue = require('vue/dist/vue.js'); var TopHeader = require('components/header.js');
webpack在編譯代碼時,按resolve.modules
聲明的順序依次查找對應模塊,如按照上一節定義的resolve.modules
:
resolve: { root: [ path.resolve('./src/'), 'node_modules' ] }
查找模塊時,將首先在src/vue/dist/
目錄下尋找vue
模塊,在src/components/
目錄下查找header.js
模塊,查找到後返回,不然進入node_modules
目錄查找。
如今,咱們還能夠經過resolve.alias
爲模塊或路徑聲明一個別名,更方便的聲明加載模塊:
resolve: { alias: { 'vue$': 'vue/dist/vue.js' components: path.resolve(__dirname, 'src/components/') } }
我可使用以下方式加載模塊:
var Vue = require('vue'); var TopHeader = require('components/header.js');
$
符號關於alias
的詳細使用介紹,請參見文檔,本文並非要介紹webpack文檔,在這裏介紹一下聲明的vue$
別名中的$
符號:
這裏的$
符合是正則的文末匹配符,即只有當vue
是最後一級路徑時,webpack纔會將該值解析成別名,進行別名與對應值替換,如vue/test.js
中的vue是不會看成別名解析的,而components/header.js
中的components則會按照聲明的components
別名進行解析,其結果是src/components/header.js
。
該值定義解析模塊時的查找文件的後綴順序,如["", ".js", ".json"]
,會優先返回js文件,其次json文件,而後是其餘文件,注意,這裏數組傳入了一個空字符串,他的做用是在未找到配置中全部列舉的類型文件時,支持webpack返回其餘類型文件。
webpack還支持多種多樣的插件拓展,你可使用它們對你的項目webpack模塊構建過程進行額外處理,如代碼壓縮,圖片等資源提交壓縮,構建異常捕獲和提高,構建流程時間消耗比,等等,而關於這些插件使用的配置在plugins
屬性數組內,將在後續進行介紹。
爲了方便開發和調試,一般都須要在本地主機開啓服務,提供局域網內多終端訪問,而且在文件變動時,實時刷新頁面,正如grunt和gulp中Browsersync
插件提供的功能同樣,webpack可使用webpack-dev-server
模塊實現。
webpack-dev-server是一個Node.js的express服務器,以webpack開發中間件的形式爲webpack包提供服務,當監聽到源碼文件變動時,會自動從新打包,而且支持配置自動刷新瀏覽器,從新加載資源。
因爲該插件只用於開發模式,因此經過如下npm指令安裝:
npm install webpack-dev-server --save-dev
啓用webpack-dev-server
時,其默認開啓8080端口,訪問localhost:8080
返回當前目錄下的index.html
,即執行指令當前目錄下的靜態資源,固然能夠經過指令傳遞參數或在配置文件進行配置指定靜態資源目錄。
另外須要注意的是,開啓
webpack-dev-server
後,變動文件從新打包後,並不會實際輸出到配置的output
目錄,而是在publicPath
屬性聲明的相對路徑所在的內存中讀取。
webpack-dev-server --content-base src/
執行以上指令開啓服務後,webpack-dev-server
將默認在src/
目錄返回靜態資源,固然也能夠在webpack.config.js
配置文件中指定:
devServer: { contentBase: './src' }
訪問http://localhost:8080
和http://localhost:8080/index.html
效果同樣,均返回src
目錄下的index.html
文件。
在前文webpack配置一節中提到output.publicPath
屬性值表示,在瀏覽器訪問webpack output
輸出的文件時的基礎相對路徑,如設置:
output: { path: 'dist/scripts', filename: 'app.js', publicPath: 'assets/' }
則在html文件中引用該app.js
文件的方式以下:
<script src="assets/app.js"></script>
在瀏覽器中訪問app.js
的方式爲:http://localhost:8080/assets/app.js
前面說到webpack-dev-server
支持文件變動時,自動刷新瀏覽器,這也是開發者急需的功能,webpack-dev-server
支持兩種方式實現:
iframe
模式(iframe mode):頁面經過iframe
窗口插入而後變動時自動從新加載;inline
模式(inline mode):經過sock.js(好比websocket協議,輪詢等方式)在頁面嵌入一個小型客戶端與webpack-dev-server
服務器創建鏈接,當發生變動從新打包時,經過此鏈接通知頁面從新加載;使用默認的iframe
模式時,不須要進行任何配置,能夠直接訪問:http://localhost:8080/webpack-dev-server/index.html
便可,如圖,經過iframe
插入咱們的頁面:
注意:
iframe
內部,不會反映在瀏覽器地址欄;要開啓inline
模式,只須要指定--inline
命令行參數或在配置文件中指定inline: true
:
devServer: { contentBase: './src', inline: true }
在此模式下,直接訪問http://localhost:8080/index.html
或http://localhost:8080
便可,此模式與iframe
模式的區別在於:
inline
配置參數;其實inline
模式還能夠配合Node.Js服務運行,以後再介紹,這裏只說明瞭其在HTML文檔中的使用。
除了自動刷新,webpack-dev-server
的另外一大賣點是模塊熱替換,那麼熱替換究竟是什麼?
熱替換,即文件發生變動時,webpack包只替換髮生變動的模塊,而不須要所有替換;瀏覽器不須要徹底從新加載,而能夠直接將變動的模塊注入到運行中的應用。
開啓熱替換功能須要指定--hot
指令參數,或在配置文件中添加:
devServer: { contentBase: './src', inline: true, hot: true }
注意到以上代碼,熱替換須要與inline
模式一塊兒使用,另外須要指定output.publicPath
值。
配置好後還須要使用webpack.HotModuleReplacementPlugin
插件,才能真正啓用熱替換功能:
plugins: [ new webpack.HotModuleReplacementPlugin() ]
一樣的,熱替換能夠搭配Node.js服務一塊兒使用,以後介紹。
如圖,爲每一個文件(app.js, test.js)都實現了HMR熱替換,當發生變動時,只更新變動模塊,而不是從新加載全部文件:
ES6推出以來,廣受Jser們青睞,其確實有不少新特性和新規範,值得咱們深刻學習並使用,能夠參考ECMAScript 6入門,將來全部的JavaScript應用都應該擁抱ES6,不過,目前各大瀏覽器都在推動ES6的實現,在兼容實現以前,咱們還須要過渡性的將其轉換成ES5語法,最通用的方式就是使用babel
轉換。
首先,爲了能使用webpack和babel轉換js代碼,須要使用babel-loader
加載器,另外還須要安裝babel
轉換js的轉換規則插件,如babel-preset-es2015
定義了轉換規則,安裝方式以下:
npm install --save-dev babel-loader babel-preset-es2015
而後在根目錄下建立.babelrc
文件,內容:
{ "presets": ["es2015"] }
在webpack.config.js配置文件中,添加相關loader配置:
module: { loaders: [ { test: /\.(js|vue)$/, exclude: /node_modules/, loader: 'babel-loader' } ] }
其中,test
匹配須要轉換的文件,exclude
匹配不須要轉換的文件或目錄。
咱們須要明白的一點是babel-preset-es2015
能作的,只是轉換ES6代碼成ES5,使得瀏覽器能夠解析執行,可是對於ES6新提出的API,如Promise,Generator等沒法簡單的轉換成ES5代碼,這時就須要babel-polyfill
了,babel-polyfill
是一個墊片,它能夠模擬提供全部的ES6功能和特性,能夠看做是提供了一個模擬的全局ES6環境。
安裝依然很簡單,因爲是墊片,是須要在源碼中使用的,全部指定--save
參數:
npm install --save babel-polyfill
不一樣於babel-preset-es2015
,babel-polyfill
須要直接打包進源碼,並且須要在使用ES6代碼前引入一次:
import 'babel-polyfill'
只須要引入一次,由於該墊片提供的是一個模擬的全局ES6環境,而不是模塊內部的。
或者直接在webpack.config.js中配置打包入口文件時加入該墊片:
entry: { app: ['babel-polyfill', './scripts/app.js'] },
如今你能夠在你的代碼中使用任何你想用的ES6 API了。
到此,基本介紹瞭如何使用webpack搭建開發環境,下一篇將開始介紹如何使用webpack處理CSS及如何使用Vue進行組件化開發。