webpack工做原理:css
經過一個入口文件,main.js開始找到你的項目的全部依賴文件,使用loaders處理它們,最後打包爲一個瀏覽器可識別的JavaScript文件。html
正如js文件能夠是一個「模塊(module)」同樣,其餘的(如css、image或html)文件也可視做模 塊。所以,你能夠require('myJSfile.js')亦能夠require('myCSSfile.css')。這意味着咱們能夠將事物(業務)分割成更小的易於管理的片斷,從而達到重複利用等的目的。前端
傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。vue
最開始以前先說下:node
一、package.json文件。 這個文件是npm的說明文件,建立方式是npm init,有了package.json文件之後就能夠局部安裝webpack模塊做爲依賴包了。(安裝方式略)react
package.json文件中的scripts中是一個對象,裏面是{keyName : value}的方式,在node的環境下:npm run keyName 就能執行 value中的配置,因此這裏能夠把webpack的配置放到這裏。webpack
package.json中的腳本部分已經默認在命令前添加了node_modules/.bin
路徑,因此不管是全局仍是局部安裝的Webpack,你都不須要寫前面那指明詳細的路徑了web
二、webpack.config.js文件 一般放在項目的根目錄中,它自己也是一個標準的Commonjs規範的模塊,具體的配置項經過module.exports = {}暴露出去, vue-router
module.exports = { entry : " ", /*入口輸入項*/ output : {}, /*輸出項*/ module : {/*加載器配置*/ loaders : [ { test: / /, loader: ' ' } /*test是正則匹配的文件類型,loader是使用的加載資源loader*/ ] }, plugins : {},/*插件項*/ resolve : { /*其它解決方案配置*/ extensions : [],/*require的文件擴展名*/ alias : {},/*別名,用來縮寫*/ root : "",/*查找module的絕對根路徑*/ }, externals : {}/*項目中額外的類庫或API*/ }
各個區域的備註:typescript
一、var webpack = require('webpack');
// 不需解釋,引入webpack,之後能夠調用webpack的一些方法(需在devDependencies下安裝webpack)。
二、var path = require('path');
// 這是node下面的Path模塊(需在devDependencies下安裝path),用於處理文件路徑,由於js是前端腳本,不多去處理文件路徑的問題,這個在後端語言中很常見(需掌握)。
******path下面有4個經常使用的方法******
path.join('參數1' ,'參數2') :用路徑分隔符鏈接,它會自動識別系統,Unix系統是」/「,Windows系統是」\「。 path.join(mydir, "foo"); unix下----> 返回路徑mydir/foo
path.resolve():最終結果,取出絕對路徑。它能夠接受多個參數,依次表示所要進入的路徑,直到將最後一個參數(至關於cd進入每個參數,最後調用cwd命令)
例子1: path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile')
$ cd foo/bar $ cd /tmp/file/ $ cd .. $ cd a/../subfile $ pwd(顯示當前目錄)
例子2:path.resolve('/foo/bar', './baz') // '/foo/bar/baz'
例子3:path.resolve('/foo/bar', '/tmp/file/') // '/tmp/file'
例子4:path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif')// 若是當前目錄是/home/myself/node,返回// /home/myself/node/wwwroot/static_files/gif/image.gif
結論:是 / 開頭的絕對路徑那麼就替換成最新的 是 ./ 開頭的相對路徑就後面添加 是 ../ 開頭的回退路徑,就取消一層,最後輸出所在的全路徑名
path.relative() path.parse()略
三、process進程對象及其屬性
process對象是Node的一個全局對象,能夠在任意位置使用,沒必要經過require
命令加載。
process對象提供一系列屬性 process.cwd() process.env _ _dirname
process.cwd()
與__dirname
的區別:前者進程發起時的位置的絕對路徑(在node中表明所輸命令行上面的那一行,
後者是腳本的位置(文件原本來本處於的目錄位置),二者多是不一致的。
process.env:process.env
屬性返回一個對象,包含了當前Shell的全部環境變量,
通常這裏的作法,新建一個環境變量NODE_ENV,用它肯定當前所處的開發階段。
生產階段設爲production
,開發階段設爲development。
用法:A 腳本中讀取
process.env.NODE_ENV來肯定是哪一個階段。B 運行腳本時,設置環境變量 node命令行中:
$ NODE_ENV=production node app.js
var env = process.env.NODE_ENV env === 'development' env === 'production'
四、webpack-dev-server依賴 支持2種自動刷新的方式 ——iframe模式和inline模式,默認監聽8080端口
webpack-dev-server是一個Node.js服務器,一個小型的靜態文件服務器(須要開發者從npm自行安裝),爲經過webpack打包生成的資源文件提供Web服務。
iframe模式:在網頁中嵌入一個iframe
,將咱們本身的應用注入到這個 iframe
當中去,所以每次你修改的文件後,都是這個 iframe
進行了 reload。
訪問路徑:
localhost:8080/webpack-dev-server/index.html。 ---------- 不推薦使用
inline模式:是 webpack-dev-server
會在你的 webpack.config.js
的入口配置文件中再添加一個入口
訪問的路徑是:localhost:8080/index.html ---------- 推薦使用
inline模式又分兩種啓動命令的方式:(Node.js API命令行方式和CLI模式(cmd line)):
一、CLI模式(又分兩種寫法):
寫法a:在node窗口環境下輸入,webpack須要全局安裝,若是隻是局部安裝的話 node_modules/.bin/webpack
寫法b:在package.json文件中的script中配置,用npm run來運行webpack命令
寫法 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
其中 --hot --inline爲webpack-dev-server參數,有兩種方式傳參:
// 經過CLI傳參 webpack-dev-server --hot --inline
// 經過webpack.config.js文件的"devServer"對象 devServer: { inline: true, hot:true }
webpack-dev-server的一些經常使用選項(用於開發dev時候,pro時候不用),能夠寫成 --形式,也能夠在devServer對象中以key:value(boolean)形式來配置
// 當資源發生改變,如下三種方式都會生成新的bundle,可是又有區別: // 1. 不會刷新瀏覽器 $ webpack-dev-server //2. --inline「熱加載」功能,刷新瀏覽器 $ webpack-dev-server --inline
//3. --hot 「熱替換,嘗試從新加載組件改變的部分(而不是從新加載整個頁面) // --inline --hot 當資源改變時,webpack-dev-server將會先嚐試HRM(即熱替換),若是失敗則從新加載整個入口頁面 $ webpack-dev-server --inline --hot --color // 打包信息帶有顏色顯示 --no-colors // 關閉顏色 --quiet // 控制檯中不輸出打包的信息 --compress // 開啓gzip壓縮 --progress // 顯示打包過程當中的進度 --host // 配置主機名或IP, 0.0.0.0綁定到全部主機 --port // 配置端口號 --history-api-fallback // 是否支持HTML5歷史API撤退,若是是true,則每次跳轉都指向index.html
二、Node.js API命令行方式:
五、module.exports = { 配置項 } 配置項解析:
entry選項: webpack做用的入口文件,也就是啓動webpack時候要最早處理的文件,通常這個文件內部會引用不少其餘所依賴的模塊。
此文件內部的寫法也能夠用import引入其餘須要的模塊,好比 import Vue from 'vue'; import VueRouter from 'vue-router';。
能夠是字符串、數組或對象,
路徑:相對webpack.config.js的路徑,好比:此處的"./entry.js" 好比"./src/index.js"
路徑也能夠用path模塊下的方法來配置:entry: path.resolve(__dirname, './src/app.js'),path.resolve()方法,能夠結合咱們給定的兩個參數最後生成絕對路徑,最終指向的就是咱們
的app.js文件,此法要引入path模塊,var path = require('path');
字符串:單一入口用字符串,不過單一入口用數組和對象也是能夠的,無所謂
數組:單頁面的多入口,且彼此不互相依賴的文件,使用數組格式
對象:多頁面的多入口,有多個html文件,多處引用。如下的配置將會生成兩個js文件:indexEntry.js和profileEntry.js分別會在index.html和profile.html中被引用。。
對象的混合使用:
output選項:
output輸出文件,最終提交出去的通過合併壓縮等等一系列操做的輸出文件。
參數是個對象,定義了輸出文件的位置path及名字filename和 publishPath 屬性或者chunkFilename
path ---- 打包文件存放的絕對路徑, 若是文件目錄不存在那麼自動建立
filename ---- 打包後的文件名,(以下例子)
publishPath ---- 表明靜態資源發佈後的前綴地址,即 網站運行時的訪問路徑(主要用於生產環境靜態資源的從新配置),被許多Webpack的插件用於在生產模式下更新內嵌到css、html文件裏的url值。
chunkFilename ---- 用來打包require.ensure方法中引入的模塊,若是該方法中沒有引入任何模塊則不會生成任何chunk塊文件
注意:對於不是在require.ensure方法中引入的模塊,此屬性不會生效,只能用CommonsChunkPlugin插件來提取
filename :當咱們在entry中定義構建多個文件("./entry1", "./entry2")時,filename能夠對應的更改成[name].js,用於定義不一樣文件構建後的名字。
舉例:輸入 page2: ["./entry1", "./entry2"],輸出filename: "[name].bundle.js"
publishPath :在localhost(本地開發模式)裏的css文件中邊你可能用「./test.png」這樣的url來加載圖片,可是在生產模式下「test.png」文件可能會定位到CDN上而且你的Node.js服務器多是運行在雲平臺上邊的。這就意味着在生產環境你必須手動更新全部文件裏的url爲CDN的路徑,有了這個選項配置,就簡單多了。
下圖是利用publishPath和url-loader在生產模式編譯輸出時候更改了url的路徑(相對---->絕對)
// 開發環境:Server和圖片都是在localhost(域名)下 .image { background-image: url('./test.png'); } // 生產環境:Server部署下HeroKu可是圖片在CDN上 .image { background-image: url('https://someCDN/test.png'); }
一些output的配置項。
module選項:
loaders : [{},{},{}] 對象組成的數組
module: { loaders: [{ test: /\.js$/, // 匹配.js文件,若是經過則使用下面的loader (必選) loader: 'babel' // 使用babel(babel-loader的簡寫)做爲loader }] (必選) exclude: /node_modules/, // 排除node_modules文件夾 ,不須要處理 (可選) include: /node_modules/, // 手動添加必須處理的文件夾 (可選) query: {} // 爲loader提供額外的配置選項 (可選) }] }
test選項:
loader選項:將瀏覽器不能識別的類型,經過相應的loader模塊加載器轉換成可識別的代碼。
規則:鏈式(管道式)的加載器(從右往左執行),須要多個loader的時候,從右往左執行,且不一樣的loader之間應該用!來分割開。
可簡寫,省略-loader字段,style-loader!css-loader能夠寫成style!css
舉例:css-loader 處理css文件以及css的依賴(@import移入的css文件) style-loader 添加style標籤嵌入到html中。
因此順序就是:
query:loader自身配置項(好比:針對圖片的url配置)
配置url-loader來將小於1024字節的圖片使用DataUrl替換而 大於1024字節的圖片使用url,咱們能夠用以下兩種方式經過傳入「limit「參數來實現這一目的:
兩種方式:(用參數模式或者query模式)
/*使用?參數的方式*/ { test :/\.png$/, loader: 'url-loader?limit=1024' } /*使用query屬性*/ { test :/\.png$/, loader: 'url-loader' query:{
limit:1024
name: utils.assetsPath('img/[name].[hash:7].[ext]')
} }
特殊的:
一、babel-loader的query配置項,他能夠寫到 loader[{}]中,也能夠單出提出來寫到一個 .babelrc文件中,webpack編譯的時候會自動查找。
安裝:babel-core babel-loader babel-preset-es2015
module: { loaders: [ { test: /\.jsx?$/, exclude: /(node_modulesbower_components)/, loader: 'babel', query: { // 直接寫到loader內部 presets: ['react', 'es2015'] } } ] }
或者
//webpack.config.js 文件 無query配置項 module: { loaders: [ { test: /\.jsx?$/, exclude: /(node_modulesbower_components)/, loader: 'babel' } ] }
//.bablerc文件 { presets: ['react', 'es2015'] }
.bablere文件的其餘配置項解析
// .bablere文件的其餘配置項解析 { "presets": ["es2015", "stage-2"], // XXXXXXXXXXXXXXXXXXX "plugins": ["transform-runtime"], // XXXXXXXXXXXXXX "comments": false // XXXXXXXXXXXXXXXXXXX }
二、PostCSS 安裝postcss-loader 和 autoprefixer(自動添加前綴的插件)
直接寫在module:{}中,而不是loader:[{}]中,和loader同級的。
postcss: [module: { loaders: [ { test: /\.json$/, loader: "json" }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel' }, { test: /\.css$/, loader: 'style!css?modules!postcss' } ] },
require('autoprefixer')//調用autoprefixer插件 ],
devserver服務選項(對象):能夠參考上面的
devServer: { contentBase: "./public",//默認webpack-dev-server會爲根文件夾提供本地服務器,若是想爲另一個目錄下的文件提供本地服務器,應該在這裏設置其所在目錄(本例設置到「public"目錄) colors: true,//終端中輸出結果爲彩色 port : 8888,// 設置默認監聽端口,若是省略,默認爲」8080「 historyApiFallback: true,// 在開發單頁應用時很是有用,它依賴於HTML5 history API,若是設置爲true,全部的跳轉將指向index.html inline: true// 當源文件改變時會自動刷新頁面 }
devtool開發調試選項:
打包後的文件有時候你是不容易找到出錯了的地方對應的源代碼的位置的,Webpack在打包時能夠爲咱們生成的source maps,這爲咱們提供了一種對應編譯文件和源文件的方法。
//配置生成Source Maps,選擇合適的選項 // 在一個單獨的文件中產生一個完整且功能徹底的文件,減慢打包文件的構建速度 devtool: 'source-map', // 在一個單獨的文件中生成一個不帶列映射的map,提升項目構建速度,可是隻能對應到具體的行,不能對應到具體的列(符號) devtool: 'cheap-module-source-map', // 使用eval打包源文件模塊,在同一個文件中生成乾淨的完整的source map。這個選項能夠在不影響構建速度的前提下生成完整的sourcemap,可是對打包後輸出的JS文件的執行具備性能和安全的隱患。不過在開發階段這是一個很是好的選項,可是在生產階段必定不要用這個選項; devtool: 'eval-source-map', // 這是在打包文件時最快的生成source map的方法,生成的Source Map 會和打包後的JavaScript文件同行顯示,沒有列映射 (中小項目用) devtool: 'cheap-module-eval-source-map',
plugins插件選項(數組):用new XX()的形式。。
plugins: [ new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html" // 命名模板文件名稱爲app下的index.tmpl.html,他到時候會自動被添加自動添加所依賴的 css, js,favicon等文件 }), new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin(), new ExtractTextPlugin("[name]-[hash].css") ]
HtmlWebpackPlugin // 這個插件的做用是依據一個簡單的模板,幫你生成最終的Html5文件,這個文件中自動引用了你打包後的JS文件。每次編譯都在文件名中插入一個不一樣的哈希值。
resolve選項(對象):
externals
webpack的一些插件:
WebPack.optimize.UglifyJsPlugin (WebPack內建插件)// 代碼壓縮
WebPack.optimize.CommonsChunkPlugin(WebPack內建插件)//提取公用文件,合併到一塊兒
var HtmlWebpackPlugin = require('html-webpack-plugin'); //自動生成帶hash的HTML 文件
var ExtractTextPlugin = require("extract-text-webpack-plugin"); // 獨立樣式文件,會將全部的樣式文件打包成一個單獨的style.css
參考:http://www.jianshu.com/p/dcb28b582318